Files
Geneweb/bin/gwdiff/gwdiff.ml
2024-03-05 22:01:20 +01:00

653 lines
24 KiB
OCaml

(* Copyright (c) 2001 Ludovic LEDIEU *)
open Def
open Gwdb
(*= TODO =====================================================================
- Improve the way not to check several time the same persons.
=========================================================================== *)
let in_file1 = ref ""
let in_file2 = ref ""
let html = ref false
let root = ref ""
let cr = ref ""
(** Messages are printed when there is a difference between a person
present in the two bases explored. *)
type messages =
| MsgBadChild of iper
| MsgBirthDate
| MsgBirthPlace
| MsgChildMissing of iper
| MsgChildren of iper
| MsgDeathDate
| MsgDeathPlace
| MsgDivorce
| MsgFirstName
| MsgOccupation
| MsgParentsMissing
| MsgMarriageDate
| MsgMarriagePlace
| MsgSex
| MsgSpouseMissing of iper
| MsgSpouses of iper
| MsgSurname
(** [person_string base iper]
Returns the string associated to the person with id `iper` in the base
`base`. *)
let person_string base iper =
let p = poi base iper in
let fn = sou base (get_first_name p) in
let sn = sou base (get_surname p) in
if sn = "?" || fn = "?" then fn ^ " " ^ sn ^ " (#" ^ string_of_iper iper ^ ")"
else fn ^ "." ^ string_of_int (get_occ p) ^ " " ^ sn
(** Returns the string associated to a person in HTML if the html option is set,
otherwise it has the same effect tja, `person_string`. *)
let person_link bname base iper target =
if !html then
Printf.sprintf "<A HREF=\"%s%s_w?i=%s\" TARGET=\"%s\">%s</A>" !root bname
(string_of_iper iper) target (person_string base iper)
else person_string base iper
(** Prints a message *)
let print_message base1 msg =
Printf.printf " ";
(match msg with
| MsgBadChild iper1 ->
Printf.printf "can not isolate one child match: %s"
(person_link !in_file1 base1 iper1 "base1")
| MsgBirthDate -> Printf.printf "birth date"
| MsgBirthPlace -> Printf.printf "birth place"
| MsgChildMissing iper1 ->
Printf.printf "child missing: %s"
(person_link !in_file1 base1 iper1 "base1")
| MsgChildren iper1 ->
Printf.printf "more than one child match: %s"
(person_link !in_file1 base1 iper1 "base1")
| MsgDeathDate -> Printf.printf "death (status or date)"
| MsgDeathPlace -> Printf.printf "death place"
| MsgDivorce -> Printf.printf "divorce"
| MsgFirstName -> Printf.printf "first name"
| MsgOccupation -> Printf.printf "occupation"
| MsgParentsMissing -> Printf.printf "parents missing"
| MsgMarriageDate -> Printf.printf "marriage date"
| MsgMarriagePlace -> Printf.printf "marriage place"
| MsgSex -> Printf.printf "sex"
| MsgSpouseMissing iper1 ->
Printf.printf "spouse missing: %s"
(person_link !in_file1 base1 iper1 "base1")
| MsgSpouses iper1 ->
Printf.printf "more than one spouse match: %s"
(person_link !in_file1 base1 iper1 "base1")
| MsgSurname -> Printf.printf "surname");
Printf.printf "%s" !cr
(** Prints messages associates to the two families identifiers in argument *)
let print_f_messages base1 base2 ifam1 ifam2 res =
let f1 = foi base1 ifam1 in
let f2 = foi base2 ifam2 in
Printf.printf "%s x %s%s/ %s x %s%s"
(person_link !in_file1 base1 (get_father f1) "base1")
(person_link !in_file1 base1 (get_mother f1) "base1")
!cr
(person_link !in_file2 base2 (get_father f2) "base2")
(person_link !in_file2 base2 (get_father f2) "base2")
!cr;
List.iter (print_message base1) res
(** Same, but for persons *)
let print_p_messages base1 base2 iper1 iper2 res =
Printf.printf "%s / %s%s"
(person_link !in_file1 base1 iper1 "base1")
(person_link !in_file2 base2 iper2 "base2")
!cr;
List.iter (print_message base1) res
(** [compatible_names src_name dest_name_list]
Returns true if `src_name` is in `dest_name_list` (case insensitive) *)
let compatible_names src_name dest_name_list =
let src_name = Name.lower src_name in
let dest_name_list = List.map Name.lower dest_name_list in
List.mem src_name dest_name_list
(** [compatible_str_field istr1 istr2]
Checks the compatibility of two string identifiers, i.e.
if istr1 is not the empty string identifier, then istr2
must not be. *)
let compatible_str_field istr1 istr2 =
is_empty_string istr1 || not (is_empty_string istr2)
(** Returns a list of intervals of SDN (SDN 1 is November 25, 4714 BC Gregorian
calendar) of the date in argument. An interval has the format (b, b'),
where b is an optional lower bound (None => no bound), and b' an optional
upper bound. *)
let dmy_to_sdn_range_l dmy =
let sdn_of_dmy dmy =
let sdn = Calendar.sdn_of_gregorian dmy in
let sdn = if dmy.month = 0 || dmy.day = 0 then sdn + 1 else sdn in
let sdn2 =
if dmy.delta != 0 then sdn + dmy.delta
else
let dmy2 =
{
year =
(if dmy.month = 0 || (dmy.month = 12 && dmy.day = 0) then
dmy.year + 1
else dmy.year);
month =
(if dmy.month = 0 then 1
else if dmy.day = 0 then
if dmy.month = 12 then 1 else dmy.month + 1
else dmy.month);
day = (if dmy.day = 0 then 1 else dmy.day);
prec = (if dmy.month = 0 || dmy.day = 0 then Before else Sure);
delta = dmy.delta;
}
in
let sdn2 = Calendar.sdn_of_gregorian dmy2 in
if dmy2.prec = Before then sdn2 - 1 else sdn2
in
(sdn, sdn2)
in
(* S: calls to sdn_of_dmy dmy can be factorized *)
match dmy.prec with
| Sure ->
let sdn1, sdn2 = sdn_of_dmy dmy in
[ (Some sdn1, Some sdn2) ]
| Maybe ->
let sdn1, sdn2 = sdn_of_dmy dmy in
[ (Some sdn1, Some sdn2); (None, None) ]
| About ->
let sdn1, sdn2 = sdn_of_dmy dmy in
let delta = (sdn2 - sdn1 + 1) * 5 in
[ (Some (sdn1 - delta), Some (sdn2 + delta)) ]
| Before ->
let _sdn1, sdn2 = sdn_of_dmy dmy in
[ (None, Some sdn2) ]
| After ->
let sdn1, _sdn2 = sdn_of_dmy dmy in
[ (Some sdn1, None) ]
| OrYear dmy2 ->
let sdn11, sdn12 = sdn_of_dmy dmy in
let sdn21, sdn22 = sdn_of_dmy (Date.dmy_of_dmy2 dmy2) in
[ (Some sdn11, Some sdn12); (Some sdn21, Some sdn22) ]
| YearInt dmy2 ->
let sdn11, _sdn12 = sdn_of_dmy dmy in
let _sdn21, sdn22 = sdn_of_dmy (Date.dmy_of_dmy2 dmy2) in
[ (Some sdn11, Some sdn22) ]
(** [compatible_sdn i1 i2]
Checks if two intervals `i1` and `i2` (as described for `dmy_to_sdn_range_l`)
are compatible, i.e. if i2 is a sub interval of i1. *)
let compatible_sdn (sdn11, sdn12) (sdn21, sdn22) =
if (sdn21, sdn22) = (None, None) then true
else
(* S: Add unit argument to bool2 to make good use of OCaml laziness *)
let bool1 =
match (sdn11, sdn21) with
| Some sdn1, Some sdn2 -> sdn1 <= sdn2
| None, _ -> true
| Some _, None -> false
in
let bool2 =
match (sdn12, sdn22) with
| Some sdn1, Some sdn2 -> sdn1 >= sdn2
| None, _ -> true
| Some _, None -> false
in
bool1 && bool2
(** [compatible_sdn_l l i]
Checks if there exists an interval in `l` that is compatible with `i` *)
let compatible_sdn_l sdn1_l sdn2 =
(* S: replace by List.exists *)
List.fold_left (fun r sdn1 -> r || compatible_sdn sdn1 sdn2) false sdn1_l
(** [compatible_sdn_l l1 l2]
Checks if for all intervals `i2` in `l2`, there exists an interval `i1` in
`l1` such that `i1` is compatible with `i2` *)
let compatible_sdn_ll sdn1_l sdn2_l =
List.fold_left (fun r sdn2 -> r && compatible_sdn_l sdn1_l sdn2) true sdn2_l
(** [compatible_dmys d1 d2]
Checks if `d1` is compatible with `d2`, i.e. if despite a potential lack
of precision in the dates, d2 is more precise than d1. *)
let compatible_dmys dmy1 dmy2 =
compatible_sdn_ll (dmy_to_sdn_range_l dmy1) (dmy_to_sdn_range_l dmy2)
(** [compatible_dates date1 date2]
Same than before, but also checks the kind of date (Dgreg or Dtext)
and, in the first case, if calendars are compatible. *)
let compatible_dates date1 date2 =
let compatible_cals cal1 cal2 =
match (cal1, cal2) with
| Dgregorian, Djulian | Dgregorian, Dfrench -> true
| _ -> cal1 = cal2
in
if date1 = date2 then true
else
match (date1, date2) with
| Dgreg (dmy1, cal1), Dgreg (dmy2, cal2) ->
compatible_dmys dmy1 dmy2 && compatible_cals cal1 cal2
| Dgreg (_, _), Dtext _ -> false
| Dtext _, _ -> true
(** Same than before, but for Adef.ctype. *)
let compatible_cdates cdate1 cdate2 =
let od1 = Date.od_of_cdate cdate1 in
let od2 = Date.od_of_cdate cdate2 in
match (od1, od2) with
| Some date1, Some date2 -> compatible_dates date1 date2
| Some _, None -> false
| None, _ -> true
(** Checks if birth between two persons are compatible, i.e. if their birth date
(baptism date if birth date not provided) and place are compatible, and
returns a list of messages.
If birth is not provided, checks bathism date instead.
If birth/bathism date are not compatible, the returned list will have MsgBirthDate
If birth place are not compatible, the returned list will have MsgBirthPlace *)
let compatible_birth p1 p2 =
let get_birth person =
if person.birth = Date.cdate_None then person.baptism else person.birth
in
let birth1 = get_birth p1 in
let birth2 = get_birth p2 in
let res1 = if compatible_cdates birth1 birth2 then [] else [ MsgBirthDate ] in
let res2 =
if compatible_str_field p1.birth_place p2.birth_place then []
else [ MsgBirthPlace ]
in
res1 @ res2
(** Same than before, but for death. Messages returned are
MsgDeathDate and MsgDeathPlace *)
let compatible_death p1 p2 =
let bool1 =
p1.death = p2.death
||
match (p1.death, p2.death) with
| Death (_, cdate1), Death (_, cdate2) ->
let date1 = Date.date_of_cdate cdate1 in
let date2 = Date.date_of_cdate cdate2 in
compatible_dates date1 date2
| NotDead, _
| DeadYoung, Death (_, _)
| DeadDontKnowWhen, (Death (_, _) | DeadYoung | DeadDontKnowWhen)
| DontKnowIfDead, _ ->
true
| _ -> (* S: avoid non-exhaustive pattern matching *) false
in
let res1 = if bool1 then [] else [ MsgDeathDate ] in
let res2 =
if compatible_str_field p1.death_place p2.death_place then []
else [ MsgDeathPlace ]
in
res1 @ res2
(** [compatible_sexes p1 p2]
Returns [] if `p1` and `p2` have the same sex, [MsgSex] otherwise. *)
let compatible_sexes p1 p2 = if p1.sex = p2.sex then [] else [ MsgSex ]
(** [compatible_occupations p1 p2]
Returns [] if `p1` and `p2` have compatible occupations, [MsgOccupation] otherwise. *)
let compatible_occupations p1 p2 =
if compatible_str_field p1.occupation p2.occupation then []
else [ MsgOccupation ]
(** Checks if two persons' names are compatible wrt. their eventual aliases and returns a
list of messages.
If first names are not compatible, the returned list will have MsgFirstName.
If surnames are not compatible, the returned list will have MsgSurname. *)
let compatible_persons_ligth base1 base2 p1 p2 =
let fn1 = sou base1 p1.first_name in
let fn2 = sou base2 p2.first_name in
let afn2 = fn2 :: List.map (sou base2) p2.first_names_aliases in
let sn1 = sou base1 p1.surname in
let sn2 = sou base2 p2.surname in
let asn2 = sn2 :: List.map (sou base2) p2.surnames_aliases in
let res1 = if compatible_names fn1 afn2 then [] else [ MsgFirstName ] in
let res2 = if compatible_names sn1 asn2 then [] else [ MsgSurname ] in
res1 @ res2
(** Checks if two persons are compatible and returns all the messages associated
to the compatiblity of their name, sex, birth, death and occupation. *)
let compatible_persons base1 base2 p1 p2 =
compatible_persons_ligth base1 base2 p1 p2
@ compatible_sexes p1 p2 @ compatible_birth p1 p2 @ compatible_death p1 p2
@ compatible_occupations p1 p2
(** [find_compatible_persons_ligth base1 base2 iper1 iper2_list]
Returns the sublist of persons of `iper2_list` that are compatible with
`iper1` (only checking names). *)
let rec find_compatible_persons_ligth base1 base2 iper1 iper2_list =
(* S: not tail recursive, could be *)
match iper2_list with
| [] -> []
| head :: rest ->
let p1 = gen_person_of_person (poi base1 iper1) in
let p2 = gen_person_of_person (poi base2 head) in
let c_rest = find_compatible_persons_ligth base1 base2 iper1 rest in
if compatible_persons_ligth base1 base2 p1 p2 = [] then head :: c_rest
else c_rest
(** Same than before, but with full compatibility ( name, sex, birth, death and
occupation) *)
let rec find_compatible_persons base1 base2 iper1 iper2_list =
match iper2_list with
| [] -> []
| head :: rest ->
let p1 = gen_person_of_person (poi base1 iper1) in
let p2 = gen_person_of_person (poi base2 head) in
let c_rest = find_compatible_persons base1 base2 iper1 rest in
if compatible_persons base1 base2 p1 p2 = [] then head :: c_rest
else c_rest
(** Checks if the spouse of the persons (whose id are in argument) are
compatible (only checking names) and returns the associated messages list. *)
let compatible_unions base1 base2 iper1 iper2 ifam1 ifam2 =
let get_spouse base iper ifam =
let f = foi base ifam in
if iper = get_father f then poi base (get_mother f)
else poi base (get_father f)
in
let spouse1 = gen_person_of_person (get_spouse base1 iper1 ifam1) in
let spouse2 = gen_person_of_person (get_spouse base2 iper2 ifam2) in
compatible_persons_ligth base1 base2 spouse1 spouse2
(** [find_compatible_unions base1 base2 iper1 iper2_list ifam1 ifam2_list]
Returns the sublist of families of `ifam2_list` whose union is compatible
(in the sense of `compatible_unions`). *)
let rec find_compatible_unions base1 base2 iper1 iper2 ifam1 ifam2_list =
match ifam2_list with
| [] -> []
| head :: rest ->
let c_rest = find_compatible_unions base1 base2 iper1 iper2 ifam1 rest in
if compatible_unions base1 base2 iper1 iper2 ifam1 head = [] then
head :: c_rest
else c_rest
(** [compatible_divorces d1 d2]
Returns true if divorces are compatible, i.e. if both divorced, then
checking date compatibility, if d1 is a divorce and d2 is not returns
false, otherwise returns true. *)
let compatible_divorces d1 d2 =
match (d1, d2) with
| Divorced cdate1, Divorced cdate2 -> compatible_cdates cdate1 cdate2
| Divorced _, _ -> false
| _ -> true
(** Checks the compatibility of marriages (mariage date, divorce
and mariage place), then print the list of messages calculated. *)
let compatible_marriages base1 base2 ifam1 ifam2 =
let f1 = gen_family_of_family (foi base1 ifam1) in
let f2 = gen_family_of_family (foi base2 ifam2) in
let res1 =
if compatible_cdates f1.marriage f2.marriage then []
else [ MsgMarriageDate ]
in
let res2 =
if compatible_divorces f1.divorce f2.divorce then [] else [ MsgDivorce ]
in
let res3 =
if compatible_str_field f1.marriage_place f2.marriage_place then []
else [ MsgMarriagePlace ]
in
let res = res1 @ res2 @ res3 in
if res = [] then () else print_f_messages base1 base2 ifam1 ifam2 res
(** Calculates the compatibility of two persons and prints the associated
messages *)
let pdiff base1 base2 iper1 iper2 =
let p1 = gen_person_of_person (poi base1 iper1) in
let p2 = gen_person_of_person (poi base2 iper2) in
let res = compatible_persons base1 base2 p1 p2 in
if res = [] then () else print_p_messages base1 base2 iper1 iper2 res
(** Calculates the compatibility of two persons' families and prints the
associated messages. *)
let compatible_parents base1 base2 iper1 iper2 =
let a1 = get_parents (poi base1 iper1) in
let a2 = get_parents (poi base2 iper2) in
match (a1, a2) with
| Some ifam1, Some ifam2 ->
let f1 = foi base1 ifam1 in
let f2 = foi base2 ifam2 in
let _ = pdiff base1 base2 (get_father f1) (get_father f2) in
let _ = pdiff base1 base2 (get_mother f1) (get_mother f2) in
compatible_marriages base1 base2 ifam1 ifam2
| None, _ -> ()
| Some _, None ->
print_p_messages base1 base2 iper1 iper2 [ MsgParentsMissing ]
(** Checks che compatibility of two persons and their families, and prints it.
This is performed recursively through their descendants *)
let rec ddiff base1 base2 iper1 iper2 d_tab =
(* S: Simplify with statement:
let ddiff iper1 iper2 = ddiff base1 base2 iper1 iper2 d_tab *)
let d_check = Gwdb.Marker.get d_tab iper1 in
if List.mem iper2 d_check then ()
else
let _ = Gwdb.Marker.set d_tab iper1 (iper2 :: d_check) in
let spouse f iper =
if iper = get_father f then get_mother f else get_father f
in
let udiff base1 base2 iper1 iper2 ifam1 ifam2 =
let fd b1 b2 ip2_list ip1 =
match find_compatible_persons_ligth b1 b2 ip1 ip2_list with
| [ ip2 ] -> ddiff base1 base2 ip1 ip2 d_tab
| [] -> print_p_messages base1 base2 iper1 iper2 [ MsgChildMissing ip1 ]
| rest_list -> (
match find_compatible_persons b1 b2 ip1 rest_list with
| [ best_ip2 ] -> ddiff base1 base2 ip1 best_ip2 d_tab
| [] -> print_p_messages base1 base2 iper1 iper2 [ MsgBadChild ip1 ]
| _ -> print_p_messages base1 base2 iper1 iper2 [ MsgChildren ip1 ])
in
let f1 = foi base1 ifam1 in
let f2 = foi base2 ifam2 in
let p1 = spouse f1 iper1 in
let p2 = spouse f2 iper2 in
let d1 = Array.to_list (get_children (foi base1 ifam1)) in
let d2 = Array.to_list (get_children (foi base2 ifam2)) in
pdiff base1 base2 p1 p2;
List.iter (fd base1 base2 d2) d1
in
let fu b1 b2 ifam2_list ifam1 =
match find_compatible_unions b1 b2 iper1 iper2 ifam1 ifam2_list with
| [ ifam2 ] ->
compatible_marriages b1 b2 ifam1 ifam2;
compatible_parents b1 b2
(spouse (foi base1 ifam1) iper1)
(spouse (foi base2 ifam2) iper2);
udiff b1 b2 iper1 iper2 ifam1 ifam2
| [] ->
print_p_messages base1 base2 iper1 iper2
[ MsgSpouseMissing (spouse (foi base1 ifam1) iper1) ]
| _ ->
print_p_messages base1 base2 iper1 iper2
[ MsgSpouses (spouse (foi base1 ifam1) iper1) ]
in
let u1 = Array.to_list (get_family (poi base1 iper1)) in
let u2 = Array.to_list (get_family (poi base2 iper2)) in
pdiff base1 base2 iper1 iper2;
List.iter (fu base1 base2 u2) u1
(** Returns the eldest persons on the base starting from the persons in argument. *)
let rec find_top base1 base2 iper1 iper2 =
let p1 = gen_person_of_person (poi base1 iper1) in
let p2 = gen_person_of_person (poi base2 iper2) in
if compatible_persons_ligth base1 base2 p1 p2 = [] then
let a1 = get_parents (poi base1 iper1) in
let a2 = get_parents (poi base2 iper2) in
match (a1, a2) with
| Some ifam1, Some ifam2 ->
let f1 = foi base1 ifam1 in
let f2 = foi base2 ifam2 in
let f_top_list = find_top base1 base2 (get_father f1) (get_father f2) in
let m_top_list = find_top base1 base2 (get_mother f1) (get_mother f2) in
f_top_list @ m_top_list
| _ -> [ (iper1, iper2) ]
else (
Printf.printf " Warning: %s doesn't match %s%s"
(person_link !in_file1 base1 iper1 "base1")
(person_link !in_file2 base2 iper2 "base2")
!cr;
[])
(** Same than ddiff, but starting from the eldest ancestors from the persons in argument *)
let addiff base1 base2 iper1 iper2 d_tab =
let topdiff (iper1, iper2) =
Printf.printf "==> %s / %s%s"
(person_link !in_file1 base1 iper1 "base1")
(person_link !in_file2 base2 iper2 "base2")
!cr;
ddiff base1 base2 iper1 iper2 d_tab
in
Printf.printf "Building top list...%s" !cr;
let top_list = find_top base1 base2 iper1 iper2 in
Printf.printf "Top list built.%s" !cr;
List.iter topdiff top_list
(* Main *)
let gwdiff base1 base2 iper1 iper2 d_mode ad_mode =
let desc_tab = Gwdb.iper_marker (Gwdb.ipers base1) [] in
match (d_mode, ad_mode) with
| true, _ | false, false -> ddiff base1 base2 iper1 iper2 desc_tab
| false, true -> addiff base1 base2 iper1 iper2 desc_tab
let p1_fn = ref ""
let p1_occ = ref 0
let p1_sn = ref ""
let p2_fn = ref ""
let p2_occ = ref 0
let p2_sn = ref ""
type arg_state = ASnone | ASwaitP1occ | ASwaitP1sn | ASwaitP2occ | ASwaitP2sn
let arg_state = ref ASnone
let mem = ref false
let d_mode = ref false
let ad_mode = ref false
let speclist =
[
( "-1",
Arg.String
(fun s ->
p1_fn := s;
arg_state := ASwaitP1occ),
"<fn> <occ> <sn> : (mandatory) defines starting person in base1" );
( "-2",
Arg.String
(fun s ->
p2_fn := s;
arg_state := ASwaitP2occ),
"<fn> <occ> <sn> : (mandatory) defines starting person in base2" );
("-ad", Arg.Set ad_mode, ": checks descendants of all ascendants ");
("-d", Arg.Set d_mode, ": checks descendants (default)");
( "-html",
Arg.String
(fun s ->
html := true;
root := s),
"<root>: HTML format used for report" );
("-mem", Arg.Set mem, ": save memory space, but slower");
]
let anonfun s =
match !arg_state with
| ASnone ->
if !in_file1 = "" then in_file1 := s
else if !in_file2 = "" then in_file2 := s
else raise (Arg.Bad "Too much arguments")
| ASwaitP1occ -> (
try
p1_occ := int_of_string s;
arg_state := ASwaitP1sn
with Failure _ -> raise (Arg.Bad "Numeric value for occ (-1)!"))
| ASwaitP1sn ->
p1_sn := s;
arg_state := ASnone
| ASwaitP2occ -> (
try
p2_occ := int_of_string s;
arg_state := ASwaitP2sn
with Failure _ -> raise (Arg.Bad "Numeric value for occ (-2)!"))
| ASwaitP2sn ->
p2_sn := s;
arg_state := ASnone
let errmsg = "Usage: " ^ Sys.argv.(0) ^ " [options] base1 base2\nOptions are: "
let check_args () =
Arg.parse speclist anonfun errmsg;
if !in_file1 = "" then (
Printf.printf "Missing reference data base\n";
Printf.printf "Use option -help for usage\n";
flush stdout;
exit 2);
if !in_file2 = "" then (
Printf.printf "Missing destination data base\n";
Printf.printf "Use option -help for usage\n";
flush stdout;
exit 2);
if !p1_fn = "" then (
Printf.printf "-1 parameter is mandatory\n";
Printf.printf "Use option -help for usage\n";
flush stdout;
exit 2);
if !p1_sn = "" then (
Printf.printf "Incomplete -1 parameter\n";
Printf.printf "Use option -help for usage\n";
flush stdout;
exit 2);
if !p2_fn = "" then (
Printf.printf "-2 parameter is mandatory\n";
Printf.printf "Use option -help for usage\n";
flush stdout;
exit 2);
if !p2_sn = "" then (
Printf.printf "Incomplete -2 parameter\n";
Printf.printf "Use option -help for usage\n";
flush stdout;
exit 2)
let main () =
let _ = check_args () in
let _ = if not !html then cr := "\n" else cr := "<BR>\n" in
let load_base file =
let base = open_base file in
let () = load_ascends_array base in
let () = load_strings_array base in
let () =
if not !mem then
let () = load_unions_array base in
let () = load_couples_array base in
let () = load_descends_array base in
()
in
base
in
(* Reference base *)
let base1 = load_base !in_file1 in
(* Destination base *)
let base2 = if !in_file1 != !in_file2 then load_base !in_file2 else base1 in
let iper1 = person_of_key base1 !p1_fn !p1_sn !p1_occ in
let iper2 = person_of_key base2 !p2_fn !p2_sn !p2_occ in
if !html then Printf.printf "<BODY>\n";
(match (iper1, iper2) with
| None, _ ->
Printf.printf "Cannot find person %s.%d %s in reference base" !p1_fn
!p1_occ !p1_sn
| _, None ->
Printf.printf "Cannot find person %s.%d %s in destination base" !p2_fn
!p2_occ !p2_sn
| Some iper1, Some iper2 -> gwdiff base1 base2 iper1 iper2 !d_mode !ad_mode);
if !html then Printf.printf "</BODY>\n"
let _ = Printexc.print main ()