/* utilities - basic utility functions */
/* XLISP-STAT 2.1 Copyright (c) 1990, by Luke Tierney */
/* Additions to Xlisp 2.1, Copyright (c) 1989 by David Michael Betz */
/* You may give out copies of this software; for conditions see the */
/* file COPYING included with this distribution. */
/****** ///// clean this stuff up */
#include "xlisp.h"
#include "xlstat.h"
typedef LVAL (*subrfun)(V);
/************************************************************************/
/** Basic Utilities **/
/************************************************************************/
/* return list of two elements */
LVAL list2 P2C(LVAL, x1, LVAL, x2)
{
LVAL list, y1, y2;
/* protect some pointers */
xlstkcheck(3);
xlsave(list);
xlsave(y1);
xlsave(y2);
y1 = x1;
y2 = x2;
list = consa(y2);
list = cons(y1, list);
/* restore the stack frame */
xlpopn(3);
return(list);
}
/* return list of three elements */
LVAL list3 P3C(LVAL, x1, LVAL, x2, LVAL, x3)
{
LVAL list, y1, y2, y3;
/* protect some pointers */
xlstkcheck(4);
xlsave(list);
xlsave(y1);
xlsave(y2);
xlsave(y3);
y1 = x1;
y2 = x2;
y3 = x3;
list = consa(y3);
list = cons(y2, list);
list = cons(y1, list);
/* restore the stack frame */
xlpopn(4);
return(list);
}
/* return the i-th argument, without popping it; signal an error if needed. */
LVAL peekarg P1C(int, i)
{
if (xlargc <= i) xltoofew();
return(xlargv[i]);
}
/* Get the next element in the sequence; cdr the pointer if it is a list */
LVAL getnextelement P2C(LVAL *, pseq, int, i)
{
LVAL value;
switch (ntype(*pseq)) {
case VECTOR:
value = getelement(*pseq, i);
break;
case TVEC:
case STRING:
value = gettvecelement(*pseq, i);
break;
case CONS:
value = car(*pseq);
*pseq = cdr(*pseq);
break;
default:
xlbadtype(*pseq);
value = NIL;
}
return(value);
}
/* Set the next element in the sequence; cdr the pointer if it is a list */
VOID setnextelement P3C(LVAL *, pseq, int, i, LVAL, value)
{
switch (ntype(*pseq)) {
case VECTOR:
setelement(*pseq, i, value);
break;
case TVEC:
case STRING:
settvecelement(*pseq, i, value);
break;
case CONS:
rplaca(*pseq, value);
*pseq = cdr(*pseq);
break;
default:
xlbadtype(*pseq);
}
}
/************************************************************************/
/** Function Applicaiton Utilities **/
/************************************************************************/
VOID pushargvec P3C(LVAL, fun, int, argc, LVAL *, argv)
{
LVAL *newfp, *oldsp;
int i;
/* build a new argument stack frame */
newfp = oldsp = xlsp;
pusharg(NIL); /* place holder for stack frame increment */
pusharg(fun);
pusharg(NIL); /* place holder for argc */
/* push the arguments */
for (i = 0; i < argc; i++)
pusharg(argv[i]);
/* establish the new stack frame */
oldsp[0] = cvfixnum((FIXTYPE)(newfp - xlfp));
oldsp[2] = cvfixnum((FIXTYPE) argc);
xlfp = newfp;
}
LVAL xsapplysubr P2C(subrfun, f, LVAL, args)
{
LVAL *oldargv, val;
int argc, oldargc;
xlprot1(args); /* protect arguments while pushing */
argc = pushargs(NIL, args);
xlpop(); /* now they are protected since they are on the stack */
oldargc = xlargc;
oldargv = xlargv;
xlargc = argc;
xlargv = xlfp + 3;
val = (*f)();
xlargc = oldargc;
xlargv = oldargv;
/* remove the call frame */
xlsp = xlfp;
xlfp = xlfp - (int)getfixnum(*xlfp);
return(val);
}
LVAL xscallsubrvec P3C(subrfun, f, int, argc, LVAL *, argv)
{
LVAL *oldargv, val;
int oldargc;
pushargvec(NIL, argc, argv);
oldargc = xlargc;
oldargv = xlargv;
xlargc = argc;
xlargv = xlfp + 3;
val = (*f)();
xlargc = oldargc;
xlargv = oldargv;
/* remove the call frame */
xlsp = xlfp;
xlfp = xlfp - (int)getfixnum(*xlfp);
return(val);
}
LVAL xsfuncall0 P1C(LVAL, fun)
{
pushargvec(fun, 0, NULL);
return(xlapply(0));
}
LVAL xsfuncall1 P2C(LVAL, fun, LVAL, x)
{
pushargvec(fun, 1, &x);
return(xlapply(1));
}
LVAL xsfuncall2 P3C(LVAL, fun, LVAL, x, LVAL, y)
{
LVAL args[2];
args[0] = x;
args[1] = y;
pushargvec(fun, 2, args);
return(xlapply(2));
}
/* replicates a list n times */
int xsboolkey P2C(LVAL, key, int, dflt)
{
LVAL val;
int result = dflt;
if (xlgetkeyarg(key, &val)) result = ((val != NIL) ? TRUE : FALSE);
return(result);
}
syntax highlighted by Code2HTML, v. 0.9.1