garym@cognos.UUCP (Gary Murphy) (02/27/90)
Posting-number: Volume 10, Issue 91 Submitted-by: garym@cognos.UUCP (Gary Murphy) Archive-name: xlisp21/part04 #!/bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #!/bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create the files: # xlbfun.c # xlcont.c # xldbug.c # xldmem.c # xldmem.h # xleval.c # This archive created: Sun Feb 18 07:45:24 1990 # By: Gary Murphy () export PATH; PATH=/bin:$PATH echo shar: extracting "'xlbfun.c'" '(12891 characters)' if test -f 'xlbfun.c' then echo shar: over-writing existing file "'xlbfun.c'" fi sed 's/^X//' << \SHAR_EOF > 'xlbfun.c' X/* xlbfun.c - xlisp basic built-in functions */ X/* Copyright (c) 1985, by David Michael Betz X All Rights Reserved X Permission is granted for unrestricted non-commercial use */ X X#include "xlisp.h" X X/* external variables */ Xextern LVAL xlenv,xlfenv,xldenv,true; Xextern LVAL s_evalhook,s_applyhook; Xextern LVAL s_car,s_cdr,s_nth,s_get,s_svalue,s_splist,s_aref; Xextern LVAL s_lambda,s_macro; Xextern LVAL s_comma,s_comat; Xextern LVAL s_unbound; Xextern char gsprefix[]; Xextern int gsnumber; X X/* external routines */ Xextern LVAL xlxeval(); X X/* forward declarations */ XFORWARD LVAL bquote1(); XFORWARD LVAL defun(); XFORWARD LVAL makesymbol(); X X/* xeval - the built-in function 'eval' */ XLVAL xeval() X{ X LVAL expr; X X /* get the expression to evaluate */ X expr = xlgetarg(); X xllastarg(); X X /* evaluate the expression */ X return (xleval(expr)); X} X X/* xapply - the built-in function 'apply' */ XLVAL xapply() X{ X LVAL fun,arglist; X X /* get the function and argument list */ X fun = xlgetarg(); X arglist = xlgalist(); X xllastarg(); X X /* apply the function to the arguments */ X return (xlapply(pushargs(fun,arglist))); X} X X/* xfuncall - the built-in function 'funcall' */ XLVAL xfuncall() X{ X LVAL *newfp; X int argc; X X /* build a new argument stack frame */ X newfp = xlsp; X pusharg(cvfixnum((FIXTYPE)(newfp - xlfp))); X pusharg(xlgetarg()); X pusharg(NIL); /* will be argc */ X X /* push each argument */ X for (argc = 0; moreargs(); ++argc) X pusharg(nextarg()); X X /* establish the new stack frame */ X newfp[2] = cvfixnum((FIXTYPE)argc); X xlfp = newfp; X X /* apply the function to the arguments */ X return (xlapply(argc)); X} X X/* xmacroexpand - expand a macro call repeatedly */ XLVAL xmacroexpand() X{ X LVAL form; X form = xlgetarg(); X xllastarg(); X return (xlexpandmacros(form)); X} X X/* x1macroexpand - expand a macro call */ XLVAL x1macroexpand() X{ X LVAL form,fun,args; X X /* protect some pointers */ X xlstkcheck(2); X xlsave(fun); X xlsave(args); X X /* get the form */ X form = xlgetarg(); X xllastarg(); X X /* expand until the form isn't a macro call */ X if (consp(form)) { X fun = car(form); /* get the macro name */ X args = cdr(form); /* get the arguments */ X if (symbolp(fun) && fboundp(fun)) { X fun = xlgetfunction(fun); /* get the expansion function */ X macroexpand(fun,args,&form); X } X } X X /* restore the stack and return the expansion */ X xlpopn(2); X return (form); X} X X/* xatom - is this an atom? */ XLVAL xatom() X{ X LVAL arg; X arg = xlgetarg(); X xllastarg(); X return (atom(arg) ? true : NIL); X} X X/* xsymbolp - is this an symbol? */ XLVAL xsymbolp() X{ X LVAL arg; X arg = xlgetarg(); X xllastarg(); X return (arg == NIL || symbolp(arg) ? true : NIL); X} X X/* xnumberp - is this a number? */ XLVAL xnumberp() X{ X LVAL arg; X arg = xlgetarg(); X xllastarg(); X return (fixp(arg) || floatp(arg) ? true : NIL); X} X X/* xintegerp - is this an integer? */ XLVAL xintegerp() X{ X LVAL arg; X arg = xlgetarg(); X xllastarg(); X return (fixp(arg) ? true : NIL); X} X X/* xfloatp - is this a float? */ XLVAL xfloatp() X{ X LVAL arg; X arg = xlgetarg(); X xllastarg(); X return (floatp(arg) ? true : NIL); X} X X/* xcharp - is this a character? */ XLVAL xcharp() X{ X LVAL arg; X arg = xlgetarg(); X xllastarg(); X return (charp(arg) ? true : NIL); X} X X/* xstringp - is this a string? */ XLVAL xstringp() X{ X LVAL arg; X arg = xlgetarg(); X xllastarg(); X return (stringp(arg) ? true : NIL); X} X X/* xarrayp - is this an array? */ XLVAL xarrayp() X{ X LVAL arg; X arg = xlgetarg(); X xllastarg(); X return (vectorp(arg) ? true : NIL); X} X X/* xstreamp - is this a stream? */ XLVAL xstreamp() X{ X LVAL arg; X arg = xlgetarg(); X xllastarg(); X return (streamp(arg) || ustreamp(arg) ? true : NIL); X} X X/* xobjectp - is this an object? */ XLVAL xobjectp() X{ X LVAL arg; X arg = xlgetarg(); X xllastarg(); X return (objectp(arg) ? true : NIL); X} X X/* xboundp - is this a value bound to this symbol? */ XLVAL xboundp() X{ X LVAL sym; X sym = xlgasymbol(); X xllastarg(); X return (boundp(sym) ? true : NIL); X} X X/* xfboundp - is this a functional value bound to this symbol? */ XLVAL xfboundp() X{ X LVAL sym; X sym = xlgasymbol(); X xllastarg(); X return (fboundp(sym) ? true : NIL); X} X X/* xnull - is this null? */ XLVAL xnull() X{ X LVAL arg; X arg = xlgetarg(); X xllastarg(); X return (null(arg) ? true : NIL); X} X X/* xlistp - is this a list? */ XLVAL xlistp() X{ X LVAL arg; X arg = xlgetarg(); X xllastarg(); X return (listp(arg) ? true : NIL); X} X X/* xendp - is this the end of a list? */ XLVAL xendp() X{ X LVAL arg; X arg = xlgalist(); X xllastarg(); X return (null(arg) ? true : NIL); X} X X/* xconsp - is this a cons? */ XLVAL xconsp() X{ X LVAL arg; X arg = xlgetarg(); X xllastarg(); X return (consp(arg) ? true : NIL); X} X X/* xeq - are these equal? */ XLVAL xeq() X{ X LVAL arg1,arg2; X X /* get the two arguments */ X arg1 = xlgetarg(); X arg2 = xlgetarg(); X xllastarg(); X X /* compare the arguments */ X return (arg1 == arg2 ? true : NIL); X} X X/* xeql - are these equal? */ XLVAL xeql() X{ X LVAL arg1,arg2; X X /* get the two arguments */ X arg1 = xlgetarg(); X arg2 = xlgetarg(); X xllastarg(); X X /* compare the arguments */ X return (eql(arg1,arg2) ? true : NIL); X} X X/* xequal - are these equal? (recursive) */ XLVAL xequal() X{ X LVAL arg1,arg2; X X /* get the two arguments */ X arg1 = xlgetarg(); X arg2 = xlgetarg(); X xllastarg(); X X /* compare the arguments */ X return (equal(arg1,arg2) ? true : NIL); X} X X/* xset - built-in function set */ XLVAL xset() X{ X LVAL sym,val; X X /* get the symbol and new value */ X sym = xlgasymbol(); X val = xlgetarg(); X xllastarg(); X X /* assign the symbol the value of argument 2 and the return value */ X setvalue(sym,val); X X /* return the result value */ X return (val); X} X X/* xgensym - generate a symbol */ XLVAL xgensym() X{ X char sym[STRMAX+11]; /* enough space for prefix and number */ X LVAL x; X X /* get the prefix or number */ X if (moreargs()) { X x = xlgetarg(); X switch (ntype(x)) { X case SYMBOL: X x = getpname(x); X case STRING: X strncpy(gsprefix,getstring(x),STRMAX); X gsprefix[STRMAX] = '\0'; X break; X case FIXNUM: X gsnumber = getfixnum(x); X break; X default: X xlerror("bad argument type",x); X } X } X xllastarg(); X X /* create the pname of the new symbol */ X sprintf(sym,"%s%d",gsprefix,gsnumber++); X X /* make a symbol with this print name */ X return (xlmakesym(sym)); X} X X/* xmakesymbol - make a new uninterned symbol */ XLVAL xmakesymbol() X{ X return (makesymbol(FALSE)); X} X X/* xintern - make a new interned symbol */ XLVAL xintern() X{ X return (makesymbol(TRUE)); X} X X/* makesymbol - make a new symbol */ XLOCAL LVAL makesymbol(iflag) X int iflag; X{ X LVAL pname; X X /* get the print name of the symbol to intern */ X pname = xlgastring(); X xllastarg(); X X /* make the symbol */ X return (iflag ? xlenter(getstring(pname)) X : xlmakesym(getstring(pname))); X} X X/* xsymname - get the print name of a symbol */ XLVAL xsymname() X{ X LVAL sym; X X /* get the symbol */ X sym = xlgasymbol(); X xllastarg(); X X /* return the print name */ X return (getpname(sym)); X} X X/* xsymvalue - get the value of a symbol */ XLVAL xsymvalue() X{ X LVAL sym,val; X X /* get the symbol */ X sym = xlgasymbol(); X xllastarg(); X X /* get the global value */ X while ((val = getvalue(sym)) == s_unbound) X xlunbound(sym); X X /* return its value */ X return (val); X} X X/* xsymfunction - get the functional value of a symbol */ XLVAL xsymfunction() X{ X LVAL sym,val; X X /* get the symbol */ X sym = xlgasymbol(); X xllastarg(); X X /* get the global value */ X while ((val = getfunction(sym)) == s_unbound) X xlfunbound(sym); X X /* return its value */ X return (val); X} X X/* xsymplist - get the property list of a symbol */ XLVAL xsymplist() X{ X LVAL sym; X X /* get the symbol */ X sym = xlgasymbol(); X xllastarg(); X X /* return the property list */ X return (getplist(sym)); X} X X/* xget - get the value of a property */ XLVAL xget() X{ X LVAL sym,prp; X X /* get the symbol and property */ X sym = xlgasymbol(); X prp = xlgasymbol(); X xllastarg(); X X /* retrieve the property value */ X return (xlgetprop(sym,prp)); X} X X/* xputprop - set the value of a property */ XLVAL xputprop() X{ X LVAL sym,val,prp; X X /* get the symbol and property */ X sym = xlgasymbol(); X val = xlgetarg(); X prp = xlgasymbol(); X xllastarg(); X X /* set the property value */ X xlputprop(sym,val,prp); X X /* return the value */ X return (val); X} X X/* xremprop - remove a property value from a property list */ XLVAL xremprop() X{ X LVAL sym,prp; X X /* get the symbol and property */ X sym = xlgasymbol(); X prp = xlgasymbol(); X xllastarg(); X X /* remove the property */ X xlremprop(sym,prp); X X /* return nil */ X return (NIL); X} X X/* xhash - compute the hash value of a string or symbol */ XLVAL xhash() X{ X unsigned char *str; X LVAL len,val; X int n; X X /* get the string and the table length */ X val = xlgetarg(); X len = xlgafixnum(); n = (int)getfixnum(len); X xllastarg(); X X /* get the string */ X if (symbolp(val)) X str = getstring(getpname(val)); X else if (stringp(val)) X str = getstring(val); X else X xlerror("bad argument type",val); X X /* return the hash index */ X return (cvfixnum((FIXTYPE)hash(str,n))); X} X X/* xaref - array reference function */ XLVAL xaref() X{ X LVAL array,index; X int i; X X /* get the array and the index */ X array = xlgavector(); X index = xlgafixnum(); i = (int)getfixnum(index); X xllastarg(); X X /* range check the index */ X if (i < 0 || i >= getsize(array)) X xlerror("array index out of bounds",index); X X /* return the array element */ X return (getelement(array,i)); X} X X/* xmkarray - make a new array */ XLVAL xmkarray() X{ X LVAL size; X int n; X X /* get the size of the array */ X size = xlgafixnum() ; n = (int)getfixnum(size); X xllastarg(); X X /* create the array */ X return (newvector(n)); X} X X/* xvector - make a vector */ XLVAL xvector() X{ X LVAL val; X int i; X X /* make the vector */ X val = newvector(xlargc); X X /* store each argument */ X for (i = 0; moreargs(); ++i) X setelement(val,i,nextarg()); X xllastarg(); X X /* return the vector */ X return (val); X} X X/* xerror - special form 'error' */ XLVAL xerror() X{ X LVAL emsg,arg; X X /* get the error message and the argument */ X emsg = xlgastring(); X arg = (moreargs() ? xlgetarg() : s_unbound); X xllastarg(); X X /* signal the error */ X xlerror(getstring(emsg),arg); X} X X/* xcerror - special form 'cerror' */ XLVAL xcerror() X{ X LVAL cmsg,emsg,arg; X X /* get the correction message, the error message, and the argument */ X cmsg = xlgastring(); X emsg = xlgastring(); X arg = (moreargs() ? xlgetarg() : s_unbound); X xllastarg(); X X /* signal the error */ X xlcerror(getstring(cmsg),getstring(emsg),arg); X X /* return nil */ X return (NIL); X} X X/* xbreak - special form 'break' */ XLVAL xbreak() X{ X LVAL emsg,arg; X X /* get the error message */ X emsg = (moreargs() ? xlgastring() : NIL); X arg = (moreargs() ? xlgetarg() : s_unbound); X xllastarg(); X X /* enter the break loop */ X xlbreak((emsg ? getstring(emsg) : (unsigned char *)"**BREAK**"),arg); X X /* return nil */ X return (NIL); X} X X/* xcleanup - special form 'clean-up' */ XLVAL xcleanup() X{ X xllastarg(); X xlcleanup(); X} X X/* xtoplevel - special form 'top-level' */ XLVAL xtoplevel() X{ X xllastarg(); X xltoplevel(); X} X X/* xcontinue - special form 'continue' */ XLVAL xcontinue() X{ X xllastarg(); X xlcontinue(); X} X X/* xevalhook - eval hook function */ XLVAL xevalhook() X{ X LVAL expr,newehook,newahook,newenv,oldenv,oldfenv,olddenv,val; X X /* protect some pointers */ X xlstkcheck(3); X xlsave(oldenv); X xlsave(oldfenv); X xlsave(newenv); X X /* get the expression, the new hook functions and the environment */ X expr = xlgetarg(); X newehook = xlgetarg(); X newahook = xlgetarg(); X newenv = (moreargs() ? xlgalist() : NIL); X xllastarg(); X X /* bind *evalhook* and *applyhook* to the hook functions */ X olddenv = xldenv; X xldbind(s_evalhook,newehook); X xldbind(s_applyhook,newahook); X X /* establish the environment for the hook function */ X if (newenv) { X oldenv = xlenv; X oldfenv = xlfenv; X xlenv = car(newenv); X xlfenv = cdr(newenv); X } X X /* evaluate the expression (bypassing *evalhook*) */ X val = xlxeval(expr); X X /* restore the old environment */ X xlunbind(olddenv); X if (newenv) { X xlenv = oldenv; X xlfenv = oldfenv; X } X X /* restore the stack */ X xlpopn(3); X X /* return the result */ X return (val); X} X SHAR_EOF if test 12891 -ne "`wc -c 'xlbfun.c'`" then echo shar: error transmitting "'xlbfun.c'" '(should have been 12891 characters)' fi echo shar: extracting "'xlcont.c'" '(28157 characters)' if test -f 'xlcont.c' then echo shar: over-writing existing file "'xlcont.c'" fi sed 's/^X//' << \SHAR_EOF > 'xlcont.c' X/* xlcont - xlisp special forms */ X/* Copyright (c) 1985, by David Michael Betz X All Rights Reserved X Permission is granted for unrestricted non-commercial use */ X X#include "xlisp.h" X X/* external variables */ Xextern LVAL xlenv,xlfenv,xldenv,xlvalue; Xextern LVAL s_setf,s_car,s_cdr,s_nth,s_aref,s_get; Xextern LVAL s_svalue,s_sfunction,s_splist; Xextern LVAL s_lambda,s_macro; Xextern LVAL s_comma,s_comat; Xextern LVAL s_unbound; Xextern LVAL true; X X/* external routines */ Xextern LVAL makearglist(); X X/* forward declarations */ XFORWARD LVAL bquote1(); XFORWARD LVAL let(); XFORWARD LVAL flet(); XFORWARD LVAL prog(); XFORWARD LVAL progx(); XFORWARD LVAL doloop(); XFORWARD LVAL evarg(); XFORWARD LVAL match(); XFORWARD LVAL evmatch(); X X/* dummy node type for a list */ X#define LIST -1 X X/* xquote - special form 'quote' */ XLVAL xquote() X{ X LVAL val; X val = xlgetarg(); X xllastarg(); X return (val); X} X X/* xfunction - special form 'function' */ XLVAL xfunction() X{ X LVAL val; X X /* get the argument */ X val = xlgetarg(); X xllastarg(); X X /* create a closure for lambda expressions */ X if (consp(val) && car(val) == s_lambda && consp(cdr(val))) X val = xlclose(NIL,s_lambda,car(cdr(val)),cdr(cdr(val)),xlenv,xlfenv); X X /* otherwise, get the value of a symbol */ X else if (symbolp(val)) X val = xlgetfunction(val); X X /* otherwise, its an error */ X else X xlerror("not a function",val); X X /* return the function */ X return (val); X} X X/* xbquote - back quote special form */ XLVAL xbquote() X{ X LVAL expr; X X /* get the expression */ X expr = xlgetarg(); X xllastarg(); X X /* fill in the template */ X return (bquote1(expr)); X} X X/* bquote1 - back quote helper function */ XLOCAL LVAL bquote1(expr) X LVAL expr; X{ X LVAL val,list,last,new; X X /* handle atoms */ X if (atom(expr)) X val = expr; X X /* handle (comma <expr>) */ X else if (car(expr) == s_comma) { X if (atom(cdr(expr))) X xlfail("bad comma expression"); X val = xleval(car(cdr(expr))); X } X X /* handle ((comma-at <expr>) ... ) */ X else if (consp(car(expr)) && car(car(expr)) == s_comat) { X xlstkcheck(2); X xlsave(list); X xlsave(val); X if (atom(cdr(car(expr)))) X xlfail("bad comma-at expression"); X list = xleval(car(cdr(car(expr)))); X for (last = NIL; consp(list); list = cdr(list)) { X new = consa(car(list)); X if (last) X rplacd(last,new); X else X val = new; X last = new; X } X if (last) X rplacd(last,bquote1(cdr(expr))); X else X val = bquote1(cdr(expr)); X xlpopn(2); X } X X /* handle any other list */ X else { X xlsave1(val); X val = consa(NIL); X rplaca(val,bquote1(car(expr))); X rplacd(val,bquote1(cdr(expr))); X xlpop(); X } X X /* return the result */ X return (val); X} X X/* xlambda - special form 'lambda' */ XLVAL xlambda() X{ X LVAL fargs,arglist,val; X X /* get the formal argument list and function body */ X xlsave1(arglist); X fargs = xlgalist(); X arglist = makearglist(xlargc,xlargv); X X /* create a new function definition */ X val = xlclose(NIL,s_lambda,fargs,arglist,xlenv,xlfenv); X X /* restore the stack and return the closure */ X xlpop(); X return (val); X} X X/* xgetlambda - get the lambda expression associated with a closure */ XLVAL xgetlambda() X{ X LVAL closure; X closure = xlgaclosure(); X return (cons(gettype(closure), X cons(getlambda(closure),getbody(closure)))); X} X X/* xsetq - special form 'setq' */ XLVAL xsetq() X{ X LVAL sym,val; X X /* handle each pair of arguments */ X for (val = NIL; moreargs(); ) { X sym = xlgasymbol(); X val = xleval(nextarg()); X xlsetvalue(sym,val); X } X X /* return the result value */ X return (val); X} X X/* xpsetq - special form 'psetq' */ XLVAL xpsetq() X{ X LVAL plist,sym,val; X X /* protect some pointers */ X xlsave1(plist); X X /* handle each pair of arguments */ X for (val = NIL; moreargs(); ) { X sym = xlgasymbol(); X val = xleval(nextarg()); X plist = cons(cons(sym,val),plist); X } X X /* do parallel sets */ X for (; plist; plist = cdr(plist)) X xlsetvalue(car(car(plist)),cdr(car(plist))); X X /* restore the stack */ X xlpop(); X X /* return the result value */ X return (val); X} X X/* xsetf - special form 'setf' */ XLVAL xsetf() X{ X LVAL place,value; X X /* protect some pointers */ X xlsave1(value); X X /* handle each pair of arguments */ X while (moreargs()) { X X /* get place and value */ X place = xlgetarg(); X value = xleval(nextarg()); X X /* expand macros in the place form */ X if (consp(place)) X place = xlexpandmacros(place); X X /* check the place form */ X if (symbolp(place)) X xlsetvalue(place,value); X else if (consp(place)) X placeform(place,value); X else X xlfail("bad place form"); X } X X /* restore the stack */ X xlpop(); X X /* return the value */ X return (value); X} X X/* placeform - handle a place form other than a symbol */ XLOCAL placeform(place,value) X LVAL place,value; X{ X LVAL fun,arg1,arg2; X int i; X X /* check the function name */ X if ((fun = match(SYMBOL,&place)) == s_get) { X xlstkcheck(2); X xlsave(arg1); X xlsave(arg2); X arg1 = evmatch(SYMBOL,&place); X arg2 = evmatch(SYMBOL,&place); X if (place) toomany(place); X xlputprop(arg1,value,arg2); X xlpopn(2); X } X else if (fun == s_svalue) { X arg1 = evmatch(SYMBOL,&place); X if (place) toomany(place); X setvalue(arg1,value); X } X else if (fun == s_sfunction) { X arg1 = evmatch(SYMBOL,&place); X if (place) toomany(place); X setfunction(arg1,value); X } X else if (fun == s_splist) { X arg1 = evmatch(SYMBOL,&place); X if (place) toomany(place); X setplist(arg1,value); X } X else if (fun == s_car) { X arg1 = evmatch(CONS,&place); X if (place) toomany(place); X rplaca(arg1,value); X } X else if (fun == s_cdr) { X arg1 = evmatch(CONS,&place); X if (place) toomany(place); X rplacd(arg1,value); X } X else if (fun == s_nth) { X xlsave1(arg1); X arg1 = evmatch(FIXNUM,&place); X arg2 = evmatch(LIST,&place); X if (place) toomany(place); X for (i = (int)getfixnum(arg1); i > 0 && consp(arg2); --i) X arg2 = cdr(arg2); X if (consp(arg2)) X rplaca(arg2,value); X xlpop(); X } X else if (fun == s_aref) { X xlsave1(arg1); X arg1 = evmatch(VECTOR,&place); X arg2 = evmatch(FIXNUM,&place); i = (int)getfixnum(arg2); X if (place) toomany(place); X if (i < 0 || i >= getsize(arg1)) X xlerror("index out of range",arg2); X setelement(arg1,i,value); X xlpop(); X } X else if (fun = xlgetprop(fun,s_setf)) X setffunction(fun,place,value); X else X xlfail("bad place form"); X} X X/* setffunction - call a user defined setf function */ XLOCAL setffunction(fun,place,value) X LVAL fun,place,value; X{ X LVAL *newfp; X int argc; X X /* create the new call frame */ X newfp = xlsp; X pusharg(cvfixnum((FIXTYPE)(newfp - xlfp))); X pusharg(fun); X pusharg(NIL); X X /* push the values of all of the place expressions and the new value */ X for (argc = 1; consp(place); place = cdr(place), ++argc) X pusharg(xleval(car(place))); X pusharg(value); X X /* insert the argument count and establish the call frame */ X newfp[2] = cvfixnum((FIXTYPE)argc); X xlfp = newfp; X X /* apply the function */ X xlapply(argc); X} X X/* xdefun - special form 'defun' */ XLVAL xdefun() X{ X LVAL sym,fargs,arglist; X X /* get the function symbol and formal argument list */ X xlsave1(arglist); X sym = xlgasymbol(); X fargs = xlgalist(); X arglist = makearglist(xlargc,xlargv); X X /* make the symbol point to a new function definition */ X xlsetfunction(sym,xlclose(sym,s_lambda,fargs,arglist,xlenv,xlfenv)); X X /* restore the stack and return the function symbol */ X xlpop(); X return (sym); X} X X/* xdefmacro - special form 'defmacro' */ XLVAL xdefmacro() X{ X LVAL sym,fargs,arglist; X X /* get the function symbol and formal argument list */ X xlsave1(arglist); X sym = xlgasymbol(); X fargs = xlgalist(); X arglist = makearglist(xlargc,xlargv); X X /* make the symbol point to a new function definition */ X xlsetfunction(sym,xlclose(sym,s_macro,fargs,arglist,NIL,NIL)); X X /* restore the stack and return the function symbol */ X xlpop(); X return (sym); X} X X/* xcond - special form 'cond' */ XLVAL xcond() X{ X LVAL list,val; X X /* find a predicate that is true */ X for (val = NIL; moreargs(); ) { X X /* get the next conditional */ X list = nextarg(); X X /* evaluate the predicate part */ X if (consp(list) && (val = xleval(car(list)))) { X X /* evaluate each expression */ X for (list = cdr(list); consp(list); list = cdr(list)) X val = xleval(car(list)); X X /* exit the loop */ X break; X } X } X X /* return the value */ X return (val); X} X X/* xwhen - special form 'when' */ XLVAL xwhen() X{ X LVAL val; X X /* check the test expression */ X if (val = xleval(xlgetarg())) X while (moreargs()) X val = xleval(nextarg()); X X /* return the value */ X return (val); X} X X/* xunless - special form 'unless' */ XLVAL xunless() X{ X LVAL val=NIL; X X /* check the test expression */ X if (xleval(xlgetarg()) == NIL) X while (moreargs()) X val = xleval(nextarg()); X X /* return the value */ X return (val); X} X X/* xcase - special form 'case' */ XLVAL xcase() X{ X LVAL key,list,cases,val; X X /* protect some pointers */ X xlsave1(key); X X /* get the key expression */ X key = xleval(nextarg()); X X /* find a case that matches */ X for (val = NIL; moreargs(); ) { X X /* get the next case clause */ X list = nextarg(); X X /* make sure this is a valid clause */ X if (consp(list)) { X X /* compare the key list against the key */ X if ((cases = car(list)) == true || X (listp(cases) && keypresent(key,cases)) || X eql(key,cases)) { X X /* evaluate each expression */ X for (list = cdr(list); consp(list); list = cdr(list)) X val = xleval(car(list)); X X /* exit the loop */ X break; X } X } X else X xlerror("bad case clause",list); X } X X /* restore the stack */ X xlpop(); X X /* return the value */ X return (val); X} X X/* keypresent - check for the presence of a key in a list */ XLOCAL int keypresent(key,list) X LVAL key,list; X{ X for (; consp(list); list = cdr(list)) X if (eql(car(list),key)) X return (TRUE); X return (FALSE); X} X X/* xand - special form 'and' */ XLVAL xand() X{ X LVAL val; X X /* evaluate each argument */ X for (val = true; moreargs(); ) X if ((val = xleval(nextarg())) == NIL) X break; X X /* return the result value */ X return (val); X} X X/* xor - special form 'or' */ XLVAL xor() X{ X LVAL val; X X /* evaluate each argument */ X for (val = NIL; moreargs(); ) X if ((val = xleval(nextarg()))) X break; X X /* return the result value */ X return (val); X} X X/* xif - special form 'if' */ XLVAL xif() X{ X LVAL testexpr,thenexpr,elseexpr; X X /* get the test expression, then clause and else clause */ X testexpr = xlgetarg(); X thenexpr = xlgetarg(); X elseexpr = (moreargs() ? xlgetarg() : NIL); X xllastarg(); X X /* evaluate the appropriate clause */ X return (xleval(xleval(testexpr) ? thenexpr : elseexpr)); X} X X/* xlet - special form 'let' */ XLVAL xlet() X{ X return (let(TRUE)); X} X X/* xletstar - special form 'let*' */ XLVAL xletstar() X{ X return (let(FALSE)); X} X X/* let - common let routine */ XLOCAL LVAL let(pflag) X int pflag; X{ X LVAL newenv,val; X X /* protect some pointers */ X xlsave1(newenv); X X /* create a new environment frame */ X newenv = xlframe(xlenv); X X /* get the list of bindings and bind the symbols */ X if (!pflag) xlenv = newenv; X dobindings(xlgalist(),newenv); X if (pflag) xlenv = newenv; X X /* execute the code */ X for (val = NIL; moreargs(); ) X val = xleval(nextarg()); X X /* unbind the arguments */ X xlenv = cdr(xlenv); X X /* restore the stack */ X xlpop(); X X /* return the result */ X return (val); X} X X/* xflet - built-in function 'flet' */ XLVAL xflet() X{ X return (flet(s_lambda,TRUE)); X} X X/* xlabels - built-in function 'labels' */ XLVAL xlabels() X{ X return (flet(s_lambda,FALSE)); X} X X/* xmacrolet - built-in function 'macrolet' */ XLVAL xmacrolet() X{ X return (flet(s_macro,TRUE)); X} X X/* flet - common flet/labels/macrolet routine */ XLOCAL LVAL flet(type,letflag) X LVAL type; int letflag; X{ X LVAL list,bnd,sym,fargs,val; X X /* create a new environment frame */ X xlfenv = xlframe(xlfenv); X X /* bind each symbol in the list of bindings */ X for (list = xlgalist(); consp(list); list = cdr(list)) { X X /* get the next binding */ X bnd = car(list); X X /* get the symbol and the function definition */ X sym = match(SYMBOL,&bnd); X fargs = match(LIST,&bnd); X val = xlclose(sym,type,fargs,bnd,xlenv,(letflag?cdr(xlfenv):xlfenv)); X X /* bind the value to the symbol */ X xlfbind(sym,val); X } X X /* execute the code */ X for (val = NIL; moreargs(); ) X val = xleval(nextarg()); X X /* unbind the arguments */ X xlfenv = cdr(xlfenv); X X /* return the result */ X return (val); X} X X/* xprog - special form 'prog' */ XLVAL xprog() X{ X return (prog(TRUE)); X} X X/* xprogstar - special form 'prog*' */ XLVAL xprogstar() X{ X return (prog(FALSE)); X} X X/* prog - common prog routine */ XLOCAL LVAL prog(pflag) X int pflag; X{ X LVAL newenv,val; X CONTEXT cntxt; X X /* protect some pointers */ X xlsave1(newenv); X X /* create a new environment frame */ X newenv = xlframe(xlenv); X X /* establish a new execution context */ X xlbegin(&cntxt,CF_RETURN,NIL); X if (setjmp(cntxt.c_jmpbuf)) X val = xlvalue; X else { X X /* get the list of bindings and bind the symbols */ X if (!pflag) xlenv = newenv; X dobindings(xlgalist(),newenv); X if (pflag) xlenv = newenv; X X /* execute the code */ X tagbody(); X val = NIL; X X /* unbind the arguments */ X xlenv = cdr(xlenv); X } X xlend(&cntxt); X X /* restore the stack */ X xlpop(); X X /* return the result */ X return (val); X} X X/* xgo - special form 'go' */ XLVAL xgo() X{ X LVAL label; X X /* get the target label */ X label = xlgetarg(); X xllastarg(); X X /* transfer to the label */ X xlgo(label); X} X X/* xreturn - special form 'return' */ XLVAL xreturn() X{ X LVAL val; X X /* get the return value */ X val = (moreargs() ? xleval(nextarg()) : NIL); X xllastarg(); X X /* return from the inner most block */ X xlreturn(NIL,val); X} X X/* xrtnfrom - special form 'return-from' */ XLVAL xrtnfrom() X{ X LVAL name,val; X X /* get the return value */ X name = xlgasymbol(); X val = (moreargs() ? xleval(nextarg()) : NIL); X xllastarg(); X X /* return from the inner most block */ X xlreturn(name,val); X} X X/* xprog1 - special form 'prog1' */ XLVAL xprog1() X{ X return (progx(1)); X} X X/* xprog2 - special form 'prog2' */ XLVAL xprog2() X{ X return (progx(2)); X} X X/* progx - common progx code */ XLOCAL LVAL progx(n) X int n; X{ X LVAL val; X X /* protect some pointers */ X xlsave1(val); X X /* evaluate the first n expressions */ X while (moreargs() && --n >= 0) X val = xleval(nextarg()); X X /* evaluate each remaining argument */ X while (moreargs()) X xleval(nextarg()); X X /* restore the stack */ X xlpop(); X X /* return the last test expression value */ X return (val); X} X X/* xprogn - special form 'progn' */ XLVAL xprogn() X{ X LVAL val; X X /* evaluate each expression */ X for (val = NIL; moreargs(); ) X val = xleval(nextarg()); X X /* return the last test expression value */ X return (val); X} X X/* xprogv - special form 'progv' */ XLVAL xprogv() X{ X LVAL olddenv,vars,vals,val; X X /* protect some pointers */ X xlstkcheck(2); X xlsave(vars); X xlsave(vals); X X /* get the list of variables and the list of values */ X vars = xlgalist(); vars = xleval(vars); X vals = xlgalist(); vals = xleval(vals); X X /* bind the values to the variables */ X for (olddenv = xldenv; consp(vars); vars = cdr(vars)) { X if (!symbolp(car(vars))) X xlerror("expecting a symbol",car(vars)); X if (consp(vals)) { X xldbind(car(vars),car(vals)); X vals = cdr(vals); X } X else X xldbind(car(vars),s_unbound); X } X X /* evaluate each expression */ X for (val = NIL; moreargs(); ) X val = xleval(nextarg()); X X /* restore the previous environment and the stack */ X xlunbind(olddenv); X xlpopn(2); X X /* return the last test expression value */ X return (val); X} X X/* xloop - special form 'loop' */ XLVAL xloop() X{ X LVAL *argv,arg,val; X CONTEXT cntxt; X int argc; X X /* protect some pointers */ X xlsave1(arg); X X /* establish a new execution context */ X xlbegin(&cntxt,CF_RETURN,NIL); X if (setjmp(cntxt.c_jmpbuf)) X val = xlvalue; X else X for (argv = xlargv, argc = xlargc; ; xlargv = argv, xlargc = argc) X while (moreargs()) { X arg = nextarg(); X if (consp(arg)) X xleval(arg); X } X xlend(&cntxt); X X /* restore the stack */ X xlpop(); X X /* return the result */ X return (val); X} X X/* xdo - special form 'do' */ XLVAL xdo() X{ X return (doloop(TRUE)); X} X X/* xdostar - special form 'do*' */ XLVAL xdostar() X{ X return (doloop(FALSE)); X} X X/* doloop - common do routine */ XLOCAL LVAL doloop(pflag) X int pflag; X{ X LVAL newenv,*argv,blist,clist,test,val; X CONTEXT cntxt; X int argc; X X /* protect some pointers */ X xlsave1(newenv); X X /* get the list of bindings, the exit test and the result forms */ X blist = xlgalist(); X clist = xlgalist(); X test = (consp(clist) ? car(clist) : NIL); X argv = xlargv; X argc = xlargc; X X /* create a new environment frame */ X newenv = xlframe(xlenv); X X /* establish a new execution context */ X xlbegin(&cntxt,CF_RETURN,NIL); X if (setjmp(cntxt.c_jmpbuf)) X val = xlvalue; X else { X X /* bind the symbols */ X if (!pflag) xlenv = newenv; X dobindings(blist,newenv); X if (pflag) xlenv = newenv; X X /* execute the loop as long as the test is false */ X for (val = NIL; xleval(test) == NIL; doupdates(blist,pflag)) { X xlargv = argv; X xlargc = argc; X tagbody(); X } X X /* evaluate the result expression */ X if (consp(clist)) X for (clist = cdr(clist); consp(clist); clist = cdr(clist)) X val = xleval(car(clist)); X X /* unbind the arguments */ X xlenv = cdr(xlenv); X } X xlend(&cntxt); X X /* restore the stack */ X xlpop(); X X /* return the result */ X return (val); X} X X/* xdolist - special form 'dolist' */ XLVAL xdolist() X{ X LVAL list,*argv,clist,sym,val; X CONTEXT cntxt; X int argc; X X /* protect some pointers */ X xlsave1(list); X X /* get the control list (sym list result-expr) */ X clist = xlgalist(); X sym = match(SYMBOL,&clist); X list = evmatch(LIST,&clist); X argv = xlargv; X argc = xlargc; X X /* initialize the local environment */ X xlenv = xlframe(xlenv); X xlbind(sym,NIL); X X /* establish a new execution context */ X xlbegin(&cntxt,CF_RETURN,NIL); X if (setjmp(cntxt.c_jmpbuf)) X val = xlvalue; X else { X X /* loop through the list */ X for (val = NIL; consp(list); list = cdr(list)) { X X /* bind the symbol to the next list element */ X xlsetvalue(sym,car(list)); X X /* execute the loop body */ X xlargv = argv; X xlargc = argc; X tagbody(); X } X X /* evaluate the result expression */ X xlsetvalue(sym,NIL); X val = (consp(clist) ? xleval(car(clist)) : NIL); X X /* unbind the arguments */ X xlenv = cdr(xlenv); X } X xlend(&cntxt); X X /* restore the stack */ X xlpop(); X X /* return the result */ X return (val); X} X X/* xdotimes - special form 'dotimes' */ XLVAL xdotimes() X{ X LVAL *argv,clist,sym,cnt,val; X CONTEXT cntxt; X int argc,n,i; X X /* get the control list (sym list result-expr) */ X clist = xlgalist(); X sym = match(SYMBOL,&clist); X cnt = evmatch(FIXNUM,&clist); n = getfixnum(cnt); X argv = xlargv; X argc = xlargc; X X /* initialize the local environment */ X xlenv = xlframe(xlenv); X xlbind(sym,NIL); X X /* establish a new execution context */ X xlbegin(&cntxt,CF_RETURN,NIL); X if (setjmp(cntxt.c_jmpbuf)) X val = xlvalue; X else { X X /* loop through for each value from zero to n-1 */ X for (val = NIL, i = 0; i < n; ++i) { X X /* bind the symbol to the next list element */ X xlsetvalue(sym,cvfixnum((FIXTYPE)i)); X X /* execute the loop body */ X xlargv = argv; X xlargc = argc; X tagbody(); X } X X /* evaluate the result expression */ X xlsetvalue(sym,cnt); X val = (consp(clist) ? xleval(car(clist)) : NIL); X X /* unbind the arguments */ X xlenv = cdr(xlenv); X } X xlend(&cntxt); X X /* return the result */ X return (val); X} X X/* xblock - special form 'block' */ XLVAL xblock() X{ X LVAL name,val; X CONTEXT cntxt; X X /* get the block name */ X name = xlgetarg(); X if (name && !symbolp(name)) X xlbadtype(name); X X /* execute the block */ X xlbegin(&cntxt,CF_RETURN,name); X if (setjmp(cntxt.c_jmpbuf)) X val = xlvalue; X else X for (val = NIL; moreargs(); ) X val = xleval(nextarg()); X xlend(&cntxt); X X /* return the value of the last expression */ X return (val); X} X X/* xtagbody - special form 'tagbody' */ XLVAL xtagbody() X{ X tagbody(); X return (NIL); X} X X/* xcatch - special form 'catch' */ XLVAL xcatch() X{ X CONTEXT cntxt; X LVAL tag,val; X X /* protect some pointers */ X xlsave1(tag); X X /* get the tag */ X tag = xleval(nextarg()); X X /* establish an execution context */ X xlbegin(&cntxt,CF_THROW,tag); X X /* check for 'throw' */ X if (setjmp(cntxt.c_jmpbuf)) X val = xlvalue; X X /* otherwise, evaluate the remainder of the arguments */ X else { X for (val = NIL; moreargs(); ) X val = xleval(nextarg()); X } X xlend(&cntxt); X X /* restore the stack */ X xlpop(); X X /* return the result */ X return (val); X} X X/* xthrow - special form 'throw' */ XLVAL xthrow() X{ X LVAL tag,val; X X /* get the tag and value */ X tag = xleval(nextarg()); X val = (moreargs() ? xleval(nextarg()) : NIL); X xllastarg(); X X /* throw the tag */ X xlthrow(tag,val); X} X X/* xunwindprotect - special form 'unwind-protect' */ XLVAL xunwindprotect() X{ X extern CONTEXT *xltarget; X extern int xlmask; X CONTEXT cntxt,*target; X int mask,sts; X LVAL val; X X /* protect some pointers */ X xlsave1(val); X X /* get the expression to protect */ X val = xlgetarg(); X X /* evaluate the protected expression */ X xlbegin(&cntxt,CF_UNWIND,NIL); X if (sts = setjmp(cntxt.c_jmpbuf)) { X target = xltarget; X mask = xlmask; X val = xlvalue; X } X else X val = xleval(val); X xlend(&cntxt); X X /* evaluate the cleanup expressions */ X while (moreargs()) X xleval(nextarg()); X X /* if unwinding, continue unwinding */ X if (sts) X xljump(target,mask,val); X X /* restore the stack */ X xlpop(); X X /* return the value of the protected expression */ X return (val); X} X X/* xerrset - special form 'errset' */ XLVAL xerrset() X{ X LVAL expr,flag,val; X CONTEXT cntxt; X X /* get the expression and the print flag */ X expr = xlgetarg(); X flag = (moreargs() ? xlgetarg() : true); X xllastarg(); X X /* establish an execution context */ X xlbegin(&cntxt,CF_ERROR,flag); X X /* check for error */ X if (setjmp(cntxt.c_jmpbuf)) X val = NIL; X X /* otherwise, evaluate the expression */ X else { X expr = xleval(expr); X val = consa(expr); X } X xlend(&cntxt); X X /* return the result */ X return (val); X} X X/* xtrace - special form 'trace' */ XLVAL xtrace() X{ X LVAL sym,fun,this; X X /* loop through all of the arguments */ X sym = xlenter("*TRACELIST*"); X while (moreargs()) { X fun = xlgasymbol(); X X /* check for the function name already being in the list */ X for (this = getvalue(sym); consp(this); this = cdr(this)) X if (car(this) == fun) X break; X X /* add the function name to the list */ X if (null(this)) X setvalue(sym,cons(fun,getvalue(sym))); X } X return (getvalue(sym)); X} X X/* xuntrace - special form 'untrace' */ XLVAL xuntrace() X{ X LVAL sym,fun,this,last; X X /* loop through all of the arguments */ X sym = xlenter("*TRACELIST*"); X while (moreargs()) { X fun = xlgasymbol(); X X /* remove the function name from the list */ X last = NIL; X for (this = getvalue(sym); consp(this); this = cdr(this)) { X if (car(this) == fun) { X if (last) X rplacd(last,cdr(this)); X else X setvalue(sym,cdr(this)); X break; X } X last = this; X } X } X return (getvalue(sym)); X} X X/* dobindings - handle bindings for let/let*, prog/prog*, do/do* */ XLOCAL dobindings(list,env) X LVAL list,env; X{ X LVAL bnd,sym,val; X X /* protect some pointers */ X xlsave1(val); X X /* bind each symbol in the list of bindings */ X for (; consp(list); list = cdr(list)) { X X /* get the next binding */ X bnd = car(list); X X /* handle a symbol */ X if (symbolp(bnd)) { X sym = bnd; X val = NIL; X } X X /* handle a list of the form (symbol expr) */ X else if (consp(bnd)) { X sym = match(SYMBOL,&bnd); X val = evarg(&bnd); X } X else X xlfail("bad binding"); X X /* bind the value to the symbol */ X xlpbind(sym,val,env); X } X X /* restore the stack */ X xlpop(); X} X X/* doupdates - handle updates for do/do* */ XLOCAL doupdates(list,pflag) X LVAL list; int pflag; X{ X LVAL plist,bnd,sym,val; X X /* protect some pointers */ X xlstkcheck(2); X xlsave(plist); X xlsave(val); X X /* bind each symbol in the list of bindings */ X for (; consp(list); list = cdr(list)) { X X /* get the next binding */ X bnd = car(list); X X /* handle a list of the form (symbol expr) */ X if (consp(bnd)) { X sym = match(SYMBOL,&bnd); X bnd = cdr(bnd); X if (bnd) { X val = evarg(&bnd); X if (pflag) X plist = cons(cons(sym,val),plist); X else X xlsetvalue(sym,val); X } X } X } X X /* set the values for parallel updates */ X for (; plist; plist = cdr(plist)) X xlsetvalue(car(car(plist)),cdr(car(plist))); X X /* restore the stack */ X xlpopn(2); X} X X/* tagbody - execute code within a block and tagbody */ XLOCAL tagbody() X{ X LVAL *argv,arg; X CONTEXT cntxt; X int argc; X X /* establish an execution context */ X xlbegin(&cntxt,CF_GO,NIL); X argc = xlargc; X argv = xlargv; X X /* check for a 'go' */ X if (setjmp(cntxt.c_jmpbuf)) { X cntxt.c_xlargc = argc; X cntxt.c_xlargv = argv; X } X X /* execute the body */ X while (moreargs()) { X arg = nextarg(); X if (consp(arg)) X xleval(arg); X } X xlend(&cntxt); X} X X/* match - get an argument and match its type */ XLOCAL LVAL match(type,pargs) X int type; LVAL *pargs; X{ X LVAL arg; X X /* make sure the argument exists */ X if (!consp(*pargs)) X toofew(*pargs); X X /* get the argument value */ X arg = car(*pargs); X X /* move the argument pointer ahead */ X *pargs = cdr(*pargs); X X /* check its type */ X if (type == LIST) { X if (arg && ntype(arg) != CONS) X xlerror("bad argument type",arg); X } X else { X if (arg == NIL || ntype(arg) != type) X xlerror("bad argument type",arg); X } X X /* return the argument */ X return (arg); X} X X/* evarg - get the next argument and evaluate it */ XLOCAL LVAL evarg(pargs) X LVAL *pargs; X{ X LVAL arg; X X /* protect some pointers */ X xlsave1(arg); X X /* make sure the argument exists */ X if (!consp(*pargs)) X toofew(*pargs); X X /* get the argument value */ X arg = car(*pargs); X X /* move the argument pointer ahead */ X *pargs = cdr(*pargs); X X /* evaluate the argument */ X arg = xleval(arg); X X /* restore the stack */ X xlpop(); X X /* return the argument */ X return (arg); X} X X/* evmatch - get an evaluated argument and match its type */ XLOCAL LVAL evmatch(type,pargs) X int type; LVAL *pargs; X{ X LVAL arg; X X /* protect some pointers */ X xlsave1(arg); X X /* make sure the argument exists */ X if (!consp(*pargs)) X toofew(*pargs); X X /* get the argument value */ X arg = car(*pargs); X X /* move the argument pointer ahead */ X *pargs = cdr(*pargs); X X /* evaluate the argument */ X arg = xleval(arg); X X /* check its type */ X if (type == LIST) { X if (arg && ntype(arg) != CONS) X xlerror("bad argument type",arg); X } X else { X if (arg == NIL || ntype(arg) != type) X xlerror("bad argument type",arg); X } X X /* restore the stack */ X xlpop(); X X /* return the argument */ X return (arg); X} X X/* toofew - too few arguments */ XLOCAL toofew(args) X LVAL args; X{ X xlerror("too few arguments",args); X} X X/* toomany - too many arguments */ XLOCAL toomany(args) X LVAL args; X{ X xlerror("too many arguments",args); X} X SHAR_EOF if test 28157 -ne "`wc -c 'xlcont.c'`" then echo shar: error transmitting "'xlcont.c'" '(should have been 28157 characters)' fi echo shar: extracting "'xldbug.c'" '(3992 characters)' if test -f 'xldbug.c' then echo shar: over-writing existing file "'xldbug.c'" fi sed 's/^X//' << \SHAR_EOF > 'xldbug.c' X/* xldebug - xlisp debugging support */ X/* Copyright (c) 1985, by David Michael Betz X All Rights Reserved X Permission is granted for unrestricted non-commercial use */ X X#include "xlisp.h" X X/* external variables */ Xextern int xldebug; Xextern int xlsample; Xextern LVAL s_debugio,s_unbound; Xextern LVAL s_tracenable,s_tlimit,s_breakenable; Xextern LVAL true; Xextern char buf[]; X X/* external routines */ Xextern char *malloc(); X X/* forward declarations */ XFORWARD LVAL stacktop(); X X/* xlabort - xlisp serious error handler */ Xxlabort(emsg) X char *emsg; X{ X xlsignal(emsg,s_unbound); X xlerrprint("error",NULL,emsg,s_unbound); X xlbrklevel(); X} X X/* xlbreak - enter a break loop */ Xxlbreak(emsg,arg) X char *emsg; LVAL arg; X{ X breakloop("break","return from BREAK",emsg,arg,TRUE); X} X X/* xlfail - xlisp error handler */ Xxlfail(emsg) X char *emsg; X{ X xlerror(emsg,s_unbound); X} X X/* xlerror - handle a fatal error */ Xxlerror(emsg,arg) X char *emsg; LVAL arg; X{ X if (getvalue(s_breakenable) != NIL) X breakloop("error",NULL,emsg,arg,FALSE); X else { X xlsignal(emsg,arg); X xlerrprint("error",NULL,emsg,arg); X xlbrklevel(); X } X} X X/* xlcerror - handle a recoverable error */ Xxlcerror(cmsg,emsg,arg) X char *cmsg,*emsg; LVAL arg; X{ X if (getvalue(s_breakenable) != NIL) X breakloop("error",cmsg,emsg,arg,TRUE); X else { X xlsignal(emsg,arg); X xlerrprint("error",NULL,emsg,arg); X xlbrklevel(); X } X} X X/* xlerrprint - print an error message */ Xxlerrprint(hdr,cmsg,emsg,arg) X char *hdr,*cmsg,*emsg; LVAL arg; X{ X /* print the error message */ X sprintf(buf,"%s: %s",hdr,emsg); X errputstr(buf); X X /* print the argument */ X if (arg != s_unbound) { X errputstr(" - "); X errprint(arg); X } X X /* no argument, just end the line */ X else X errputstr("\n"); X X /* print the continuation message */ X if (cmsg) { X sprintf(buf,"if continued: %s\n",cmsg); X errputstr(buf); X } X} X X/* breakloop - the debug read-eval-print loop */ XLOCAL int breakloop(hdr,cmsg,emsg,arg,cflag) X char *hdr,*cmsg,*emsg; LVAL arg; int cflag; X{ X LVAL expr,val; X CONTEXT cntxt; X int type; X X /* print the error message */ X xlerrprint(hdr,cmsg,emsg,arg); X X /* flush the input buffer */ X xlflush(); X X /* do the back trace */ X if (getvalue(s_tracenable)) { X val = getvalue(s_tlimit); X xlbaktrace(fixp(val) ? (int)getfixnum(val) : -1); X } X X /* protect some pointers */ X xlsave1(expr); X X /* increment the debug level */ X ++xldebug; X X /* debug command processing loop */ X xlbegin(&cntxt,CF_BRKLEVEL|CF_CLEANUP|CF_CONTINUE,true); X for (type = 0; type == 0; ) { X X /* setup the continue trap */ X if (type = setjmp(cntxt.c_jmpbuf)) X switch (type) { X case CF_CLEANUP: X continue; X case CF_BRKLEVEL: X type = 0; X break; X case CF_CONTINUE: X if (cflag) { X dbgputstr("[ continue from break loop ]\n"); X continue; X } X else xlabort("this error can't be continued"); X } X X /* print a prompt */ X sprintf(buf,"%d> ",xldebug); X dbgputstr(buf); X X /* read an expression and check for eof */ X if (!xlread(getvalue(s_debugio),&expr,FALSE)) { X type = CF_CLEANUP; X break; X } X X /* save the input expression */ X xlrdsave(expr); X X /* evaluate the expression */ X expr = xleval(expr); X X /* save the result */ X xlevsave(expr); X X /* print it */ X dbgprint(expr); X } X xlend(&cntxt); X X /* decrement the debug level */ X --xldebug; X X /* restore the stack */ X xlpop(); X X /* check for aborting to the previous level */ X if (type == CF_CLEANUP) X xlbrklevel(); X} X X/* baktrace - do a back trace */ Xxlbaktrace(n) X int n; X{ X LVAL *fp,*p; X int argc; X for (fp = xlfp; (n < 0 || n--) && *fp; fp = fp - (int)getfixnum(*fp)) { X p = fp + 1; X errputstr("Function: "); X errprint(*p++); X if (argc = (int)getfixnum(*p++)) X errputstr("Arguments:\n"); X while (--argc >= 0) { X errputstr(" "); X errprint(*p++); X } X } X} X X/* xldinit - debug initialization routine */ Xxldinit() X{ X xlsample = 0; X xldebug = 0; X} X SHAR_EOF if test 3992 -ne "`wc -c 'xldbug.c'`" then echo shar: error transmitting "'xldbug.c'" '(should have been 3992 characters)' fi echo shar: extracting "'xldmem.c'" '(14715 characters)' if test -f 'xldmem.c' then echo shar: over-writing existing file "'xldmem.c'" fi sed 's/^X//' << \SHAR_EOF > 'xldmem.c' X/* xldmem - xlisp dynamic memory management routines */ X/* Copyright (c) 1985, by David Michael Betz X All Rights Reserved X Permission is granted for unrestricted non-commercial use */ X X#include "xlisp.h" X X/* node flags */ X#define MARK 1 X#define LEFT 2 X X/* macro to compute the size of a segment */ X#define segsize(n) (sizeof(SEGMENT)+((n)-1)*sizeof(struct node)) X X/* external variables */ Xextern LVAL obarray,s_gcflag,s_gchook,s_unbound,true; Xextern LVAL xlenv,xlfenv,xldenv; Xextern char buf[]; X X/* variables local to xldmem.c and xlimage.c */ XSEGMENT *segs,*lastseg,*fixseg,*charseg; Xint anodes,nsegs,gccalls; Xlong nnodes,nfree,total; XLVAL fnodes; X X/* external procedures */ Xextern char *malloc(); Xextern char *calloc(); X X/* forward declarations */ XFORWARD LVAL newnode(); XFORWARD unsigned char *stralloc(); XFORWARD SEGMENT *newsegment(); X X/* cons - construct a new cons node */ XLVAL cons(x,y) X LVAL x,y; X{ X LVAL nnode; X X /* get a free node */ X if ((nnode = fnodes) == NIL) { X xlstkcheck(2); X xlprotect(x); X xlprotect(y); X findmem(); X if ((nnode = fnodes) == NIL) X xlabort("insufficient node space"); X xlpop(); X xlpop(); X } X X /* unlink the node from the free list */ X fnodes = cdr(nnode); X --nfree; X X /* initialize the new node */ X nnode->n_type = CONS; X rplaca(nnode,x); X rplacd(nnode,y); X X /* return the new node */ X return (nnode); X} X X/* cvstring - convert a string to a string node */ XLVAL cvstring(str) X char *str; X{ X LVAL val; X xlsave1(val); X val = newnode(STRING); X val->n_strlen = strlen(str) + 1; X val->n_string = stralloc(getslength(val)); X strcpy(getstring(val),str); X xlpop(); X return (val); X} X X/* newstring - allocate and initialize a new string */ XLVAL newstring(size) X int size; X{ X LVAL val; X xlsave1(val); X val = newnode(STRING); X val->n_strlen = size; X val->n_string = stralloc(getslength(val)); X strcpy(getstring(val),""); X xlpop(); X return (val); X} X X/* cvsymbol - convert a string to a symbol */ XLVAL cvsymbol(pname) X char *pname; X{ X LVAL val; X xlsave1(val); X val = newvector(SYMSIZE); X val->n_type = SYMBOL; X setvalue(val,s_unbound); X setfunction(val,s_unbound); X setpname(val,cvstring(pname)); X xlpop(); X return (val); X} X X/* cvsubr - convert a function to a subr or fsubr */ XLVAL cvsubr(fcn,type,offset) X LVAL (*fcn)(); int type,offset; X{ X LVAL val; X val = newnode(type); X val->n_subr = fcn; X val->n_offset = offset; X return (val); X} X X/* cvfile - convert a file pointer to a stream */ XLVAL cvfile(fp) X FILE *fp; X{ X LVAL val; X val = newnode(STREAM); X setfile(val,fp); X setsavech(val,'\0'); X return (val); X} X X/* cvfixnum - convert an integer to a fixnum node */ XLVAL cvfixnum(n) X FIXTYPE n; X{ X LVAL val; X if (n >= SFIXMIN && n <= SFIXMAX) X return (&fixseg->sg_nodes[(int)n-SFIXMIN]); X val = newnode(FIXNUM); X val->n_fixnum = n; X return (val); X} X X/* cvflonum - convert a floating point number to a flonum node */ XLVAL cvflonum(n) X FLOTYPE n; X{ X LVAL val; X val = newnode(FLONUM); X val->n_flonum = n; X return (val); X} X X/* cvchar - convert an integer to a character node */ XLVAL cvchar(n) X int n; X{ X if (n >= CHARMIN && n <= CHARMAX) X return (&charseg->sg_nodes[n-CHARMIN]); X xlerror("character code out of range",cvfixnum((FIXTYPE)n)); X} X X/* newustream - create a new unnamed stream */ XLVAL newustream() X{ X LVAL val; X val = newnode(USTREAM); X sethead(val,NIL); X settail(val,NIL); X return (val); X} X X/* newobject - allocate and initialize a new object */ XLVAL newobject(cls,size) X LVAL cls; int size; X{ X LVAL val; X val = newvector(size+1); X val->n_type = OBJECT; X setelement(val,0,cls); X return (val); X} X X/* newclosure - allocate and initialize a new closure */ XLVAL newclosure(name,type,env,fenv) X LVAL name,type,env,fenv; X{ X LVAL val; X val = newvector(CLOSIZE); X val->n_type = CLOSURE; X setname(val,name); X settype(val,type); X setenv(val,env); X setfenv(val,fenv); X return (val); X} X X/* newstruct - allocate and initialize a new structure node */ XLVAL newstruct(type,size) X LVAL type; int size; X{ X LVAL val; X val = newvector(size+1); X val->n_type = STRUCT; X setelement(val,0,type); X return (val); X} X X/* newvector - allocate and initialize a new vector node */ XLVAL newvector(size) X int size; X{ X LVAL vect; X int bsize; X xlsave1(vect); X vect = newnode(VECTOR); X vect->n_vsize = 0; X if (bsize = size * sizeof(LVAL)) { X if ((vect->n_vdata = (LVAL *)calloc(1,bsize)) == NULL) { X findmem(); X if ((vect->n_vdata = (LVAL *)calloc(1,bsize)) == NULL) X xlfail("insufficient vector space"); X } X vect->n_vsize = size; X total += (long) bsize; X } X xlpop(); X return (vect); X} X X/* newnode - allocate a new node */ XLOCAL LVAL newnode(type) X int type; X{ X LVAL nnode; X X /* get a free node */ X if ((nnode = fnodes) == NIL) { X findmem(); X if ((nnode = fnodes) == NIL) X xlabort("insufficient node space"); X } X X /* unlink the node from the free list */ X fnodes = cdr(nnode); X nfree -= 1L; X X /* initialize the new node */ X nnode->n_type = type; X rplacd(nnode,NIL); X X /* return the new node */ X return (nnode); X} X X/* stralloc - allocate memory for a string adding a byte for the terminator */ XLOCAL unsigned char *stralloc(size) X int size; X{ X unsigned char *sptr; X X /* allocate memory for the string copy */ X if ((sptr = (unsigned char *)malloc(size)) == NULL) { X gc(); X if ((sptr = (unsigned char *)malloc(size)) == NULL) X xlfail("insufficient string space"); X } X total += (long)size; X X /* return the new string memory */ X return (sptr); X} X X/* findmem - find more memory by collecting then expanding */ XLOCAL findmem() X{ X gc(); X if (nfree < (long)anodes) X addseg(); X} X X/* gc - garbage collect (only called here and in xlimage.c) */ Xgc() X{ X register LVAL **p,*ap,tmp; X char buf[STRMAX+1]; X LVAL *newfp,fun; X X /* print the start of the gc message */ X if (s_gcflag && getvalue(s_gcflag)) { X sprintf(buf,"[ gc: total %ld, ",nnodes); X stdputstr(buf); X } X X /* mark the obarray, the argument list and the current environment */ X if (obarray) X mark(obarray); X if (xlenv) X mark(xlenv); X if (xlfenv) X mark(xlfenv); X if (xldenv) X mark(xldenv); X X /* mark the evaluation stack */ X for (p = xlstack; p < xlstktop; ++p) X if (tmp = **p) X mark(tmp); X X /* mark the argument stack */ X for (ap = xlargstkbase; ap < xlsp; ++ap) X if (tmp = *ap) X mark(tmp); X X /* sweep memory collecting all unmarked nodes */ X sweep(); X X /* count the gc call */ X ++gccalls; X X /* call the *gc-hook* if necessary */ X if (s_gchook && (fun = getvalue(s_gchook))) { X newfp = xlsp; X pusharg(cvfixnum((FIXTYPE)(newfp - xlfp))); X pusharg(fun); X pusharg(cvfixnum((FIXTYPE)2)); X pusharg(cvfixnum((FIXTYPE)nnodes)); X pusharg(cvfixnum((FIXTYPE)nfree)); X xlfp = newfp; X xlapply(2); X } X X /* print the end of the gc message */ X if (s_gcflag && getvalue(s_gcflag)) { X sprintf(buf,"%ld free ]\n",nfree); X stdputstr(buf); X } X} X X/* mark - mark all accessible nodes */ XLOCAL mark(ptr) X LVAL ptr; X{ X register LVAL this,prev,tmp; X int type,i,n; X X /* initialize */ X prev = NIL; X this = ptr; X X /* mark this list */ X for (;;) { X X /* descend as far as we can */ X while (!(this->n_flags & MARK)) X X /* check cons and unnamed stream nodes */ X if ((type = ntype(this)) == CONS || type == USTREAM) { X if (tmp = car(this)) { X this->n_flags |= MARK|LEFT; X rplaca(this,prev); X } X else if (tmp = cdr(this)) { X this->n_flags |= MARK; X rplacd(this,prev); X } X else { /* both sides nil */ X this->n_flags |= MARK; X break; X } X prev = this; /* step down the branch */ X this = tmp; X } X X /* mark other node types */ X else { X this->n_flags |= MARK; X switch (type) { X case SYMBOL: X case OBJECT: X case VECTOR: X case CLOSURE: X case STRUCT: X for (i = 0, n = getsize(this); --n >= 0; ++i) X if (tmp = getelement(this,i)) X mark(tmp); X break; X } X break; X } X X /* backup to a point where we can continue descending */ X for (;;) X X /* make sure there is a previous node */ X if (prev) { X if (prev->n_flags & LEFT) { /* came from left side */ X prev->n_flags &= ~LEFT; X tmp = car(prev); X rplaca(prev,this); X if (this = cdr(prev)) { X rplacd(prev,tmp); X break; X } X } X else { /* came from right side */ X tmp = cdr(prev); X rplacd(prev,this); X } X this = prev; /* step back up the branch */ X prev = tmp; X } X X /* no previous node, must be done */ X else X return; X } X} X X/* sweep - sweep all unmarked nodes and add them to the free list */ XLOCAL sweep() X{ X SEGMENT *seg; X LVAL p; X int n; X X /* empty the free list */ X fnodes = NIL; X nfree = 0L; X X /* add all unmarked nodes */ X for (seg = segs; seg; seg = seg->sg_next) { X if (seg == fixseg) /* don't sweep the fixnum segment */ X continue; X else if (seg == charseg) /* don't sweep the character segment */ X continue; X p = &seg->sg_nodes[0]; X for (n = seg->sg_size; --n >= 0; ++p) X if (!(p->n_flags & MARK)) { X switch (ntype(p)) { X case STRING: X if (getstring(p) != NULL) { X total -= (long)getslength(p); X free(getstring(p)); X } X break; X case STREAM: X if (getfile(p)) X osclose(getfile(p)); X break; X case SYMBOL: X case OBJECT: X case VECTOR: X case CLOSURE: X case STRUCT: X if (p->n_vsize) { X total -= (long) (p->n_vsize * sizeof(LVAL)); X free(p->n_vdata); X } X break; X } X p->n_type = FREE; X rplaca(p,NIL); X rplacd(p,fnodes); X fnodes = p; X nfree += 1L; X } X else X p->n_flags &= ~MARK; X } X} X X/* addseg - add a segment to the available memory */ XLOCAL int addseg() X{ X SEGMENT *newseg; X LVAL p; X int n; X X /* allocate the new segment */ X if (anodes == 0 || (newseg = newsegment(anodes)) == NULL) X return (FALSE); X X /* add each new node to the free list */ X p = &newseg->sg_nodes[0]; X for (n = anodes; --n >= 0; ++p) { X rplacd(p,fnodes); X fnodes = p; X } X X /* return successfully */ X return (TRUE); X} X X/* newsegment - create a new segment (only called here and in xlimage.c) */ XSEGMENT *newsegment(n) X int n; X{ X SEGMENT *newseg; X X /* allocate the new segment */ X if ((newseg = (SEGMENT *)calloc(1,segsize(n))) == NULL) X return (NULL); X X /* initialize the new segment */ X newseg->sg_size = n; X newseg->sg_next = NULL; X if (segs) X lastseg->sg_next = newseg; X else X segs = newseg; X lastseg = newseg; X X /* update the statistics */ X total += (long)segsize(n); X nnodes += (long)n; X nfree += (long)n; X ++nsegs; X X /* return the new segment */ X return (newseg); X} X X/* stats - print memory statistics */ XLOCAL stats() X{ X sprintf(buf,"Nodes: %ld\n",nnodes); stdputstr(buf); X sprintf(buf,"Free nodes: %ld\n",nfree); stdputstr(buf); X sprintf(buf,"Segments: %d\n",nsegs); stdputstr(buf); X sprintf(buf,"Allocate: %d\n",anodes); stdputstr(buf); X sprintf(buf,"Total: %ld\n",total); stdputstr(buf); X sprintf(buf,"Collections: %d\n",gccalls); stdputstr(buf); X} X X/* xgc - xlisp function to force garbage collection */ XLVAL xgc() X{ X /* make sure there aren't any arguments */ X xllastarg(); X X /* garbage collect */ X gc(); X X /* return nil */ X return (NIL); X} X X/* xexpand - xlisp function to force memory expansion */ XLVAL xexpand() X{ X LVAL num; X int n,i; X X /* get the new number to allocate */ X if (moreargs()) { X num = xlgafixnum(); X n = getfixnum(num); X } X else X n = 1; X xllastarg(); X X /* allocate more segments */ X for (i = 0; i < n; i++) X if (!addseg()) X break; X X /* return the number of segments added */ X return (cvfixnum((FIXTYPE)i)); X} X X/* xalloc - xlisp function to set the number of nodes to allocate */ XLVAL xalloc() X{ X int n,oldn; X LVAL num; X X /* get the new number to allocate */ X num = xlgafixnum(); X n = getfixnum(num); X X /* make sure there aren't any more arguments */ X xllastarg(); X X /* set the new number of nodes to allocate */ X oldn = anodes; X anodes = n; X X /* return the old number */ X return (cvfixnum((FIXTYPE)oldn)); X} X X/* xmem - xlisp function to print memory statistics */ XLVAL xmem() X{ X /* allow one argument for compatiblity with common lisp */ X if (moreargs()) xlgetarg(); X xllastarg(); X X /* print the statistics */ X stats(); X X /* return nil */ X return (NIL); X} X X#ifdef SAVERESTORE X/* xsave - save the memory image */ XLVAL xsave() X{ X unsigned char *name; X X /* get the file name, verbose flag and print flag */ X name = getstring(xlgetfname()); X xllastarg(); X X /* save the memory image */ X return (xlisave(name) ? true : NIL); X} X X/* xrestore - restore a saved memory image */ XLVAL xrestore() X{ X extern jmp_buf top_level; X unsigned char *name; X X /* get the file name, verbose flag and print flag */ X name = getstring(xlgetfname()); X xllastarg(); X X /* restore the saved memory image */ X if (!xlirestore(name)) X return (NIL); X X /* return directly to the top level */ X stdputstr("[ returning to the top level ]\n"); X longjmp(top_level,1); X} X#endif X X/* xlminit - initialize the dynamic memory module */ Xxlminit() X{ X LVAL p; X int i; X X /* initialize our internal variables */ X segs = lastseg = NULL; X nnodes = nfree = total = 0L; X nsegs = gccalls = 0; X anodes = NNODES; X fnodes = NIL; X X /* allocate the fixnum segment */ X if ((fixseg = newsegment(SFIXSIZE)) == NULL) X xlfatal("insufficient memory"); X X /* initialize the fixnum segment */ X p = &fixseg->sg_nodes[0]; X for (i = SFIXMIN; i <= SFIXMAX; ++i) { X p->n_type = FIXNUM; X p->n_fixnum = i; X ++p; X } X X /* allocate the character segment */ X if ((charseg = newsegment(CHARSIZE)) == NULL) X xlfatal("insufficient memory"); X X /* initialize the character segment */ X p = &charseg->sg_nodes[0]; X for (i = CHARMIN; i <= CHARMAX; ++i) { X p->n_type = CHAR; X p->n_chcode = i; X ++p; X } X X /* initialize structures that are marked by the collector */ X obarray = xlenv = xlfenv = xldenv = NIL; X s_gcflag = s_gchook = NIL; X X /* allocate the evaluation stack */ X if ((xlstkbase = (LVAL **)malloc(EDEPTH * sizeof(LVAL *))) == NULL) X xlfatal("insufficient memory"); X xlstack = xlstktop = xlstkbase + EDEPTH; X X /* allocate the argument stack */ X if ((xlargstkbase = (LVAL *)malloc(ADEPTH * sizeof(LVAL))) == NULL) X xlfatal("insufficient memory"); X xlargstktop = xlargstkbase + ADEPTH; X xlfp = xlsp = xlargstkbase; X *xlsp++ = NIL; X} X SHAR_EOF if test 14715 -ne "`wc -c 'xldmem.c'`" then echo shar: error transmitting "'xldmem.c'" '(should have been 14715 characters)' fi echo shar: extracting "'xldmem.h'" '(6120 characters)' if test -f 'xldmem.h' then echo shar: over-writing existing file "'xldmem.h'" fi sed 's/^X//' << \SHAR_EOF > 'xldmem.h' X/* xldmem.h - dynamic memory definitions */ X/* Copyright (c) 1987, by David Michael Betz X All Rights Reserved X Permission is granted for unrestricted non-commercial use */ X X/* small fixnum range */ X#define SFIXMIN (-128) X#define SFIXMAX 255 X#define SFIXSIZE 384 X X/* character range */ X#define CHARMIN 0 X#define CHARMAX 255 X#define CHARSIZE 256 X X/* new node access macros */ X#define ntype(x) ((x)->n_type) X X/* cons access macros */ X#define car(x) ((x)->n_car) X#define cdr(x) ((x)->n_cdr) X#define rplaca(x,y) ((x)->n_car = (y)) X#define rplacd(x,y) ((x)->n_cdr = (y)) X X/* symbol access macros */ X#define getvalue(x) ((x)->n_vdata[0]) X#define setvalue(x,v) ((x)->n_vdata[0] = (v)) X#define getfunction(x) ((x)->n_vdata[1]) X#define setfunction(x,v) ((x)->n_vdata[1] = (v)) X#define getplist(x) ((x)->n_vdata[2]) X#define setplist(x,v) ((x)->n_vdata[2] = (v)) X#define getpname(x) ((x)->n_vdata[3]) X#define setpname(x,v) ((x)->n_vdata[3] = (v)) X#define SYMSIZE 4 X X/* closure access macros */ X#define getname(x) ((x)->n_vdata[0]) X#define setname(x,v) ((x)->n_vdata[0] = (v)) X#define gettype(x) ((x)->n_vdata[1]) X#define settype(x,v) ((x)->n_vdata[1] = (v)) X#define getargs(x) ((x)->n_vdata[2]) X#define setargs(x,v) ((x)->n_vdata[2] = (v)) X#define getoargs(x) ((x)->n_vdata[3]) X#define setoargs(x,v) ((x)->n_vdata[3] = (v)) X#define getrest(x) ((x)->n_vdata[4]) X#define setrest(x,v) ((x)->n_vdata[4] = (v)) X#define getkargs(x) ((x)->n_vdata[5]) X#define setkargs(x,v) ((x)->n_vdata[5] = (v)) X#define getaargs(x) ((x)->n_vdata[6]) X#define setaargs(x,v) ((x)->n_vdata[6] = (v)) X#define getbody(x) ((x)->n_vdata[7]) X#define setbody(x,v) ((x)->n_vdata[7] = (v)) X#define getenv(x) ((x)->n_vdata[8]) X#define setenv(x,v) ((x)->n_vdata[8] = (v)) X#define getfenv(x) ((x)->n_vdata[9]) X#define setfenv(x,v) ((x)->n_vdata[9] = (v)) X#define getlambda(x) ((x)->n_vdata[10]) X#define setlambda(x,v) ((x)->n_vdata[10] = (v)) X#define CLOSIZE 11 X X/* vector access macros */ X#define getsize(x) ((x)->n_vsize) X#define getelement(x,i) ((x)->n_vdata[i]) X#define setelement(x,i,v) ((x)->n_vdata[i] = (v)) X X/* object access macros */ X#define getclass(x) ((x)->n_vdata[0]) X#define getivar(x,i) ((x)->n_vdata[i+1]) X#define setivar(x,i,v) ((x)->n_vdata[i+1] = (v)) X X/* subr/fsubr access macros */ X#define getsubr(x) ((x)->n_subr) X#define getoffset(x) ((x)->n_offset) X X/* fixnum/flonum/char access macros */ X#define getfixnum(x) ((x)->n_fixnum) X#define getflonum(x) ((x)->n_flonum) X#define getchcode(x) ((x)->n_chcode) X X/* string access macros */ X#define getstring(x) ((x)->n_string) X#define getslength(x) ((x)->n_strlen) X X/* file stream access macros */ X#define getfile(x) ((x)->n_fp) X#define setfile(x,v) ((x)->n_fp = (v)) X#define getsavech(x) ((x)->n_savech) X#define setsavech(x,v) ((x)->n_savech = (v)) X X/* unnamed stream access macros */ X#define gethead(x) ((x)->n_car) X#define sethead(x,v) ((x)->n_car = (v)) X#define gettail(x) ((x)->n_cdr) X#define settail(x,v) ((x)->n_cdr = (v)) X X/* node types */ X#define FREE 0 X#define SUBR 1 X#define FSUBR 2 X#define CONS 3 X#define SYMBOL 4 X#define FIXNUM 5 X#define FLONUM 6 X#define STRING 7 X#define OBJECT 8 X#define STREAM 9 X#define VECTOR 10 X#define CLOSURE 11 X#define CHAR 12 X#define USTREAM 13 X#define STRUCT 14 X X/* subr/fsubr node */ X#define n_subr n_info.n_xsubr.xs_subr X#define n_offset n_info.n_xsubr.xs_offset X X/* cons node */ X#define n_car n_info.n_xcons.xc_car X#define n_cdr n_info.n_xcons.xc_cdr X X/* fixnum node */ X#define n_fixnum n_info.n_xfixnum.xf_fixnum X X/* flonum node */ X#define n_flonum n_info.n_xflonum.xf_flonum X/* character node */ X#define n_chcode n_info.n_xchar.xc_chcode X X/* string node */ X#define n_string n_info.n_xstring.xs_string X#define n_strlen n_info.n_xstring.xs_length X X/* stream node */ X#define n_fp n_info.n_xstream.xs_fp X#define n_savech n_info.n_xstream.xs_savech X X/* vector/object node */ X#define n_vsize n_info.n_xvector.xv_size X#define n_vdata n_info.n_xvector.xv_data X X/* node structure */ Xtypedef struct node { X char n_type; /* type of node */ X char n_flags; /* flag bits */ X union ninfo { /* value */ X struct xsubr { /* subr/fsubr node */ X struct node *(*xs_subr)(); /* function pointer */ X int xs_offset; /* offset into funtab */ X } n_xsubr; X struct xcons { /* cons node */ X struct node *xc_car; /* the car pointer */ X struct node *xc_cdr; /* the cdr pointer */ X } n_xcons; X struct xfixnum { /* fixnum node */ X FIXTYPE xf_fixnum; /* fixnum value */ X } n_xfixnum; X struct xflonum { /* flonum node */ X FLOTYPE xf_flonum; /* flonum value */ X } n_xflonum; X struct xchar { /* character node */ X int xc_chcode; /* character code */ X } n_xchar; X struct xstring { /* string node */ X int xs_length; /* string length */ X unsigned char *xs_string; /* string pointer */ X } n_xstring; X struct xstream { /* stream node */ X FILE *xs_fp; /* the file pointer */ X int xs_savech; /* lookahead character */ X } n_xstream; X struct xvector { /* vector/object/symbol/structure node */ X int xv_size; /* vector size */ X struct node **xv_data; /* vector data */ X } n_xvector; X } n_info; X} *LVAL; X X/* memory segment structure definition */ Xtypedef struct segment { X int sg_size; X struct segment *sg_next; X struct node sg_nodes[1]; X} SEGMENT; X X/* memory allocation functions */ Xextern LVAL cons(); /* (cons x y) */ Xextern LVAL cvsymbol(); /* convert a string to a symbol */ Xextern LVAL cvstring(); /* convert a string */ Xextern LVAL cvfile(); /* convert a FILE * to a file */ Xextern LVAL cvsubr(); /* convert a function to a subr/fsubr */ Xextern LVAL cvfixnum(); /* convert a fixnum */ Xextern LVAL cvflonum(); /* convert a flonum */ Xextern LVAL cvchar(); /* convert a character */ X Xextern LVAL newstring(); /* create a new string */ Xextern LVAL newvector(); /* create a new vector */ Xextern LVAL newobject(); /* create a new object */ Xextern LVAL newclosure(); /* create a new closure */ Xextern LVAL newustream(); /* create a new unnamed stream */ Xextern LVAL newstruct(); /* create a new structure */ X SHAR_EOF if test 6120 -ne "`wc -c 'xldmem.h'`" then echo shar: error transmitting "'xldmem.h'" '(should have been 6120 characters)' fi echo shar: extracting "'xleval.c'" '(19240 characters)' if test -f 'xleval.c' then echo shar: over-writing existing file "'xleval.c'" fi sed 's/^X//' << \SHAR_EOF > 'xleval.c' X/* xleval - xlisp evaluator */ X/* Copyright (c) 1985, by David Michael Betz X All Rights Reserved X Permission is granted for unrestricted non-commercial use */ X X#include "xlisp.h" X X/* macro to check for lambda list keywords */ X#define iskey(s) ((s) == lk_optional \ X || (s) == lk_rest \ X || (s) == lk_key \ X || (s) == lk_aux \ X || (s) == lk_allow_other_keys) X X/* macros to handle tracing */ X#define trenter(sym,argc,argv) {if (sym) doenter(sym,argc,argv);} X#define trexit(sym,val) {if (sym) doexit(sym,val);} X X/* external variables */ Xextern LVAL xlenv,xlfenv,xldenv,xlvalue,true; Xextern LVAL lk_optional,lk_rest,lk_key,lk_aux,lk_allow_other_keys; Xextern LVAL s_evalhook,s_applyhook,s_tracelist; Xextern LVAL s_lambda,s_macro; Xextern LVAL s_unbound; Xextern int xlsample; Xextern char buf[]; X X/* forward declarations */ XFORWARD LVAL xlxeval(); XFORWARD LVAL evalhook(); XFORWARD LVAL evform(); XFORWARD LVAL evfun(); X X/* xleval - evaluate an xlisp expression (checking for *evalhook*) */ XLVAL xleval(expr) X LVAL expr; X{ X /* check for control codes */ X if (--xlsample <= 0) { X xlsample = SAMPLE; X oscheck(); X } X X /* check for *evalhook* */ X if (getvalue(s_evalhook)) X return (evalhook(expr)); X X /* check for nil */ X if (null(expr)) X return (NIL); X X /* dispatch on the node type */ X switch (ntype(expr)) { X case CONS: X return (evform(expr)); X case SYMBOL: X return (xlgetvalue(expr)); X default: X return (expr); X } X} X X/* xlevalenv - evaluate an expression in a specified environment */ XLVAL xlevalenv(expr,env,fenv) X LVAL expr,env,fenv; X{ X LVAL oldenv,oldfenv,val; X X /* protect some pointers */ X xlstkcheck(2); X xlsave(oldenv); X xlsave(oldfenv); X X /* establish the new environment */ X oldenv = xlenv; X oldfenv = xlfenv; X xlenv = env; X xlfenv = fenv; X X /* evaluate the expression */ X val = xleval(expr); X X /* restore the environment */ X xlenv = oldenv; X xlfenv = oldfenv; X X /* restore the stack */ X xlpopn(2); X X /* return the result value */ X return (val); X} X X/* xlxeval - evaluate an xlisp expression (bypassing *evalhook*) */ XLVAL xlxeval(expr) X LVAL expr; X{ X /* check for nil */ X if (null(expr)) X return (NIL); X X /* dispatch on node type */ X switch (ntype(expr)) { X case CONS: X return (evform(expr)); X case SYMBOL: X return (xlgetvalue(expr)); X default: X return (expr); X } X} X X/* xlapply - apply a function to arguments (already on the stack) */ XLVAL xlapply(argc) X int argc; X{ X LVAL *oldargv,fun,val; X int oldargc; X X /* get the function */ X fun = xlfp[1]; X X /* get the functional value of symbols */ X if (symbolp(fun)) { X while ((val = getfunction(fun)) == s_unbound) X xlfunbound(fun); X fun = xlfp[1] = val; X } X X /* check for nil */ X if (null(fun)) X xlerror("bad function",fun); X X /* dispatch on node type */ X switch (ntype(fun)) { X case SUBR: X oldargc = xlargc; X oldargv = xlargv; X xlargc = argc; X xlargv = xlfp + 3; X val = (*getsubr(fun))(); X xlargc = oldargc; X xlargv = oldargv; X break; X case CONS: X if (!consp(cdr(fun))) X xlerror("bad function",fun); X if (car(fun) == s_lambda) X fun = xlclose(NIL, X s_lambda, X car(cdr(fun)), X cdr(cdr(fun)), X xlenv,xlfenv); X else X xlerror("bad function",fun); X /**** fall through into the next case ****/ X case CLOSURE: X if (gettype(fun) != s_lambda) X xlerror("bad function",fun); X val = evfun(fun,argc,xlfp+3); X break; X default: X xlerror("bad function",fun); X } X X /* remove the call frame */ X xlsp = xlfp; X xlfp = xlfp - (int)getfixnum(*xlfp); X X /* return the function value */ X return (val); X} X X/* evform - evaluate a form */ XLOCAL LVAL evform(form) X LVAL form; X{ X LVAL fun,args,val,type; X LVAL tracing=NIL; X LVAL *argv; X int argc; X X /* protect some pointers */ X xlstkcheck(2); X xlsave(fun); X xlsave(args); X X /* get the function and the argument list */ X fun = car(form); X args = cdr(form); X X /* get the functional value of symbols */ X if (symbolp(fun)) { X if (getvalue(s_tracelist) && member(fun,getvalue(s_tracelist))) X tracing = fun; X fun = xlgetfunction(fun); X } X X /* check for nil */ X if (null(fun)) X xlerror("bad function",NIL); X X /* dispatch on node type */ X switch (ntype(fun)) { X case SUBR: X argv = xlargv; X argc = xlargc; X xlargc = evpushargs(fun,args); X xlargv = xlfp + 3; X trenter(tracing,xlargc,xlargv); X val = (*getsubr(fun))(); X trexit(tracing,val); X xlsp = xlfp; X xlfp = xlfp - (int)getfixnum(*xlfp); X xlargv = argv; X xlargc = argc; X break; X case FSUBR: X argv = xlargv; X argc = xlargc; X xlargc = pushargs(fun,args); X xlargv = xlfp + 3; X val = (*getsubr(fun))(); X xlsp = xlfp; X xlfp = xlfp - (int)getfixnum(*xlfp); X xlargv = argv; X xlargc = argc; X break; X case CONS: X if (!consp(cdr(fun))) X xlerror("bad function",fun); X if ((type = car(fun)) == s_lambda) X fun = xlclose(NIL, X s_lambda, X car(cdr(fun)), X cdr(cdr(fun)), X xlenv,xlfenv); X else X xlerror("bad function",fun); X /**** fall through into the next case ****/ X case CLOSURE: X if (gettype(fun) == s_lambda) { X argc = evpushargs(fun,args); X argv = xlfp + 3; X trenter(tracing,argc,argv); X val = evfun(fun,argc,argv); X trexit(tracing,val); X xlsp = xlfp; X xlfp = xlfp - (int)getfixnum(*xlfp); X } X else { X macroexpand(fun,args,&fun); X val = xleval(fun); X } X break; X default: X xlerror("bad function",fun); X } X X /* restore the stack */ X xlpopn(2); X X /* return the result value */ X return (val); X} X X/* xlexpandmacros - expand macros in a form */ XLVAL xlexpandmacros(form) X LVAL form; X{ X LVAL fun,args; X X /* protect some pointers */ X xlstkcheck(3); X xlprotect(form); X xlsave(fun); X xlsave(args); X X /* expand until the form isn't a macro call */ X while (consp(form)) { X fun = car(form); /* get the macro name */ X args = cdr(form); /* get the arguments */ X if (!symbolp(fun) || !fboundp(fun)) X break; X fun = xlgetfunction(fun); /* get the expansion function */ X if (!macroexpand(fun,args,&form)) X break; X } X X /* restore the stack and return the expansion */ X xlpopn(3); X return (form); X} X X/* macroexpand - expand a macro call */ Xint macroexpand(fun,args,pval) X LVAL fun,args,*pval; X{ X LVAL *argv; X int argc; X X /* make sure it's really a macro call */ X if (!closurep(fun) || gettype(fun) != s_macro) X return (FALSE); X X /* call the expansion function */ X argc = pushargs(fun,args); X argv = xlfp + 3; X *pval = evfun(fun,argc,argv); X xlsp = xlfp; X xlfp = xlfp - (int)getfixnum(*xlfp); X return (TRUE); X} X X/* evalhook - call the evalhook function */ XLOCAL LVAL evalhook(expr) X LVAL expr; X{ X LVAL *newfp,olddenv,val; X X /* create the new call frame */ X newfp = xlsp; X pusharg(cvfixnum((FIXTYPE)(newfp - xlfp))); X pusharg(getvalue(s_evalhook)); X pusharg(cvfixnum((FIXTYPE)2)); X pusharg(expr); X pusharg(cons(xlenv,xlfenv)); X xlfp = newfp; X X /* rebind the hook functions to nil */ X olddenv = xldenv; X xldbind(s_evalhook,NIL); X xldbind(s_applyhook,NIL); X X /* call the hook function */ X val = xlapply(2); X X /* unbind the symbols */ X xlunbind(olddenv); X X /* return the value */ X return (val); X} X X/* evpushargs - evaluate and push a list of arguments */ XLOCAL int evpushargs(fun,args) X LVAL fun,args; X{ X LVAL *newfp; X int argc; X X /* protect the argument list */ X xlprot1(args); X X /* build a new argument stack frame */ X newfp = xlsp; X pusharg(cvfixnum((FIXTYPE)(newfp - xlfp))); X pusharg(fun); X pusharg(NIL); /* will be argc */ X X /* evaluate and push each argument */ X for (argc = 0; consp(args); args = cdr(args), ++argc) X pusharg(xleval(car(args))); X X /* establish the new stack frame */ X newfp[2] = cvfixnum((FIXTYPE)argc); X xlfp = newfp; X X /* restore the stack */ X xlpop(); X X /* return the number of arguments */ X return (argc); X} X X/* pushargs - push a list of arguments */ Xint pushargs(fun,args) X LVAL fun,args; X{ X LVAL *newfp; X int argc; X X /* build a new argument stack frame */ X newfp = xlsp; X pusharg(cvfixnum((FIXTYPE)(newfp - xlfp))); X pusharg(fun); X pusharg(NIL); /* will be argc */ X X /* push each argument */ X for (argc = 0; consp(args); args = cdr(args), ++argc) X pusharg(car(args)); X X /* establish the new stack frame */ X newfp[2] = cvfixnum((FIXTYPE)argc); X xlfp = newfp; X X /* return the number of arguments */ X return (argc); X} X X/* makearglist - make a list of the remaining arguments */ XLVAL makearglist(argc,argv) X int argc; LVAL *argv; X{ X LVAL list,this,last; X xlsave1(list); X for (last = NIL; --argc >= 0; last = this) { X this = cons(*argv++,NIL); X if (last) rplacd(last,this); X else list = this; X last = this; X } X xlpop(); X return (list); X} X X/* evfun - evaluate a function */ XLOCAL LVAL evfun(fun,argc,argv) X LVAL fun; int argc; LVAL *argv; X{ X LVAL oldenv,oldfenv,cptr,name,val; X CONTEXT cntxt; X X /* protect some pointers */ X xlstkcheck(3); X xlsave(oldenv); X xlsave(oldfenv); X xlsave(cptr); X X /* create a new environment frame */ X oldenv = xlenv; X oldfenv = xlfenv; X xlenv = xlframe(getenv(fun)); X xlfenv = getfenv(fun); X X /* bind the formal parameters */ X xlabind(fun,argc,argv); X X /* setup the implicit block */ X if (name = getname(fun)) X xlbegin(&cntxt,CF_RETURN,name); X X /* execute the block */ X if (name && setjmp(cntxt.c_jmpbuf)) X val = xlvalue; X else X for (val = NIL, cptr = getbody(fun); consp(cptr); cptr = cdr(cptr)) X val = xleval(car(cptr)); X X /* finish the block context */ X if (name) X xlend(&cntxt); X X /* restore the environment */ X xlenv = oldenv; X xlfenv = oldfenv; X X /* restore the stack */ X xlpopn(3); X X /* return the result value */ X return (val); X} X X/* xlclose - create a function closure */ XLVAL xlclose(name,type,fargs,body,env,fenv) X LVAL name,type,fargs,body,env,fenv; X{ X LVAL closure,key,arg,def,svar,new,last; X char keyname[STRMAX+2]; X X /* protect some pointers */ X xlsave1(closure); X X /* create the closure object */ X closure = newclosure(name,type,env,fenv); X setlambda(closure,fargs); X setbody(closure,body); X X /* handle each required argument */ X last = NIL; X while (consp(fargs) && (arg = car(fargs)) && !iskey(arg)) { X X /* make sure the argument is a symbol */ X if (!symbolp(arg)) X badarglist(); X X /* create a new argument list entry */ X new = cons(arg,NIL); X X /* link it into the required argument list */ X if (last) X rplacd(last,new); X else X setargs(closure,new); X last = new; X X /* move the formal argument list pointer ahead */ X fargs = cdr(fargs); X } X X /* check for the '&optional' keyword */ X if (consp(fargs) && car(fargs) == lk_optional) { X fargs = cdr(fargs); X X /* handle each optional argument */ X last = NIL; X while (consp(fargs) && (arg = car(fargs)) && !iskey(arg)) { X X /* get the default expression and specified-p variable */ X def = svar = NIL; X if (consp(arg)) { X if (def = cdr(arg)) X if (consp(def)) { X if (svar = cdr(def)) X if (consp(svar)) { X svar = car(svar); X if (!symbolp(svar)) X badarglist(); X } X else X badarglist(); X def = car(def); X } X else X badarglist(); X arg = car(arg); X } X X /* make sure the argument is a symbol */ X if (!symbolp(arg)) X badarglist(); X X /* create a fully expanded optional expression */ X new = cons(cons(arg,cons(def,cons(svar,NIL))),NIL); X X /* link it into the optional argument list */ X if (last) X rplacd(last,new); X else X setoargs(closure,new); X last = new; X X /* move the formal argument list pointer ahead */ X fargs = cdr(fargs); X } X } X X /* check for the '&rest' keyword */ X if (consp(fargs) && car(fargs) == lk_rest) { X fargs = cdr(fargs); X X /* get the &rest argument */ X if (consp(fargs) && (arg = car(fargs)) && !iskey(arg) && symbolp(arg)) X setrest(closure,arg); X else X badarglist(); X X /* move the formal argument list pointer ahead */ X fargs = cdr(fargs); X } X X /* check for the '&key' keyword */ X if (consp(fargs) && car(fargs) == lk_key) { X fargs = cdr(fargs); X X /* handle each key argument */ X last = NIL; X while (consp(fargs) && (arg = car(fargs)) && !iskey(arg)) { X X /* get the default expression and specified-p variable */ X def = svar = NIL; X if (consp(arg)) { X if (def = cdr(arg)) X if (consp(def)) { X if (svar = cdr(def)) X if (consp(svar)) { X svar = car(svar); X if (!symbolp(svar)) X badarglist(); X } X else X badarglist(); X def = car(def); X } X else X badarglist(); X arg = car(arg); X } X X /* get the keyword and the variable */ X if (consp(arg)) { X key = car(arg); X if (!symbolp(key)) X badarglist(); X if (arg = cdr(arg)) X if (consp(arg)) X arg = car(arg); X else X badarglist(); X } X else if (symbolp(arg)) { X strcpy(keyname,":"); X strcat(keyname,getstring(getpname(arg))); X key = xlenter(keyname); X } X X /* make sure the argument is a symbol */ X if (!symbolp(arg)) X badarglist(); X X /* create a fully expanded key expression */ X new = cons(cons(key,cons(arg,cons(def,cons(svar,NIL)))),NIL); X X /* link it into the optional argument list */ X if (last) X rplacd(last,new); X else X setkargs(closure,new); X last = new; X X /* move the formal argument list pointer ahead */ X fargs = cdr(fargs); X } X } X X /* check for the '&allow-other-keys' keyword */ X if (consp(fargs) && car(fargs) == lk_allow_other_keys) X fargs = cdr(fargs); /* this is the default anyway */ X X /* check for the '&aux' keyword */ X if (consp(fargs) && car(fargs) == lk_aux) { X fargs = cdr(fargs); X X /* handle each aux argument */ X last = NIL; X while (consp(fargs) && (arg = car(fargs)) && !iskey(arg)) { X X /* get the initial value */ X def = NIL; X if (consp(arg)) { X if (def = cdr(arg)) X if (consp(def)) X def = car(def); X else X badarglist(); X arg = car(arg); X } X X /* make sure the argument is a symbol */ X if (!symbolp(arg)) X badarglist(); X X /* create a fully expanded aux expression */ X new = cons(cons(arg,cons(def,NIL)),NIL); X X /* link it into the aux argument list */ X if (last) X rplacd(last,new); X else X setaargs(closure,new); X last = new; X X /* move the formal argument list pointer ahead */ X fargs = cdr(fargs); X } X } X X /* make sure this is the end of the formal argument list */ X if (fargs) X badarglist(); X X /* restore the stack */ X xlpop(); X X /* return the new closure */ X return (closure); X} X X/* xlabind - bind the arguments for a function */ Xxlabind(fun,argc,argv) X LVAL fun; int argc; LVAL *argv; X{ X LVAL *kargv,fargs,key,arg,def,svar,p; X int rargc,kargc; X X /* protect some pointers */ X xlsave1(def); X X /* bind each required argument */ X for (fargs = getargs(fun); fargs; fargs = cdr(fargs)) { X X /* make sure there is an actual argument */ X if (--argc < 0) X xlfail("too few arguments"); X X /* bind the formal variable to the argument value */ X xlbind(car(fargs),*argv++); X } X X /* bind each optional argument */ X for (fargs = getoargs(fun); fargs; fargs = cdr(fargs)) { X X /* get argument, default and specified-p variable */ X p = car(fargs); X arg = car(p); p = cdr(p); X def = car(p); p = cdr(p); X svar = car(p); X X /* bind the formal variable to the argument value */ X if (--argc >= 0) { X xlbind(arg,*argv++); X if (svar) xlbind(svar,true); X } X X /* bind the formal variable to the default value */ X else { X if (def) def = xleval(def); X xlbind(arg,def); X if (svar) xlbind(svar,NIL); X } X } X X /* save the count of the &rest of the argument list */ X rargc = argc; X X /* handle '&rest' argument */ X if (arg = getrest(fun)) { X def = makearglist(argc,argv); X xlbind(arg,def); X argc = 0; X } X X /* handle '&key' arguments */ X if (fargs = getkargs(fun)) { X for (; fargs; fargs = cdr(fargs)) { X X /* get keyword, argument, default and specified-p variable */ X p = car(fargs); X key = car(p); p = cdr(p); X arg = car(p); p = cdr(p); X def = car(p); p = cdr(p); X svar = car(p); X X /* look for the keyword in the actual argument list */ X for (kargv = argv, kargc = rargc; (kargc -= 2) >= 0; kargv += 2) X if (*kargv == key) X break; X X /* bind the formal variable to the argument value */ X if (kargc >= 0) { X xlbind(arg,*++kargv); X if (svar) xlbind(svar,true); X } X X /* bind the formal variable to the default value */ X else { X if (def) def = xleval(def); X xlbind(arg,def); X if (svar) xlbind(svar,NIL); X } X } X argc = 0; X } X X /* check for the '&aux' keyword */ X for (fargs = getaargs(fun); fargs; fargs = cdr(fargs)) { X X /* get argument and default */ X p = car(fargs); X arg = car(p); p = cdr(p); X def = car(p); X X /* bind the auxiliary variable to the initial value */ X if (def) def = xleval(def); X xlbind(arg,def); X } X X /* make sure there aren't too many arguments */ X if (argc > 0) X xlfail("too many arguments"); X X /* restore the stack */ X xlpop(); X} X X/* doenter - print trace information on function entry */ XLOCAL doenter(sym,argc,argv) X LVAL sym; int argc; LVAL *argv; X{ X extern int xltrcindent; X int i; X X /* indent to the current trace level */ X for (i = 0; i < xltrcindent; ++i) X trcputstr(" "); X ++xltrcindent; X X /* display the function call */ X sprintf(buf,"Entering: %s, Argument list: (",getstring(getpname(sym))); X trcputstr(buf); X while (--argc >= 0) { X trcprin1(*argv++); X if (argc) trcputstr(" "); X } X trcputstr(")\n"); X} X X/* doexit - print trace information for function/macro exit */ XLOCAL doexit(sym,val) X LVAL sym,val; X{ X extern int xltrcindent; X int i; X X /* indent to the current trace level */ X --xltrcindent; X for (i = 0; i < xltrcindent; ++i) X trcputstr(" "); X X /* display the function value */ X sprintf(buf,"Exiting: %s, Value: ",getstring(getpname(sym))); X trcputstr(buf); X trcprin1(val); X trcputstr("\n"); X} X X/* member - is 'x' a member of 'list'? */ XLOCAL int member(x,list) X LVAL x,list; X{ X for (; consp(list); list = cdr(list)) X if (x == car(list)) X return (TRUE); X return (FALSE); X} X X/* xlunbound - signal an unbound variable error */ Xxlunbound(sym) X LVAL sym; X{ X xlcerror("try evaluating symbol again","unbound variable",sym); X} X X/* xlfunbound - signal an unbound function error */ Xxlfunbound(sym) X LVAL sym; X{ X xlcerror("try evaluating symbol again","unbound function",sym); X} X X/* xlstkoverflow - signal a stack overflow error */ Xxlstkoverflow() X{ X xlabort("evaluation stack overflow"); X} X X/* xlargstkoverflow - signal an argument stack overflow error */ Xxlargstkoverflow() X{ X xlabort("argument stack overflow"); X} X X/* badarglist - report a bad argument list error */ XLOCAL badarglist() X{ X xlfail("bad formal argument list"); X} SHAR_EOF if test 19240 -ne "`wc -c 'xleval.c'`" then echo shar: error transmitting "'xleval.c'" '(should have been 19240 characters)' fi # End of shell archive exit 0 -- Gary Murphy uunet!mitel!sce!cognos!garym (garym%cognos.uucp@uunet.uu.net) (613) 738-1338 x5537 Cognos Inc. P.O. Box 9707 Ottawa K1G 3N3 "There are many things which do not concern the process" - Joan of Arc