/*=============================== * valid_fam_tree -- Validate FAM tree * fam1, [IN] family to validate * pmsg: [OUT] error message, if any * fam0: [IN] family to match - may be NULL * Should be replaced by valid_fam(RECORD,...) ? *=============================*/ BOOLEAN valid_fam_tree (NODE fam1, STRING *pmsg, NODE fam0) { NODE refn0, husb0, wife0, chil0, body0; NODE refn1, husb1, wife1, chil1, body1; if (!fam1) { *pmsg = _(qSbademp); return FALSE; } if (nestr("FAM", ntag(fam1))) { *pmsg = _(qSbadfm0); return FALSE; } if (nsibling(fam1)) { *pmsg = _(qSbadmul); return FALSE; } refn0 = husb0 = wife0 = chil0 = body0 = NULL; if (fam0) split_fam(fam0, &refn0, &husb0, &wife0, &chil0, &body0); split_fam(fam1, &refn1, &husb1, &wife1, &chil1, &body1); if (fam0 && !iso_nodes(fam1, fam0, FALSE, TRUE)) { *pmsg = _(qSbadfam); goto bad3; } if (!iso_nodes(husb1, husb0, FALSE, TRUE)) { *pmsg = _(qSbadhsb); goto bad3; } if (!iso_nodes(wife1, wife0, FALSE, TRUE)) { *pmsg = _(qSbadwif); goto bad3; } if (!iso_nodes(chil1, chil0, FALSE, TRUE)) { *pmsg = _(qSbadchl); goto bad3; } if (fam0) join_fam(fam0, refn0, husb0, wife0, chil0, body0); join_fam(fam1, refn1, husb1, wife1, chil1, body1); return TRUE; bad3: if (fam0) join_fam(fam0, refn0, husb0, wife0, chil0, body0); join_fam(fam1, refn1, husb1, wife1, chil1, body1); return FALSE; }
/*===================================== * write_fam_to_file -- write node tree into GEDCOM * (no user interaction) *===================================*/ static void write_fam_to_file (NODE fam, CNSTRING file) { FILE *fp; XLAT ttmo = transl_get_predefined_xlat(MINED); NODE refn, husb, wife, chil, body; ASSERT(fp = fopen(file, LLWRITETEXT)); prefix_file(fp, ttmo); split_fam(fam, &refn, &husb, &wife, &chil, &body); write_nodes(0, fp, ttmo, fam, TRUE, TRUE, TRUE); write_nodes(1, fp, ttmo, refn, TRUE, TRUE, TRUE); write_nodes(1, fp, ttmo, husb, TRUE, TRUE, TRUE); write_nodes(1, fp, ttmo, wife, TRUE, TRUE, TRUE); write_nodes(1, fp, ttmo, body, TRUE, TRUE, TRUE); write_nodes(1, fp, ttmo, chil, TRUE, TRUE, TRUE); join_fam(fam, refn, husb, wife, chil, body); fclose(fp); }
/*===================================== * process_fam -- process indi record * checking in pass 1, fixing in pass 2 *===================================*/ static void process_fam (RECORD rec) { NODE fam0, fam1; NODE fref1, husb1, wife1, chil1, rest1; NODE node1; INT members = 0; BOOLEAN altered=FALSE; BOOLEAN needfix=FALSE; CNSTRING key = nzkey(rec); fam0 = nztop(rec); if (todo.pass==1) { fam1 = fam0; } else { fam1 = copy_node_subtree(fam0); } split_fam(fam1, &fref1, &husb1, &wife1, &chil1, &rest1); /* check refns */ for (node1 = fref1; node1; node1 = nsibling(node1)) { /* STRING refn=nval(node1); */ /* TO DO: verify that refn is in db */ } /* check husbs */ for (node1 = husb1; node1; node1 = nsibling(node1)) { STRING husbkey=rmvat(nval(node1)); NODE husb = qkey_to_indi(husbkey); members++; if (!husb) { if (todo.pass == 1) { report_error(ERR_BADHUSBREF , _("Bad HUSB reference (%s) in family %s") , husbkey, key); needfix=TRUE; } else { if (fix_bad_pointer(key, rec, node1)) { report_fix(ERR_BADHUSBREF , _("Fixed Bad HUSB reference (%s) in family %s") , husbkey, key); altered=TRUE; } } } else { /* look for family (key) in husb */ if (!find_xref(key, husb, "FAMS", NULL)) { report_error(ERR_EXTRAHUSB , _("Improper HUSB (%s) in family (%s)") , husbkey, key); } } } /* check wives */ for (node1 = wife1; node1; node1 = nsibling(node1)) { STRING wifekey=rmvat(nval(node1)); NODE wife = qkey_to_indi(wifekey); members++; if (!wife) { if (todo.pass == 1) { report_error(ERR_BADWIFEREF , _("Bad wife reference (%s) in family %s") , wifekey, key); needfix=TRUE; } else { if (fix_bad_pointer(key, rec, node1)) { report_fix(ERR_BADWIFEREF , _("Fixed Bad wife reference (%s) in family %s") , printkey(wifekey), key); altered=TRUE; } } } else { /* look for family (key) in wife */ if (!find_xref(key, wife, "FAMS", NULL)) { report_error(ERR_EXTRAWIFE , _("Improper wife (%s) in family (%s)") , printkey(wifekey), key); } } } /* check children */ for (node1 = chil1; node1; node1 = nsibling(node1)) { STRING chilkey=rmvat(nval(node1)); NODE child = qkey_to_indi(chilkey); members++; if (!child) { if (todo.pass == 1) { report_error(ERR_BADCHILDREF , _("Bad child reference (%s) in family %s") , printkey(chilkey), key); needfix=TRUE; } else { if (fix_bad_pointer(key, rec, node1)) { report_fix(ERR_BADCHILDREF , _("Fixed bad child reference (%s) in family %s") , printkey(chilkey), key); altered=TRUE; } } } else { /* look for family (key) in child */ if (!find_xref(key, child, "FAMC", NULL)) { report_error(ERR_EXTRACHILD , _("Improper child: Child (%s) without FAMC reference to family (%s)") , printkey(chilkey), key); } } } join_fam(fam1, fref1, husb1, wife1, chil1, rest1); /* check for undersized family */ if (!members) { report_error(ERR_EMPTYFAM, _("Empty family (%s)"), key); } else if (members == 1) { report_error(ERR_SOLOFAM, _("Single person family (%s)"), key); } if (altered) { /* must normalize, as some lineage references may have been altered to non-lineage tags to fix broken pointers */ normalize_fam(fam1); /* write to database */ replace_fam(fam0, fam1); } else if (needfix) { enqueue_list(tofix, strsave(key)); } }