/*=============================== * 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; }
/*====================================================================== * unique_nodes -- Remove duplicates from list of nodes -- original list * is modified *====================================================================*/ NODE unique_nodes (NODE node, BOOLEAN kids) /* children matter */ { NODE node0 = node, prev, this, next; if (!node) return NULL; while (node) { prev = node; this = nsibling(node); while (this) { if (iso_nodes(node, this, kids, FALSE)) { nsibling(prev) = next = nsibling(this); nsibling(this) = NULL; free_nodes(this); this = next; } else { prev = this; this = nsibling(this); } } node = nsibling(node); } return node0; }
/*======================================================================== * difference_nodes -- Return difference of two node lists -- all in node1 * that are not in node2 * UNUSED CODE *======================================================================*/ NODE difference_nodes (NODE node1, NODE node2, BOOLEAN kids) /* children matter */ { NODE prev1, next1, curs1, curs2; node1 = copy_nodes(node1, TRUE, TRUE); prev1 = NULL; curs1 = node1; while (curs1) { curs2 = node2; while (curs2 && !iso_nodes(curs1, curs2, kids, FALSE)) curs2 = nsibling(curs2); if (curs2) { next1 = nsibling(curs1); nsibling(curs1) = NULL; free_nodes(curs1); if (!prev1) node1 = next1; else nsibling(prev1) = next1; curs1 = next1; } else { prev1 = curs1; curs1 = nsibling(curs1); } } return node1; }
/*========================================================= * intersect_nodes -- Return intersection of two node trees * UNUSED CODE *=======================================================*/ NODE intersect_nodes (NODE node1, NODE node2, BOOLEAN kids) /* children matter */ { NODE prev1, curs1, next1, prev2, curs2, next2; NODE node3, curs3; if (!node1 || !node2) return NULL; node1 = copy_nodes(node1, TRUE, TRUE); node2 = copy_nodes(node2, TRUE, TRUE); node3 = curs3 = NULL; prev1 = NULL; curs1 = node1; while (curs1) { prev2 = NULL; curs2 = node2; while (curs2 && !iso_nodes(curs1, curs2, kids, FALSE)) { prev2 = curs2; curs2 = nsibling(curs2); } if (curs2) { next2 = nsibling(curs2); nsibling(curs2) = NULL; if (node3) curs3 = nsibling(curs3) = curs2; else node3 = curs3 = curs2; if (prev2) nsibling(prev2) = next2; else node2 = next2; next1 = nsibling(curs1); nsibling(curs1) = NULL; free_nodes(curs1); if (prev1) nsibling(prev1) = next1; else node1 = next1; curs1 = next1; } else { prev1 = curs1; curs1 = nsibling(curs1); } } free_nodes(node1); free_nodes(node2); return node3; }
/*============================================== * union_nodes -- Return union of two node trees *============================================*/ NODE union_nodes (NODE node1, NODE node2, BOOLEAN kids, /* children matter */ BOOLEAN copy) /* copy operands first */ { NODE curs1, next1, prev1, curs2, prev2; if (copy) node1 = copy_nodes(node1, TRUE, TRUE); if (copy) node2 = copy_nodes(node2, TRUE, TRUE); prev2 = NULL; curs2 = node2; while (curs2) { prev1 = NULL; curs1 = node1; while (curs1 && !iso_nodes(curs1, curs2, kids, FALSE)) { prev1 = curs1; curs1 = nsibling(curs1); } if (curs1) { next1 = nsibling(curs1); nsibling(curs1) = NULL; free_nodes(curs1); if (prev1) nsibling(prev1) = next1; else node1 = next1; } prev2 = curs2; curs2 = nsibling(curs2); } if (prev2) { nsibling(prev2) = node1; return node2; } return node1; }
/*=================================== * valid_indi_tree -- Validate person tree * indi1: [IN] person to validate * pmsg: [OUT] error message, if any * orig: [IN] person to match - may be NULL * rtn: FALSE for bad * Should be replaced by valid_indi(RECORD,...) ? *=================================*/ BOOLEAN valid_indi_tree (NODE indi1, STRING *pmsg, NODE orig) { NODE name1, refn1, sex1, body1, famc1, fams1, node; NODE name0, refn0, sex0, body0, famc0, fams0; INT isex, num; STRING *keys, ukey; if (!indi1) { *pmsg = _(qSbademp); return FALSE; } if (nestr("INDI", ntag(indi1))) { *pmsg = _(qSbadin0); return FALSE; } if (nsibling(indi1)) { *pmsg = _(qSbadmul); return FALSE; } split_indi_old(indi1, &name1, &refn1, &sex1, &body1, &famc1, &fams1); if (getlloptint("RequireNames", 0) && !name1) { *pmsg = _("This person record does not have a name line."); goto bad2; } for (node = name1; node; node = nsibling(node)) { if (!valid_name(nval(node))) { *pmsg = _(qSbadenm); goto bad2; } } name0 = refn0 = sex0 = body0 = famc0 = fams0 = NULL; if (orig) split_indi_old(orig, &name0, &refn0, &sex0, &body0, &famc0, &fams0); if (orig && !iso_nodes(indi1, orig, FALSE, FALSE)) { *pmsg = _(qSbadind); goto bad1; } if (!iso_nodes(famc1, famc0, FALSE, TRUE)) { *pmsg = _(qSbadfmc); goto bad1; } if (!iso_nodes(fams1, fams0, FALSE, TRUE)) { *pmsg = _(qSbadfms); goto bad1; } isex = val_to_sex(sex0); if (!fams0) isex = SEX_UNKNOWN; if (isex != SEX_UNKNOWN && isex != val_to_sex(sex1)) { *pmsg = _(qSbadparsex); goto bad1; } ukey = (refn1 ? nval(refn1) : NULL); get_refns(ukey, &num, &keys, 'I'); if (num > 1 || (num == 1 && (!orig || nestr(keys[0], rmvat(nxref(indi1)))))) { *pmsg = _(qSbadirefn); goto bad1; } if (orig) join_indi(orig, name0, refn0, sex0, body0, famc0, fams0); join_indi(indi1, name1, refn1, sex1, body1, famc1, fams1); return TRUE; bad1: if (orig) join_indi(orig, name0, refn0, sex0, body0, famc0, fams0); bad2: join_indi(indi1, name1, refn1, sex1, body1, famc1, fams1); return FALSE; }