/*====================================== * llrpt_writeindi -- Write person to database * usage: writeindi(INDI) -> BOOLEAN *====================================*/ PVALUE llrpt_writeindi (PNODE node, SYMTAB stab, BOOLEAN *eflg) { NODE indi1; PNODE arg = iargs(node); NODE indi2 = eval_indi(arg, stab, eflg, NULL); STRING rawrec=0, msg; INT len, cnt; BOOLEAN rtn=FALSE; if (*eflg || !indi2) { prog_var_error(node, stab, arg, 0, nonind1, "writeindi"); return NULL; } /* make a copy, so we can delete it */ indi2 = copy_node_subtree(indi2); /* get existing record */ rawrec = retrieve_raw_record(rmvat(nxref(indi2)), &len); if (!rawrec) { /* TODO: What do we do here ? Are they adding a new indi ? or did they get the xref wrong ? */ goto end_writeindi; } ASSERT(indi1 = string_to_node(rawrec)); cnt = resolve_refn_links(indi2); /* validate for showstopper errors */ if (!valid_indi_tree(indi2, &msg, indi1)) { /* TODO: What to do with msg ? */ goto end_writeindi; } if (cnt > 0) { /* unresolvable refn links */ /* TODO: optional argument to make this fatal ? */ } if (equal_tree(indi1, indi2)) { /* optimization :) */ rtn = TRUE; goto end_writeindi; } if (readonly) { /* TODO: database is read only error message */ goto end_writeindi; } replace_indi(indi1, indi2); strfree(&rawrec); rtn = TRUE; end_writeindi: return create_pvalue_from_bool(rtn); }
/*===================================== * llrpt_writefam -- Write family to database * usage: writefam(FAM) -> BOOLEAN *===================================*/ PVALUE llrpt_writefam (PNODE node, SYMTAB stab, BOOLEAN *eflg) { NODE fam1; NODE fam2 = eval_fam(iargs(node), stab, eflg, NULL); STRING rawrec=0, msg; INT len, cnt; BOOLEAN rtn=FALSE; if (*eflg) return NULL; /* make a copy, so we can delete it */ fam2 = copy_node_subtree(fam2); /* get existing record */ rawrec = retrieve_raw_record(rmvat(nxref(fam2)), &len); if (!rawrec) { /* TODO: What do we do here ? Are they adding a new fam ? or did they get the xref wrong ? */ goto end_writefam; } ASSERT(fam1 = string_to_node(rawrec)); cnt = resolve_refn_links(fam2); /* validate for showstopper errors */ if (!valid_fam_tree(fam2, &msg, fam1)) { /* TODO: What to do with msg ? */ goto end_writefam; } if (cnt > 0) { /* unresolvable refn links */ /* TODO: optional argument to make this fatal ? */ } if (equal_tree(fam1, fam2)) { /* optimization :) */ rtn = TRUE; goto end_writefam; } if (readonly) { /* TODO: database is read only error message */ goto end_writefam; } replace_fam(fam1, fam2); strfree(&rawrec); rtn = TRUE; end_writefam: return create_pvalue_from_bool(rtn); }
/*================================================================= * expand_tree -- Create copy of node tree with additional link info *===============================================================*/ static NODE expand_tree (NODE root0) { NODE copy, node, sub; STRING key; static NODE root; /* root of record being edited */ LIST subs; /* list of contained records */ NODE expd; /* expanded main record - copy - our retval */ root = root0; expd = copy_nodes(root, TRUE, TRUE); subs = create_list(); traverse_nodes(expd, advedit_expand_traverse, subs); /* expand the list of records into the copied record */ FORLIST(subs, el) node = (NODE) el; #ifdef DEBUG llwprintf("in list: %s %s\n", ntag(node), nval(node)); #endif key = rmvat(nval(node)); if ((sub = nztop(key_possible_to_record(key, *key)))) { copy = copy_node_subtree(sub); nxref(node) = nxref(copy); ntag(node) = ntag(copy); nchild(node) = nchild(copy); nparent(node) = nparent(copy); /*MEMORY LEAK; MEMORY LEAK; MEMORY LEAK: node not removed (because its value and possibly xref [probably not] are still being referred to */ } ENDLIST /* Shouldn't we free subs now ? Perry 2001/06/22 */ #ifdef DEBUG show_node(expd); #endif return expd; }
/*===================================== * 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)); } }
/*===================================== * process_indi -- process indi record * checking in pass 1, fixing in pass 2 *===================================*/ static void process_indi (RECORD rec) { NODE indi0, indi1; NODE name1, refn1, sex1, body1, famc1, fams1; NODE node1; BOOLEAN altered=FALSE; BOOLEAN needfix=FALSE; CNSTRING key = nzkey(rec); indi0 = nztop(rec); if (todo.pass==1) { indi1 = indi0; } else { indi1 = copy_node_subtree(indi0); } split_indi_old(indi1, &name1, &refn1, &sex1, &body1, &famc1, &fams1); if (todo.pass == 1) { /* check names */ for (node1 = name1; node1; node1 = nsibling(node1)) { STRING name=nval(node1); if (!valid_name(name)) { report_error(ERR_BADNAME, _("Bad name for individual %s: %s"), key, name); } else { /* TO DO: verify that name is in db */ } } /* check refns */ for (node1 = refn1; node1; node1 = nsibling(node1)) { /* STRING refn=nval(node1); */ /* TO DO: verify that refn is in db */ } } /* check parents */ for (node1 = famc1; node1; node1 = nsibling(node1)) { STRING famkey=rmvat(nval(node1)); NODE fam2 = qkey_to_fam(famkey); if (!fam2) { if (todo.pass == 1) { report_error(ERR_BADFAMREF, _("Bad family reference (%s) individual %s"), famkey, key); } } else { /* look for indi1 (key) in fam2's children */ if (!find_xref(key, fam2, "CHIL", NULL)) { if (todo.pass == 1) { report_error(ERR_MISSINGCHILD, _("Missing child (%s) in family (%s)"), key, famkey); needfix=TRUE; } else { if (fix_bad_pointer(key, rec, node1)) { report_fix(ERR_MISSINGCHILD, _("Fixed missing child (%s) in family (%s)"), key, famkey); altered=TRUE; } } } } } /* check spouses */ for (node1 = fams1; node1; node1 = nsibling(node1)) { STRING famkey=rmvat(nval(node1)); NODE fam2 = qkey_to_fam(famkey); if (!fam2) { if (todo.pass == 1) { report_error(ERR_BADFAMREF, _("Bad family reference (%s) individual %s"), famkey, key); } } else { /* look for indi1 (key) in fam2's spouses */ if (!find_xref(key, fam2, "HUSB", "WIFE")) { if (todo.pass == 1) { report_error(ERR_MISSINGSPOUSE, _("Missing spouse (%s) in family (%s)"), key, famkey); needfix=TRUE; } else { if (fix_bad_pointer(key, rec, node1)) { report_fix(ERR_MISSINGSPOUSE, _("Fixed missing spouse (%s) in family (%s)"), key, famkey); altered=TRUE; } } } } } join_indi(indi1, name1, refn1, sex1, body1, famc1, fams1); if (altered) { /* must normalize, as some lineage references may have been altered to non-lineage tags to fix broken pointers */ normalize_indi(indi1); /* write to database */ replace_indi(indi0, indi1); } else if (needfix) { enqueue_list(tofix, strsave(key)); } }