Beispiel #1
0
/*================================================+
 * evaluate_cond -- Evaluate conditional expression
 *===============================================*/
BOOLEAN
evaluate_cond (PNODE node, SYMTAB stab, BOOLEAN *eflg)
{
    PVALUE val;
    BOOLEAN rc;
    PNODE var = node, expr = inext(node);
    if (!expr) {
        expr = var;
        var = NULL;
    }
    if (var && !iistype(var, IIDENT)) {
        *eflg = TRUE;
        prog_error(node, "1st arg in conditional must be variable");
        return FALSE;
    }
    val = evaluate(expr, stab, eflg);
    if (*eflg || !val) {
        *eflg = TRUE;
        prog_error(node, "error in conditional expression");
        return FALSE;
    }
#ifdef DEBUG
    llwprintf("interp_if: cond = ");
    show_pvalue(val);
    wprintf("\n");
#endif
    if (var) assign_iden(stab, iident(node), copy_pvalue(val));
    coerce_pvalue(PBOOL, val, eflg);
    rc = pvalue_to_bool(val);
    delete_pvalue(val);
    return rc;
}
Beispiel #2
0
/*======================================+
 * llrpt_newfile -- Switch output to new file
 * usage: newfile(STRING, BOOL) -> VOID
 *=====================================*/
PVALUE
llrpt_newfile (PNODE node, SYMTAB stab, BOOLEAN *eflg)
{
	PNODE argvar = builtin_args(node);
	BOOLEAN aflag=FALSE;
	STRING name=0;
	PVALUE val = eval_and_coerce(PSTRING, argvar, stab, eflg);
	if (*eflg) {
		prog_var_error(node, stab, argvar, val, nonstrx, "newfile", "1");
		delete_pvalue_ptr(&val);
		return NULL;
	}
	name = pvalue_to_string(val);
	if (!name || !name[0]) {
		*eflg = TRUE;
		prog_var_error(node, stab, argvar, val, "1st arg to newfile must be a nonempty string.");
		delete_pvalue_ptr(&val);
		return NULL;
	}
	strupdate(&outfilename, name);
	delete_pvalue_ptr(&val);
	val = eval_and_coerce(PBOOL, argvar=inext(argvar), stab, eflg);
	if (*eflg) {
		prog_var_error(node, stab, argvar, val, nonboox, "newfile", "2");
		delete_pvalue_ptr(&val);
		return NULL;
	}
	aflag = pvalue_to_bool(val);
	delete_pvalue_ptr(&val);
	if (!set_output_file(outfilename, aflag)) {
		*eflg = TRUE;
		prog_var_error(node, stab, argvar, NULL, "Failed to open output file: %s", outfilename);
	}
	return NULL;
}
Beispiel #3
0
/*===============================================+
 * llrpt_difference -- Create difference of two INDISEQs
 * usage: difference(SET, SET) -> SET
 *==============================================*/
PVALUE
llrpt_difference (PNODE node, SYMTAB stab, BOOLEAN *eflg)
{
	PNODE arg1 = builtin_args(node);
	PNODE arg2 = inext(arg1);
	INDISEQ op2=0, op1=0;
	PVALUE val1 = eval_and_coerce(PSET, arg1, stab, eflg);
	PVALUE val2=0;
	if (*eflg) {
		prog_var_error(node, stab, arg1, val1, nonsetx, "difference", "1");
		return NULL;
	}
	/* NULL indiseqs are possible, because of getindiset */
	op1 = pvalue_to_seq(val1);
	val2 = eval_and_coerce(PSET, arg2, stab, eflg);
	if (*eflg) {
		prog_var_error(node, stab, arg2, val2, nonsetx, "difference", "2");
		return NULL;
	}
	op2 = pvalue_to_seq(val2);
	/* do actual difference */
	op2 = difference_indiseq(op1, op2);
	set_pvalue_seq(val1, op2);
	/* delay to last minute lest it is a temp owning seq,
	eg, difference(ancestorset(i),ancestorset(j)) */
	delete_pvalue(val2);
	return val1;
}
Beispiel #4
0
/*=====================================
 * llrpt_createnode -- Create GEDCOM node
 * usage: createnode(STRING, STRING) -> NODE
 * args: (tag, value)
 *===================================*/
PVALUE
llrpt_createnode (PNODE node, SYMTAB stab, BOOLEAN *eflg)
{
	PNODE arg = iargs(node);
	NODE newnode=0;
	NODE prnt=NULL; /* parent node for new node */
	STRING xref=NULL; /* xref for new node */
	PVALUE val1=NULL, val2=NULL;
	STRING str1=NULL; /* 1st arg, which is tag for new node */
	STRING str2=NULL; /* 2nd arg, which is value for new node */
	val1 = eval_and_coerce(PSTRING, arg, stab, eflg);
	if (*eflg) {
		prog_var_error(node, stab, arg, val1, nonstrx, "createnode", "1");
		delete_pvalue(val1);
		return NULL;
	}
	/* 1st arg is tag for new node */
	str1 = pvalue_to_string(val1);
	val2 = eval_and_coerce(PSTRING, arg=inext(arg), stab, eflg);
	if (*eflg) {
		prog_var_error(node, stab, arg, val2, nonstrx, "createnode", "2");
		delete_pvalue(val2);
		return NULL;
	}
	/* 2nd arg is value for new node */
	str2 = pvalue_to_string(val2);
	newnode = create_temp_node(xref, str1, str2, prnt);
	return create_pvalue_from_node(newnode);
}
Beispiel #5
0
/*===========================================+
 * llrpt_deletefromset -- Remove person from INDISEQ
 * usage: deletefromset(SET, INDI, BOOL) -> VOID
 *==========================================*/
PVALUE
llrpt_deletefromset (PNODE node, SYMTAB stab, BOOLEAN *eflg)
{
	NODE indi;
	STRING key=0;
	BOOLEAN all, rc;
	INDISEQ seq;
	PNODE arg1 = builtin_args(node), arg2 = inext(arg1),
	    arg3 = inext(arg2);
	PVALUE val1 = eval_and_coerce(PSET, arg1, stab, eflg);
	PVALUE val3=0;
	if (*eflg) {
		prog_var_error(node, stab, arg1, val1, nonsetx, "deletefromset", "1");
		goto dfs_exit;
	}
	ASSERT(seq = pvalue_to_seq(val1));
	indi = eval_indi(arg2, stab, eflg, NULL);
	if (*eflg) {
		prog_var_error(node, stab, arg2, NULL, nonindx, "deletefromset", "2");
		goto dfs_exit;
	}
	if (!indi) goto dfs_exit;
	*eflg = TRUE;
	if (!(key = strsave(rmvat(nxref(indi))))) {
		prog_error(node, "major error in deletefromset.");
		goto dfs_exit;
	}
	*eflg = FALSE;
	val3 = eval_and_coerce(PBOOL, arg3, stab, eflg);
	if (*eflg) {
		prog_var_error(node, stab, arg2, NULL, nonboox, "deletefromset", "3");
		goto dfs_exit;
	}
	all = pvalue_to_bool(val3);
	delete_pvalue(val3);
	do {
		rc = delete_indiseq(seq, key, NULL, 0);
	} while (rc && all);
dfs_exit:
	/* delay delete of val1 to last minute lest it is a temp owning seq,
	    eg, deletefromset(ancestorset(i),j) */
	if (val1) delete_pvalue(val1);
	if (key) strfree(&key);
	return NULL;
}
Beispiel #6
0
/*==============================================
 * num_params -- Return number of params in list
 *============================================*/
INT
num_params (PNODE node)
{
    INT np = 0;
    while (node) {
        np++;
        node = inext(node);
    }
    return np;
}
Beispiel #7
0
/*==================================+
 * llrpt_addtoset -- Add person to INDISEQ
 * usage: addtoset(SET, INDI, ANY) -> VOID
 *=================================*/
PVALUE
llrpt_addtoset (PNODE node, SYMTAB stab, BOOLEAN *eflg)
{
	NODE indi=0;
	STRING key=0;
	INDISEQ seq=0;
	PNODE arg1 = builtin_args(node), arg2 = inext(arg1),
	    arg3 = inext(arg2);
	PVALUE val1 = eval_and_coerce(PSET, arg1, stab, eflg);
	PVALUE val2=0;
	if (*eflg) {
		prog_var_error(node, stab, arg1, val1, nonsetx, "addtoset", "1");
		return NULL;
	}
	ASSERT(seq = pvalue_to_seq(val1));
	indi = eval_indi(arg2, stab, eflg, NULL);
	if (*eflg) {
		prog_var_error(node, stab, arg2, NULL, nonindx, "addtoset","2");
		goto ats_exit;
	}
	if (!indi) goto ats_exit;
	*eflg = TRUE;
	if (!(key = strsave(rmvat(nxref(indi))))) {
		prog_error(node, "major error in addtoset.");
		goto ats_exit;
	}
	*eflg = FALSE;
	val2 = evaluate(arg3, stab, eflg);
	if (*eflg) {
		prog_error(node, "3rd arg to addtoset is in error.");
		goto ats_exit;
	}
	append_indiseq_pval(seq, key, NULL, val2, FALSE);
ats_exit:
	if (key) strfree(&key); /* append made its own copy */
	/* delay to last minute val1 cleanup lest it is a temp owning seq,
	    eg, addtoset(ancestorset(i),j) */
	if (val1) delete_pvalue(val1);
	return NULL;
}
Beispiel #8
0
/*========================================+
 * llrpt_pagemode -- Switch output to page mode
 * usage: pagemode(INT, INT) -> VOID
 *======================================*/
PVALUE
llrpt_pagemode (PNODE node, SYMTAB stab, BOOLEAN *eflg)
{
	INT cols=0, rows=0;
	PNODE argvar = builtin_args(node);
	PVALUE val = eval_and_coerce(PINT, argvar, stab, eflg);
	if (*eflg) {
		prog_var_error(node, stab, argvar, val, nonintx, "pagemode", "1");
		delete_pvalue_ptr(&val);
		return NULL;
	}
	rows = pvalue_to_int(val);
	delete_pvalue_ptr(&val);
	val = eval_and_coerce(PINT, argvar=inext(argvar), stab, eflg);
	if (*eflg) {
		prog_var_error(node, stab, argvar, val, nonintx, "pagemode", "2");
		delete_pvalue_ptr(&val);
		return NULL;
	}
	cols = pvalue_to_int(val);
	delete_pvalue_ptr(&val);
	*eflg = TRUE;
	if (!(cols >= 1 && cols <= MAXCOLS)) {
		*eflg = TRUE;
		prog_var_error(node, stab, argvar, val, badargx, "pagemode", "1");
		return NULL;
	}
	if (!(rows >= 1 && rows <= MAXROWS)) {
		*eflg = TRUE;
		prog_var_error(node, stab, argvar, val, badargx, "pagemode", "2");
		return NULL;
	}
	*eflg = FALSE;
	outputmode = PAGEMODE;
	__rows = rows;
	__cols = cols;
	if (pagebuffer) stdfree(pagebuffer);
	pagebuffer = (STRING) stdalloc(__rows*__cols);
	memset(pagebuffer, ' ', __rows*__cols);
	return NULL;
}
Beispiel #9
0
/*===============================================+
 * llrpt_pos -- Position page output to row and column
 * usage: pos(INT, INT) -> VOID
 *==============================================*/
PVALUE
llrpt_pos (PNODE node, SYMTAB stab, BOOLEAN *eflg)
{
	INT col=0, row=0;
	PNODE argvar = builtin_args(node);
	PVALUE val = eval_and_coerce(PINT, argvar, stab, eflg);
	if (*eflg) {
		prog_var_error(node, stab, argvar, val, nonintx, "pos", "1");
		delete_pvalue_ptr(&val);
		return NULL;
	}
	row = pvalue_to_int(val);
	if (row < 1 || row > __rows) {
		*eflg = TRUE;
		prog_var_error(node, stab, argvar, val, badargx, "pos", "1");
		return NULL;
	}
	delete_pvalue_ptr(&val);
	val = eval_and_coerce(PINT, argvar=inext(argvar), stab, eflg);
	if (*eflg) {
		prog_var_error(node, stab, argvar, val, nonintx, "pos", "2");
		delete_pvalue_ptr(&val);
		return NULL;
	}
	col = pvalue_to_int(val);
	if (col < 1 || col > __cols) {
		*eflg = TRUE;
		prog_var_error(node, stab, argvar, val, badargx, "pos", "2");
		return NULL;
	}
	delete_pvalue_ptr(&val);
	if (outputmode != PAGEMODE) {
		*eflg = TRUE;
		prog_var_error(node, stab, NULL, val, "pos only valid in page mode");
		return NULL;
	}
	currow = row;
	curcol = col;
	return NULL;
}
Beispiel #10
0
/*====================================+
 * llrpt_inset -- See if person is in INDISEQ
 * usage: inset(SET, INDI) -> BOOL
 *==========================================*/
PVALUE
llrpt_inset (PNODE node, SYMTAB stab, BOOLEAN *eflg)
{
	NODE indi;
	STRING key=0;
	INDISEQ seq;
	BOOLEAN rel;
	PNODE arg1 = builtin_args(node), arg2 = inext(arg1);
	PVALUE val1 = eval_and_coerce(PSET, arg1, stab, eflg);
	PVALUE valr=0;
	if (*eflg ||!val1 || !(seq = pvalue_to_seq(val1))) {
		*eflg = TRUE;
		prog_var_error(node, stab, arg1, val1, nonsetx, "inset", "1");
		goto inset_exit;
	}
	indi = eval_indi(arg2, stab, eflg, NULL);
	if (*eflg) {
		prog_var_error(node, stab, arg2, NULL, nonindx, "inset", "2");
		goto inset_exit;
	}
	if (!indi) {
		rel = FALSE;
        } else { 
		if (!(key = strsave(rmvat(nxref(indi))))) {
			*eflg = TRUE;
			prog_error(node, "major error in inset.");
			goto inset_exit;
		}
		rel = in_indiseq(seq, key);
	}
	valr = create_pvalue_from_bool(rel);
inset_exit:
	/* delay delete of val1 to last minute lest it is a temp owning seq,
	    eg, inset(ancestorset(i),j) */
	if (val1) delete_pvalue(val1);
	if (key) strfree(&key);
	return valr;
}
Beispiel #11
0
/*================================================+
 * evaluate_ufunc -- Evaluate user defined function
 *  node:   [in] parsed node of function definition
 *  stab:   [in] function's symbol table
 *  eflg:   [out] error flag
 *===============================================*/
PVALUE
evaluate_ufunc (PNODE node, SYMTAB stab, BOOLEAN *eflg)
{
    STRING procname = (STRING) iname(node);
    PNODE func, arg, parm;
    SYMTAB newstab = NULL;
    PVALUE val=NULL;
    INTERPTYPE irc;
    INT count=0;

    *eflg = TRUE;
    /* find func in local or global table */
    func = get_proc_node(procname, irptinfo(node)->functab, gfunctab, &count);
    if (!func) {
        if (!count)
            prog_error(node, _("Undefined func: %s"), procname);
        else
            prog_error(node, _("Ambiguous call to func: %s"), procname);
        goto ufunc_leave;
    }

    newstab = create_symtab_proc(procname, stab);
    arg = (PNODE) iargs(node);
    parm = (PNODE) iargs(func);
    while (arg && parm) {
        BOOLEAN eflg=TRUE;
        PVALUE value = evaluate(arg, stab, &eflg);
        if (eflg) {
            if (getlloptint("FullReportCallStack", 0) > 0)
                prog_error(node, "In user function %s()", procname);
            return INTERROR;
        }
        insert_symtab(newstab, iident(parm), value);
        arg = inext(arg);
        parm = inext(parm);
    }
    if (arg || parm) {
        prog_error(node, "``%s'': mismatched args and params\n", procname);
        goto ufunc_leave;
    }
    irc = interpret((PNODE) ibody(func), newstab, &val);
    switch (irc) {
    case INTRETURN:
    case INTOKAY:
#ifdef DEBUG
        llwprintf("Successful ufunc call -- val returned was ");
        show_pvalue(val);
        llwprintf("\n");
#endif
        *eflg = FALSE;
        goto ufunc_leave;
    case INTBREAK:
    case INTCONTINUE:
    case INTERROR:
        break;
    }
    if (getlloptint("FullReportCallStack", 0) > 0)
        prog_error(node, "In user function %s()", procname);
    *eflg = TRUE;
    delete_pvalue(val);
    val=NULL;

ufunc_leave:
    if (newstab) {
        remove_symtab(newstab);
        newstab = NULL;
    }
    return val;
}
Beispiel #12
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;
}