/*====================================== * 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); }
/*===================================== * 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)); } }