Beispiel #1
0
/*============================================
 * llrpt_detachnode -- Remove node from GEDCOM tree
 * usage: detachnode(NODE) -> VOID
 * (This is the historic deletenode)
 *==========================================*/
PVALUE
llrpt_detachnode (PNODE node, SYMTAB stab, BOOLEAN *eflg)
{
	PNODE arg = iargs(node);
	NODE dead, prnt;
	PVALUE val = eval_and_coerce(PGNODE, arg, stab, eflg);
	if (*eflg) {
		prog_var_error(node, stab, arg, val, nonnod1, "detachnode");
		delete_pvalue(val);
		return NULL;
	}
	dead = pvalue_to_node(val);
	if ((prnt = nparent(dead))) {
		NODE prev = NULL, next;
		NODE curs = nchild(prnt);
		while (curs && curs != dead) {
			prev = curs;
			curs = nsibling(curs);
		}
		ASSERT(curs); /* else broken tree: dead was not child of its parent */
		next = nsibling(dead);
		if (prev == NULL) 
			nchild(prnt) = next;
		else
			nsibling(prev) = next;
	}
	/* unparent node, but ensure its locking is only releative to new parent */
	dolock_node_in_cache(dead, FALSE);
	nparent(dead) = NULL;
	dolock_node_in_cache(dead, TRUE);
	nsibling(dead) = NULL;
	/* we don't actually delete the node, garbage collection must get it */
	return NULL;
}
Beispiel #2
0
/*========================================
 * string_to_node -- Read tree from string
 *  (modifies string -- adds 0s between lines)
 *======================================*/
NODE
string_to_node (STRING str)
{
	INT lev;
	INT lev0;
	STRING xref;
	STRING tag;
	STRING val;

	INT curlev;
	NODE root=NULL, node, curnode;
	STRING msg;
	flineno = 0;
	if (!string_to_line(&str, &lev, &xref, &tag, &val, &msg))
		goto string_to_node_fail;
	lev0 = curlev = lev;
	root = curnode = create_node(xref, tag, val, NULL);
	while (string_to_line(&str, &lev, &xref, &tag, &val, &msg)) {
		if (lev == curlev) {
			node = create_node(xref, tag, val, nparent(curnode));
			nsibling(curnode) = node;
			curnode = node;
		} else if (lev == curlev + 1) {
			node = create_node(xref, tag, val, curnode);
			nchild(curnode) = node;
			curnode = node;
			curlev = lev;
		} else if (lev < curlev) {
			if (lev < lev0) {
				llwprintf("Error: line %d: illegal level",
				    flineno);
				goto string_to_node_fail;
			}
			while (lev < curlev) {
				curnode = nparent(curnode);
				curlev--;
			}
			node = create_node(xref, tag, val, nparent(curnode));
			nsibling(curnode) = node;
			curnode = node;
		} else {
			llwprintf("Error: line %d: illegal level", flineno);
			goto string_to_node_fail;
		}
	}
	if (!msg) {
		nodechk(root, "string_to_node");
		return root;
	}
string_to_node_fail:
	free_nodes(root);
	return NULL;
}
Beispiel #3
0
/*=================================================
 * nodechk -- Check node tree to which this node belongs
 *===============================================*/
void
nodechk (NODE node, CNSTRING scope)
{
	NODE root = node;
	CNSTRING key = 0;

	if (!nodechecking) return;

	while (nparent(root)) {
		root = nparent(root);
	}
	key = nxref(node);
	check_node_recursively(root, NULL, 1, key, scope);
}
Beispiel #4
0
/*==============================================
 * check_node -- Check node (that structure is valid)
 *============================================*/
static void
check_node (NODE node, NODE parent, INT level, CNSTRING key, CNSTRING scope)
{
	if (nparent(node) != parent) {
		failreport("bad parent link", level, key, scope);
	}
	if (parent) {
		if (node->n_cel != parent->n_cel) {
			failreport("bad cel", level, key, scope);
		}
	}
}
Beispiel #5
0
/*=================================================================
 * 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;
}
Beispiel #6
0
/*==============================================================
 * next_fp_to_node -- Convert next GEDCOM record in file to tree
 *
 *  fp:   [IN]  file that holds GEDCOM record/s
 *  list: [IN]  can be list at level 0?
 *  ttm:  [IN]  character translation table
 *  pmsg: [OUT] possible error message
 *  peof: [OUT] set true if file is at end of file
 * callers should probably be converted to calling next_fp_to_record
 *============================================================*/
NODE
next_fp_to_node (FILE *fp, BOOLEAN list, XLAT ttm,
	STRING *pmsg, BOOLEAN *peof)
{
	INT curlev, bcode, rc;
	NODE root, node, curnode;
	static char scratch[100]; /*we return errors with this, keep it around*/
	*pmsg = NULL;
	*peof = FALSE;
	if (ateof) {
		ateof = *peof = TRUE;
		lahead = FALSE;
		return NULL;
	}
	if (!lahead) {
		rc = file_to_line(fp, ttm, &lev, &xref, &tag, &val, pmsg);
		if (rc == DONE) {
			ateof = *peof = TRUE;
			return NULL;
		} else if (rc == ERROR)
			return NULL;
		lahead = TRUE;
	}
	curlev = lev;
	if (curlev != lev0)  {
		*pmsg = _(qSrerwlv);
		return NULL;
	}
	root = curnode = create_node(xref, tag, val, NULL);
	bcode = OKAY;
	rc = file_to_line(fp, ttm, &lev, &xref, &tag, &val, pmsg);
	while (rc == OKAY) {
		if (lev == curlev) {
			if (lev == lev0 && !list) {
				bcode = DONE;
				break;
			}
			node = create_node(xref, tag, val, nparent(curnode));
			nsibling(curnode) = node;
			curnode = node;
		} else if (lev == curlev + 1) {
			node = create_node(xref, tag, val, curnode);
			nchild(curnode) = node;
			curnode = node;
			curlev = lev;
		} else if (lev < curlev) {
			if (lev < lev0) {
				sprintf(scratch, _(qSrerilv), flineno);
				*pmsg = scratch;
				bcode = ERROR;
				break;
			}
			if (lev == lev0 && !list) {
				bcode = DONE;
				break;
			}
			while (lev < curlev) {
				curnode = nparent(curnode);
				curlev--;
			}
			node = create_node(xref, tag, val, nparent(curnode));
			nsibling(curnode) = node;
			curnode = node;
		} else {
			sprintf(scratch, _(qSrerilv), flineno);
			*pmsg = scratch;
			bcode = ERROR;
			break;
		}
		rc = file_to_line(fp, ttm, &lev, &xref, &tag, &val, pmsg);
	}
	if (bcode == DONE) return root;
	if (bcode == ERROR || rc == ERROR) {
		free_nodes(root);
		return NULL;
	}
	lahead = FALSE;
	ateof = *peof = TRUE;
	return root;
}
Beispiel #7
0
/*=======================================
 * llrpt_addnode -- Add a node to a GEDCOM tree
 * usage: addnode(NODE, NODE, NODE) -> VOID
 * args: (node being added, parent, previous child)
 *=====================================*/
PVALUE
llrpt_addnode (PNODE node, SYMTAB stab, BOOLEAN *eflg)
{
	PNODE arg = iargs(node);
	NODE newchild, next, prnt, prev;

	/* first argument, node (must be nonnull) */
	PVALUE val = eval_and_coerce(PGNODE, arg, stab, eflg);
	if (*eflg) {
		prog_var_error(node, stab, arg, val, nonnodx, "addnode", "1");
		delete_pvalue(val);
		return NULL;
	}
	newchild = remove_node_and_delete_pvalue(&val);
	if (!newchild) {
		prog_var_error(node, stab, arg, val, nonnodx, "addnode", "1");
		return NULL;
	}

	/* second argument, parent (must be nonnull) */
	val = eval_and_coerce(PGNODE, arg=inext(arg), stab, eflg);
	if (*eflg) {
		prog_var_error(node, stab, arg, val, nonnodx, "addnode", "2");
		return NULL;
	}
	prnt = remove_node_and_delete_pvalue(&val);
	if (!prnt) {
		prog_var_error(node, stab, arg, val, nonnodx, "addnode", "2");
		return NULL;
	}

	/* third argument, prior sibling (may be null) */
	val = eval_and_coerce(PGNODE, arg=inext(arg), stab, eflg);
	if (*eflg) {
		prog_var_error(node, stab, arg, val, nonnodx, "addnode", "3");
		delete_pvalue(val);
		return NULL;
	}
	prev = remove_node_and_delete_pvalue(&val);

	if (prev) {
		/* Check that previous sibling actually is child of new parent */
		if (prnt != nparent(prev)) {
			prog_error(node, "2nd arg to addnode must be parent of 3rd arg");
			*eflg = 1;
			return NULL;
		}
	}

	/* reparent node, but ensure its locking is only relative to new parent */
	dolock_node_in_cache(newchild, FALSE);
	nparent(newchild) = prnt;
	newchild->n_cel = prnt->n_cel;
	set_temp_node(newchild, is_temp_node(prnt));
	dolock_node_in_cache(newchild, TRUE);
	if (prev == NULL) {
		next = nchild(prnt);
		nchild(prnt) = newchild;
	} else {
		next = nsibling(prev);
		nsibling(prev) = newchild;
	}
	nsibling(newchild) = next;
	return NULL;
}