home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CP/M
/
CPM_CDROM.iso
/
cpm
/
languags
/
xlisp
/
xlisp11.ark
/
XLSUBR.C
< prev
Wrap
Text File
|
1986-10-12
|
12KB
|
538 lines
/* xlsubr - xlisp builtin functions */
#ifdef AZTEC
#include "a:stdio.h"
#else
#include <stdio.h>
#endif
#include "xlisp.h"
/* external variables */
extern int (*xlgetc)();
extern struct node *xlstack;
/* local variables */
static char *sgetptr;
/* xlsubr - define a builtin function */
xlsubr(sname,subr)
char *sname; struct node *(*subr)();
{
struct node *sym;
/* enter the symbol */
sym = xlenter(sname);
/* initialize the value */
sym->n_symvalue = newnode(SUBR);
sym->n_symvalue->n_subr = subr;
}
/* xlsvar - define a builtin string variable */
xlsvar(sname,str)
char *sname,*str;
{
struct node *sym;
/* enter the symbol */
sym = xlenter(sname);
/* initialize the value */
sym->n_symvalue = newnode(STR);
sym->n_symvalue->n_str = strsave(str);
}
/* xlarg - get the next argument */
struct node *xlarg(pargs)
struct node **pargs;
{
struct node *arg;
/* make sure the argument exists */
if (*pargs == NULL)
xlfail("too few arguments");
/* get the argument value */
arg = (*pargs)->n_listvalue;
/* move the argument pointer ahead */
*pargs = (*pargs)->n_listnext;
/* return the argument */
return (arg);
}
/* xlmatch - get an argument and match its type */
struct node *xlmatch(type,pargs)
int type; struct node **pargs;
{
struct node *arg;
/* get the argument */
arg = xlarg(pargs);
/* check its type */
if (type == LIST) {
if (arg != NULL && arg->n_type != LIST)
xlfail("bad argument type");
}
else {
if (arg == NULL || arg->n_type != type)
xlfail("bad argument type");
}
/* return the argument */
return (arg);
}
/* xlevarg - get the next argument and evaluate it */
struct node *xlevarg(pargs)
struct node **pargs;
{
struct node *oldstk,val;
/* create a new stack frame */
oldstk = xlsave(&val,NULL);
/* get the argument */
val.n_ptr = xlarg(pargs);
/* evaluate the argument */
val.n_ptr = xleval(val.n_ptr);
/* restore the previous stack frame */
xlstack = oldstk;
/* return the argument */
return (val.n_ptr);
}
/* xlevmatch - get an evaluated argument and match its type */
struct node *xlevmatch(type,pargs)
int type; struct node **pargs;
{
struct node *arg;
/* get the argument */
arg = xlevarg(pargs);
/* check its type */
if (type == LIST) {
if (arg != NULL && arg->n_type != LIST)
xlfail("bad argument type");
}
else {
if (arg == NULL || arg->n_type != type)
xlfail("bad argument type");
}
/* return the argument */
return (arg);
}
/* xllastarg - make sure the remainder of the argument list is empty */
xllastarg(args)
struct node *args;
{
if (args != NULL)
xlfail("too many arguments");
}
/* assign - assign a value to a symbol */
static assign(sym,val)
struct node *sym,*val;
{
struct node *lptr;
/* check for a current object */
if ((lptr = xlobsym(sym)) != NULL)
lptr->n_listvalue = val;
else
sym->n_symvalue = val;
}
/* set - builtin function set */
static struct node *set(args)
struct node *args;
{
struct node *oldstk,arg,sym,val;
/* create a new stack frame */
oldstk = xlsave(&arg,&sym,&val,NULL);
/* initialize */
arg.n_ptr = args;
/* get the symbol */
sym.n_ptr = xlevmatch(SYM,&arg.n_ptr);
/* get the new value */
val.n_ptr = xlevarg(&arg.n_ptr);
/* make sure there aren't any more arguments */
xllastarg(arg.n_ptr);
/* assign the symbol the value of argument 2 and the return value */
assign(sym.n_ptr,val.n_ptr);
/* restore the previous stack frame */
xlstack = oldstk;
/* return the result value */
return (val.n_ptr);
}
/* setq - builtin function setq */
static struct node *setq(args)
struct node *args;
{
struct node *oldstk,arg,sym,val;
/* create a new stack frame */
oldstk = xlsave(&arg,&sym,&val,NULL);
/* initialize */
arg.n_ptr = args;
/* get the symbol */
sym.n_ptr = xlmatch(SYM,&arg.n_ptr);
/* get the new value */
val.n_ptr = xlevarg(&arg.n_ptr);
/* make sure there aren't any more arguments */
xllastarg(arg.n_ptr);
/* assign the symbol the value of argument 2 and the return value */
assign(sym.n_ptr,val.n_ptr);
/* restore the previous stack frame */
xlstack = oldstk;
/* return the result value */
return (val.n_ptr);
}
/* load - direct input from a file */
static struct node *load(args)
struct node *args;
{
struct node *fname;
/* get the file name */
fname = xlevmatch(STR,&args);
/* make sure there aren't any more arguments */
xllastarg(args);
/* direct input from the file */
xlfin(fname->n_str);
/* return the filename */
return (fname);
}
/* defun - builtin function defun */
static struct node *defun(args)
struct node *args;
{
struct node *oldstk,arg,sym,fargs,fun;
/* create a new stack frame */
oldstk = xlsave(&arg,&sym,&fargs,&fun,NULL);
/* initialize */
arg.n_ptr = args;
/* get the function symbol */
sym.n_ptr = xlmatch(SYM,&arg.n_ptr);
/* get the formal argument list */
fargs.n_ptr = xlmatch(LIST,&arg.n_ptr);
/* create a new function definition */
fun.n_ptr = newnode(LIST);
fun.n_ptr->n_listvalue = fargs.n_ptr;
fun.n_ptr->n_listnext = arg.n_ptr;
/* make the symbol point to a new function definition */
assign(sym.n_ptr,fun.n_ptr);
/* restore the previous stack frame */
xlstack = oldstk;
/* return the function symbol */
return (sym.n_ptr);
}
/* sgetc - get a character from a string */
static int sgetc()
{
if (*sgetptr == 0)
return (-1);
else
return (*sgetptr++);
}
/* read - read an expression */
static struct node *read(args)
struct node *args;
{
struct node *val;
int (*oldgetc)();
/* save the old input stream */
oldgetc = xlgetc;
/* get the string or file pointer */
if (args != NULL) {
sgetptr = xlevmatch(STR,&args)->n_str;
xlgetc = sgetc;
}
/* make sure there aren't any more arguments */
xllastarg(args);
/* read an expression */
val = xlread();
/* restore the old input stream */
xlgetc = oldgetc;
/* return the expression read */
return (val);
}
/* fwhile - builtin function while */
static struct node *fwhile(args)
struct node *args;
{
struct node *oldstk,farg,arg,*val;
/* create a new stack frame */
oldstk = xlsave(&farg,&arg,NULL);
/* initialize */
farg.n_ptr = arg.n_ptr = args;
/* loop until test fails */
val = NULL;
for (; TRUE; arg.n_ptr = farg.n_ptr) {
/* evaluate the test expression */
if (!testvalue(xlevarg(&arg.n_ptr)))
break;
/* evaluate each remaining argument */
while (arg.n_ptr != NULL)
val = xlevarg(&arg.n_ptr);
}
/* restore the previous stack frame */
xlstack = oldstk;
/* return the last test expression value */
return (val);
}
/* frepeat - builtin function repeat */
static struct node *frepeat(args)
struct node *args;
{
struct node *oldstk,farg,arg,*val;
int cnt;
/* create a new stack frame */
oldstk = xlsave(&farg,&arg,NULL);
/* initialize */
arg.n_ptr = args;
/* evaluate the repeat count */
cnt = xlevmatch(INT,&arg.n_ptr)->n_int;
/* save the first expression to repeat */
farg.n_ptr = arg.n_ptr;
/* loop until test fails */
val = NULL;
for (; cnt > 0; cnt--) {
/* evaluate each remaining argument */
while (arg.n_ptr != NULL)
val = xlevarg(&arg.n_ptr);
/* restore pointer to first expression */
arg.n_ptr = farg.n_ptr;
}
/* restore the previous stack frame */
xlstack = oldstk;
/* return the last test expression value */
return (val);
}
/* foreach - builtin function foreach */
static struct node *foreach(args)
struct node *args;
{
struct node *oldstk,arg,sym,list,code,oldbnd,*val;
/* create a new stack frame */
oldstk = xlsave(&arg,&sym,&list,&code,&oldbnd,NULL);
/* initialize */
arg.n_ptr = args;
/* get the symbol to bind to each list element */
sym.n_ptr = xlmatch(SYM,&arg.n_ptr);
/* save the old binding of the symbol */
oldbnd.n_ptr = sym.n_ptr->n_symvalue;
/* get the list to iterate over */
list.n_ptr = xlevmatch(LIST,&arg.n_ptr);
/* save the pointer to the code */
code.n_ptr = arg.n_ptr;
/* loop until test fails */
val = NULL;
while (list.n_ptr != NULL) {
/* check the node type */
if (list.n_ptr->n_type != LIST)
xlfail("bad node type in list");
/* bind the symbol to the list element */
sym.n_ptr->n_symvalue = list.n_ptr->n_listvalue;
/* evaluate each remaining argument */
while (arg.n_ptr != NULL)
val = xlevarg(&arg.n_ptr);
/* point to the next list element */
list.n_ptr = list.n_ptr->n_listnext;
/* restore the pointer to the code */
arg.n_ptr = code.n_ptr;
}
/* restore the previous stack frame */
xlstack = oldstk;
/* restore the old binding of the symbol */
sym.n_ptr->n_symvalue = oldbnd.n_ptr;
/* return the last test expression value */
return (val);
}
/* fif - builtin function if */
static struct node *fif(args)
struct node *args;
{
struct node *oldstk,arg,testexpr,thenexpr,elseexpr,*val;
int dothen;
/* create a new stack frame */
oldstk = xlsave(&arg,&testexpr,&thenexpr,&elseexpr,NULL);
/* initialize */
arg.n_ptr = args;
/* evaluate the test expression */
testexpr.n_ptr = xlevarg(&arg.n_ptr);
/* get the then clause */
thenexpr.n_ptr = xlmatch(LIST,&arg.n_ptr);
/* get the else clause */
if (arg.n_ptr != NULL)
elseexpr.n_ptr = xlmatch(LIST,&arg.n_ptr);
else
elseexpr.n_ptr = NULL;
/* make sure there aren't any more arguments */
xllastarg(arg.n_ptr);
/* figure out which expression to evaluate */
dothen = testvalue(testexpr.n_ptr);
/* default the result value to the value of the test expression */
val = testexpr.n_ptr;
/* evaluate the appropriate clause */
if (dothen)
while (thenexpr.n_ptr != NULL)
val = xlevarg(&thenexpr.n_ptr);
else
while (elseexpr.n_ptr != NULL)
val = xlevarg(&elseexpr.n_ptr);
/* restore the previous stack frame */
xlstack = oldstk;
/* return the last value */
return (val);
}
/* quote - builtin function to quote an expression */
static struct node *quote(args)
struct node *args;
{
/* make sure there is exactly one argument */
if (args == NULL || args->n_listnext != NULL)
xlfail("incorrect number of arguments");
/* return the quoted expression */
return (args->n_listvalue);
}
/* fexit - get out of xlisp */
fexit()
{
exit();
}
/* testvalue - test a value for true or false */
static int testvalue(val)
struct node *val;
{
/* check for a nil value */
if (val == NULL)
return (FALSE);
/* check the value type */
switch (val->n_type) {
case INT:
return (val->n_int != 0);
case STR:
return (strlen(val->n_str) != 0);
default:
return (TRUE);
}
}
/* xlinit - xlisp initialization routine */
xlinit()
{
/* enter a copyright notice into the oblist */
xlenter("Copyright-1983-by-David-Betz");
/* enter the builtin functions */
xlsubr("set",set);
xlsubr("setq",setq);
xlsubr("load",load);
xlsubr("read",read);
xlsubr("quote",quote);
xlsubr("while",fwhile);
xlsubr("repeat",frepeat);
xlsubr("foreach",foreach);
xlsubr("defun",defun);
xlsubr("if",fif);
xlsubr("exit",fexit);
}