+let compare_objs (v1,n1) (v2,n2) =
+ let b = compare_versions v1 v2 in
+ if b = 0 then compare_names n1 n2 else b
+
+let objs_union os1 os2 =
+ let error o = ET.EObjClash o in
+ list_union error compare_objs os1 os2
+
+let rec rev_objs_of_names v os = function
+ | [] -> os
+ | (b,n)::tl -> rev_objs_of_names v ((b,(v,n))::os) tl
+
+let obj_of_role r =
+ let n = match r.ET.n with
+ | [] -> []
+ | (_,n):: _ -> n
+ in
+ r.ET.v, n
+
+let string_of_role r =
+ string_of_obj (obj_of_role r)
+
+let compare_roles r1 r2 =
+ compare_objs (obj_of_role r1) (obj_of_role r2)
+
+let roles_union rs1 rs2 =
+ let error r = ET.ERoleClash r in
+ list_union error compare_roles rs1 rs2
+
+let exists_role_deleted v r =
+ let o = v, [] in
+ let compare r = compare_objs o (obj_of_role r) in
+ list_exists compare r
+
+let rec get_tops v = function
+ | [] -> [], []
+ | (_,r)::tl ->
+ let ds, ts = get_tops v tl in
+ if compare_versions v r.ET.v = 0 then begin
+ if r.ET.n = [] then objs_union r.ET.o ds, ts else
+ let tops = rev_objs_of_names v [] r.ET.n in
+ ds, objs_union (List.rev tops) ts
+ end else
+ ds, ts
+
+let rec match_names oi ni os ns =
+ match os, ns with
+ | _ , [] -> None
+ | [] , _ -> None
+ | (_,o)::otl,(_,n)::ntl ->
+ let b = compare_names (snd o) n in
+ if b > 0 then match_names oi (succ ni) os ntl else
+ if b < 0 then match_names (succ oi) ni otl ns else
+ Some (oi, ni)
+