[net.sources] Modified XLISP, part 2 of 5

john@x.UUCP (John Woods) (08/27/84)

This represents part 2 of 5 of my modified XLISP.  Tear at the dotted line,
and run "sh" over it to extract.

Thanks to Dave Betz for providing the original XLISP.
________________________________________________________________
echo extract with /bin/sh, not /bin/csh
echo x xleval.c
sed -n -e 's/^X//p' > xleval.c << '!Funky!Stuff!'
X			  /* XLISP evaluation module */
X
X#ifdef CI_86
X#include "a:stdio.h"
X#include "xlisp.h"
X#endif
X
X
X#ifdef AZTEC
X#include "a:stdio.h"
X#include "a:setjmp.h"
X#include "xlisp.h"
X#endif
X
X#ifdef unix
X#include <stdio.h>
X#include <setjmp.h>
X#include "xlisp.h"
X#endif
X
X
X			     /* global variables */
X    struct node *xlstack;
X				/* trace stack */
X    static struct node *trace_stack[TDEPTH];
X    static int trace_pointer = -1;
X
X			    /* external variables */
X    extern struct node *self;
X    extern struct node *xlenv;
X    extern struct node *Lambda, *Subrprop, *Fsubrprop, *Exprop, *Fexprop,
X				*Macprop;
X    extern struct node *xlget();
X
X			      /* local variables */
X    static struct node *slash;
X    static struct node *argatom;
X
X#ifdef HACK
X	   /* forward declarations (the extern hack is for decusc) */
X    extern struct node *evlist();
X    extern struct node *evsym();
X    extern struct node *evfun();
X#endif
X
X		    /***************************************
X		    *  eval - the builtin function 'eval'  *
X		    ***************************************/
X
Xstatic struct node *eval(args)
X    struct node *args;
X{
X    struct node *oldstk,expr,*val;
X
X    oldstk = xlsave(&expr,NULL);                 /* Create new stack frame */
X
X    expr.n_ptr = xlarg(&args);                   /* Expression to evaluate */
X    xllastarg(args);                             /* No more args ! */
X
X    val = xleval(expr.n_ptr);                    /* Do evaluation */
X
X    xlstack = oldstk;                            /* Restore old stack frame */
X    return (val);
X}
X
X		   /******************************************
X		   *  xleval - evaluate an xlisp expression  *
X		   ******************************************/
X
X
Xstruct node *xleval(expr)
X    struct node *expr;
X{
X    if (expr == NULL)                            /* Null evaluates to null */
X	return (NULL);
X
X    switch (expr->n_type)                        /* Value type */
X    {
X    case LIST:
X	    return (evlist(expr));
X
X    case SYM:
X	    return (evsym(expr));
X
X    case INT:
X    case STR:
X    case SUBR:
X    case FSUBR:
X    case REAL:
X	    return (expr);
X
X    default:
X	    xlfail("can't evaluate expression");
X    }
X}
X
X		     /*************************************
X		     *  xlsave - save nodes on the stack  *
X		     *************************************/
X
Xstruct node *xlsave(n)
X    struct node *n;
X{
X    struct node **nptr,*oldstk;
X
X    oldstk = xlstack;                            /* Save old stack pointer */
X
X    for (nptr = &n; *nptr != NULL; nptr++)       /* Save for each node */
X    {
X	(*nptr)->n_type = LIST;
X	(*nptr)->n_listvalue = NULL;
X	(*nptr)->n_listnext = xlstack;
X	xlstack = *nptr;
X    }
X
X    return (oldstk);                             /* Return old stack pointer */
X}
X
X			/******************************
X			 * funcall - builtin func.    *
X			 ******************************/
Xstatic struct node *funcall(args)
X    struct node *args;
X{
X	struct node *oldstk,fun,arglist, *val;
X
X	oldstk = xlsave(&fun,&arglist,NULL);
X	fun.n_ptr = xlarg(&args);
X	val = xlapply(fun.n_ptr,args);
X	xlstack = oldstk;
X	return val;
X}
X
X
X			 /*****************************
X			 *  apply - builtin function  *
X			 *****************************/
X
Xstatic struct node *apply(args)
X    struct node *args;
X{
X	struct node *oldstk,fun,arglist, *val;
X
X	oldstk = xlsave(&fun,&arglist,NULL);
X	fun.n_ptr = xlarg(&args);
X	arglist.n_ptr = xlarg(&args);
X	xllastarg(args);
X	val = xlapply(fun.n_ptr,arglist.n_ptr);
X	xlstack = oldstk;
X	return val;
X}
X
Xstruct node *xlapply(funp,arglist)
Xstruct node *funp,*arglist;
X{
X    struct node *val,*oldstk,nptr;
X
X    oldstk = xlsave(&nptr,NULL);
X
X    nptr.n_ptr = newnode(LIST);			/* cons up trace entry */
X    nptr.n_ptr->n_listvalue = funp;
X    nptr.n_ptr->n_listnext = arglist;
X
X    tpush(nptr.n_ptr);                          /* Add trace entry */
X
X    if (funp == NULL) xlfail("null function");
X    if (funp->n_type == SYM)
X    {	if ((funp = evsym(funp)) == NULL
X	&&  (funp = xlget(funp,Subrprop)) == NULL
X	&&  (funp = xlget(funp,Fsubrprop)) == NULL
X	&&  (funp = xlget(funp,Exprop)) == NULL
X	&&  (funp = xlget(funp,Exprop)) == NULL
X	&&  (funp = xlget(funp,Macprop)) == NULL)
X		xlfail("null function");
X    }
X
X    switch (funp->n_type)                   /* Evaluate function */
X    {
X    case FSUBR:
X    case SUBR:
X	    val = (*funp->n_subr)(arglist);
X	    break;
X
X    case LIST:
X	    val = evfun(funp,arglist);
X	    break;
X
X    case OBJ:
X	    val = xlsend(funp,arglist);
X	    break;
X
X    default:
XBadFun:
X	    xlfail("bad function");
X    }
X
X    xlstack = oldstk;                            /* Restore old stack frame */
X    tpop();                                      /* Remove trace entry */
X    return (val);                                /* and return result value */
X}
X			 /*****************************
X			 *  evlist - evaluate a list  *
X			 *****************************/
X
Xstatic struct node *evlist(nptr)
X    struct node *nptr;
X{
X    struct node *oldstk,fun,args,*val, *funp, formarg;
X    int funny = 0, macro=0;
X
X    oldstk = xlsave(&fun,&args,&formarg,NULL);  /* Creat a stack frame */
X
X    fun.n_ptr = nptr->n_listvalue;               /* Get function and arg list*/
X    args.n_ptr = nptr->n_listnext;
X
X    tpush(nptr);                                 /* Add trace entry */
X
X    if (fun.n_ptr == Lambda)		/* lambda form is self-literal */
X    {   
X	val = nptr;
X	goto out;
X    }
X
X	/* get a function from the first expression */
X    if ( fun.n_ptr->n_type == SYM) {
X	if ((funp = xlget(fun.n_ptr,Subrprop)) 
X	||  ((funp = xlget(fun.n_ptr,Fsubrprop)) && (funny=1))
X	||  (funp = xlget(fun.n_ptr,Exprop))
X	||  ((funp = xlget(fun.n_ptr,Fexprop)) && (funny=1))
X	||  ((funp = xlget(fun.n_ptr,Macprop)) && (macro=1)))
X	{	fun.n_ptr = funp;
X		goto doit;
X	}
X    }
X	/* last resort: evaluation */
X    if ((fun.n_ptr = xleval(fun.n_ptr)) == NULL)
X	xlfail("null function");
X
Xdoit:
X    switch (fun.n_ptr->n_type)                   /* Evaluate function */
X    {
X    case SUBR:
X	    if (!funny) args.n_ptr = xlevlis(args.n_ptr);
X	    /* fall through to raw apply code */
X    case FSUBR:
X	    val = (*fun.n_ptr->n_subr)(args.n_ptr);
X	    break;
X
X    case LIST:
X		/* macros and fexprs get a single argument:
X		   macro: the original form
X		   fexpr: the actual parameters (unevaluated)
X		 */
X	    if (funny || macro) {
X		formarg.n_ptr = newnode(LIST);
X		formarg.n_ptr->n_listvalue = (macro? nptr : args.n_ptr);
X	    } else {
X		formarg.n_ptr = xlevlis(args.n_ptr);
X	    }
X	    val = evfun(fun.n_ptr,formarg.n_ptr);
X	    if (macro)
X		val = xleval(val);
X	    break;
X
X    case OBJ:
X	    val = xlsend(fun.n_ptr,args.n_ptr);
X	    break;
X
X    default:
X	    xlfail("bad function");
X    }
Xout:
X    xlstack = oldstk;                            /* Restore old stack frame */
X    tpop();                                      /* Remove trace entry */
X    return (val);                                /* and return result value */
X}
X
X		 /*****************************************
X		 *  evlis - evaluate a list of arguments  *
X		 ******************************************/
X
Xstruct node *xlevlis(args)
X	struct node *args;
X{
X    struct node *oldstk,arg,list,val,*last,*lptr;
X
X    oldstk = xlsave(&arg,&list,&val,NULL);
X    arg.n_ptr = args;
X
X    for (last = NULL; arg.n_ptr != NULL; last = lptr)
X    {
X	val.n_ptr = xlevarg(&arg.n_ptr);
X	lptr = newnode(LIST);
X	if (last == NULL)
X	    list.n_ptr = lptr;
X	else
X	    last->n_listnext = lptr;
X	lptr->n_listvalue = val.n_ptr;
X    }
X
X    xlstack = oldstk;
X    return (list.n_ptr);
X}
X
X			 /******************************
X			 *  evsym - evaluate a symbol  *
X			 ******************************/
X
Xstatic struct node *evsym(sym)
X    struct node *sym;
X{
X    struct node *lptr;
X
X    if ((lptr = xlobsym(sym)) != NULL)           /* Check for current object */
X	return (lptr->n_listvalue);
X    else
X	return (sym->n_symvalue);
X}
X
X
X			/********************************
X			*  evfun - evaluate a function  *
X			********************************/
X
Xstatic struct node *evfun(fun,args)
X    struct node *fun,*args;
X{
X    struct node *oldenv,*oldstk,cptr,*fargs,*val;
X    int lexpr = 0;
X
X    oldstk = xlsave(&cptr,NULL);                 /* Creat a new stack frame */
X
X    if (fun->n_listvalue != Lambda)
X	xlfail("Bad functional argument");
X    fun = fun->n_listnext;
X    /* get the formal argument list */
X    if ((fargs = fun->n_listvalue) != NULL && fargs->n_type != LIST)
X    {	if (fargs->n_type != SYM)
X		xlfail("bad argument list");
X	lexpr = 1;
X    }
X
X    oldenv = xlenv;                              /*Bind the formal parameters*/
X    if (lexpr)
X	xlLbind(fargs,args);
X    else
X	xlabind(fargs,args);
X    xlfixbindings(oldenv);
X
X    for (cptr.n_ptr = fun->n_listnext; cptr.n_ptr != NULL; )    /* execute */
X	val = xlevarg(&cptr.n_ptr);	/* eval forms of body */
X
X    xlunbind(oldenv);                            /* Restore environment */
X    if (lexpr)	/* pop lexpr stack */
X	xlputprop(argatom,xlget(argatom,argatom)->n_listnext,argatom);
X    xlstack = oldstk;                            /* ..then the stack frame */
X    return (val);                                /* ...and return result */
X}
X
X		/****************************************
X		 * xlLbind - bind arguments for a lexpr *
X		 ****************************************/
XxlLbind(farg,arglist) struct node *farg, *arglist;
X{
X    struct node *oldstk,al,num,*ptr;
X    int i;
X
X    oldstk = xlsave(&num,&al,NULL);      /* Create a stack frame */
X
X    /* step one: count the arguments */
X    for (i = 0, ptr = arglist; ptr != NULL; ptr = ptr->n_listnext, i++)
X	;
X
X    num.n_ptr = newnode(INT);
X    num.n_ptr->n_int = i;
X
X    xlbind(farg,num.n_ptr);
X
X    /* now leave arg list where it will be handy */
X    al.n_ptr = newnode(LIST);
X    al.n_ptr->n_listnext = xlget(argatom,argatom);
X    al.n_ptr->n_listvalue = arglist;
X    xlputprop(argatom, al.n_ptr, argatom);
X
X    xlstack = oldstk;
X}
X
X		/************************************************
X		*  xlabind - bind the arguments for a function  *
X		************************************************/
X
Xxlabind(fargs,aargs)
X    struct node *fargs,*aargs;
X{
X    struct node *val;
X
X    while (fargs != NULL && aargs != NULL)  /* evaluate and bind */
X    {
X	if (fargs->n_listvalue == slash)    /* Check for local separator*/
X	    break;
X
X	val = xlarg(&aargs);          /* Get the arg */
X	xlbind(fargs->n_listvalue,val);    /* and bind to formal */
X
X	fargs = fargs->n_listnext;     /* Move pointer ahead */
X    }
X
X						 /* check for local variables*/
X    if (fargs != NULL && fargs->n_listvalue == slash)
X	while ((fargs = fargs->n_listnext) != NULL)
X	    xlbind(fargs->n_listvalue,NULL);
X
X    if (fargs != aargs)                /* Check for correct # */
X	xlfail("incorrect number of arguments to a function");
X}
X
X
X
X		      /************************************
X		      *  xlfail - error handling routine  *
X		      ************************************/
Xxlfail(err)
X    char *err;
X{
X    printf("error: %s\n",err);         /* Print the error message */
X    self = NULL;		       /* reset object package */
X    xlunbind(NULL);                    /* Unbind any bound symbols */
X    xltin(TRUE);                       /* Restore input to terminal */
X    trace();                           /* Do the back trace */
X    trace_pointer = -1;
X    xlabort();                         /* Restart */
X}
X
X
X		  /********************************************
X		  *  tpush - add an entry to the trace stack  *
X		  ********************************************/
X
Xstatic tpush(nptr)
X    struct node *nptr;
X{
X    if (++trace_pointer < TDEPTH)
X	trace_stack[trace_pointer] = nptr;
X}
X
X
X
X		 /*********************************************
X		 *  tpop - pop an entry from the trace stack  *
X		 *********************************************/
X
Xstatic tpop()
X{
X    trace_pointer--;
X}
X
X
X
X			  /****************************
X			  *  trace - do a back trace  *
X			  ****************************/
X
Xstatic trace()
X{
X    for (; trace_pointer >= 0; trace_pointer--)
X	if (trace_pointer < TDEPTH)
X	 {
X	    xlprint(trace_stack[trace_pointer],TRUE);
X	    putchar('\n');
X	}
X}
X
X/*****************************************************************
X *** THE FOLLOWING ROUTINES IMPLEMENT THE PROG FEATURE, WHICH  ***
X *** IS INTIMATELY TIED UP WITH EVALUATION (UNFORTUNATELY)     ***
X *****************************************************************/
X
Xstatic struct node *progstk, *returnval, *goatom;
X
X		/**************************************
X		 * prog - bind locals to nil and loop *
X		 **************************************/
X
Xstatic struct node *prog(args)
Xstruct node *args;
X{
X	struct node *locals, *oldenv, *val;
X		/* bind locals to nil */
X	oldenv = xlenv;
X	locals = xlarg(&args);
X	for ( ; locals != NULL; locals = locals->n_listnext)
X		xlbind(locals->n_listvalue, NULL);
X	xlfixbindings(oldenv);		/* make bindings available */
X
X	val = doprog(args,NULL,NULL,NULL,1);	/* 1 is no good pointer */
X	xlunbind(oldenv);
X	return val;
X}
X
X		/*******************************
X		 * olddo - MACLISP oldstyle do *
X		 *******************************/
Xstatic struct node *olddo(args) struct node *args;
X{
X	struct node *var, *init, *rpt, *endtest, *val, *oldenv;
X
X	var = xlarg(&args);
X	if (var && var->n_type != SYM)
X		xlfail("bad do variable");
X	init = xlarg(&args);
X	rpt = xlarg(&args);
X	endtest = xlarg(&args);
X
X	oldenv = xlenv;
X	if (var)
X		xlbind(var,xleval(init));
X	xlfixbindings(oldenv);
X	val = doprog(args,var,init,rpt,endtest);
X	xlunbind(oldenv);
X	return val;
X}
X
X		/***********************
X		 * do/prog common code *
X		 ***********************/
X
Xstatic struct node *doprog(forms,var,init,rpt,endtest)
Xstruct node *forms, *var, *init, *rpt, *endtest;
X{
X	jmp_buf progjmp;
X	int x, tracesave;
X	struct node *oldstk, *nowstk, val, new, *ip, *nowenv;
X
X	oldstk = xlsave(&val, &new, NULL);
X	nowstk = xlstack;
X
X		/* push entry onto prog stack */
X	new.n_ptr = newnode(PROGSTK);
X	new.n_ptr->n_progval = &progjmp;
X	new.n_ptr->n_prognext = progstk;
X	progstk = new.n_ptr;
Xtop:
X	nowenv = xlenv;			/* record current environment */
X		/* save trace pointer */
X	tracesave = trace_pointer;
X		/* set interpretation pointer */
X	ip = forms;
X	val.n_ptr = NULL;		/* set return value */
X	/* evaluate endtest first time */
X	if (endtest != 1 && xleval(endtest))
X		goto byebye;
X	/* loop on forms */
X	while (ip != NULL) {
X		if (x = setjmp(progjmp)) {
X			if (x == RETURN) {
X				val.n_ptr = returnval;
X				goto byebye;
X			}
X			/* else is a go */
X			for (ip = forms;
X			     ip != NULL && !xeq(goatom,ip->n_listvalue);
X			     ip = ip->n_listnext)
X				continue;
X			if (ip == NULL) {
X				if (!progstk)	xlfail("go target not found");
X				/* else resignal */
X				progstk = progstk->n_prognext;
X				longjmp(progstk->n_progval,GO);
X			}
X			/* reset everything */
X			xlstack = nowstk;
X			xlunbind(nowenv);
X			xlenv   = nowenv;
X			trace_pointer = tracesave;
X			/* point after atom */
X			ip = ip->n_listnext;
X			continue;
X		}
X		if (ip->n_listvalue->n_type != SYM)
X			val.n_ptr = xleval(ip->n_listvalue);
X		ip = ip->n_listnext;
X	}
X	/* for do, compute end test */
X	if (endtest != 1) { /* no good pointer */
X		if (var)
X			var->n_symvalue = xleval(rpt);
X		if (xleval(endtest) == NULL)
X			goto top;
X	}
Xbyebye:
X	/* prepare to exit */
X	trace_pointer = tracesave;
X	progstk = progstk->n_prognext;
X	xlstack = oldstk;
X	return val.n_ptr;
X}
X
Xstatic struct node *go(args) struct node *args;
X{
X	struct node *oldstk, sym, *arg;
X
X	if (!progstk) xlfail("go no prog");
X
X	oldstk = xlsave(&sym,NULL);
X	sym.n_ptr = xlarg(&args);
X	xllastarg(args);
X
X	while(sym.n_ptr && sym.n_ptr->n_type != SYM)
X		sym.n_ptr = xleval(sym.n_ptr);
X	if (sym.n_ptr == NULL)
X		xlfail("can't go nil");
X	goatom = sym.n_ptr;
X	xlstack = oldstk;
X	longjmp(progstk->n_progval,GO);
X}
X
Xstatic struct node *retrn(args) struct node *args;
X{
X	if (!progstk) xlfail("go no prog");
X
X	returnval = xlarg(&args);
X	xllastarg(args);
X
X	longjmp(progstk->n_progval,RETURN);
X}
X
Xstatic struct node *progn(args) struct node *args;
X{
X	struct node *oldstk, val;
X	oldstk = xlsave(&val,NULL);
X	while (args)
X		val.n_ptr = xlevarg(&args);
X	xlstack = oldstk;
X	return val.n_ptr;
X}
X
Xstatic struct node *prog2(args) struct node *args;
X{
X	struct node *oldstk, val;
X	int i = 0;
X	oldstk = xlsave(&val,NULL);
X	while (args)
X		if (++i == 2) val.n_ptr = xlevarg(&args);
X		else xlevarg(&args);
X	xlstack = oldstk;
X	return val.n_ptr;
X}
X
X		/*********************************************************
X		 * arg - select an argument of the current lexpr	 *
X		 * cdr down current arg property of arg atom count times *
X		 *********************************************************/
Xstruct node *arg(args) struct node *args;
X{
X	struct node *val;
X	int i;
X
X	val = xlmatch(INT,&args);
X	xllastarg(args);
X	if ( ( i = val->n_int) < 1)	xlfail("bad count to ARG");
X	if ((val = xlget(argatom,argatom)) == NULL)
X		xlfail("no lexpr active");
X	val = val->n_listvalue;
X	for ( ; --i > 0 && val != NULL ; val = val->n_listnext) ;
X	if (!val) xlfail("bad count to arg");
X	return val->n_listvalue;
X}
X
X		/*********************************************************
X		 * setarg - set an argument of the current lexpr	 *
X		 * cdr down current arg property of arg atom count times *
X		 *********************************************************/
Xstruct node *setarg(args) struct node *args;
X{
X	struct node *val, *to;
X	int i;
X
X	val = xlmatch(INT,&args);
X	to = xlarg(&args);
X	xllastarg(args);
X	if ( ( i = val->n_int) < 1)	xlfail("bad count to ARG");
X	if ((val = xlget(argatom,argatom)) == NULL)
X		xlfail("no lexpr active");
X	val = val->n_listvalue;
X	for ( ; --i > 0 && val != NULL ; val = val->n_listnext) ;
X	if (!val) xlfail("bad count to arg");
X	return (val->n_listvalue = to);
X}
X
X		    /***************************************
X		    *  xleinit - initialize the evaluator  *
X		    ***************************************/
X
Xxleinit()
X{
X    slash = xlenter("/");              /* the local variable separator */
X
X    trace_pointer = -1;                /* Initialize debugging */
X
X    xlsubr("eval",eval);               /* Built in functions from this module*/
X    xlsubr("apply",apply);
X    xlsubr("funcall",funcall);
X    xlsubr("arg",arg);
X    argatom = xlenter("arg");
X    xlsubr("setarg",setarg);
X    xlfsubr("prog",prog);
X    xlfsubr("do",olddo);
X    xlsubr("return",retrn);
X    xlfsubr("go",go);
X    xlfsubr("prog2",prog2);
X    xlfsubr("progn",progn);
X}
!Funky!Stuff!
echo x xlext.c
sed -n -e 's/^X//p' > xlext.c << '!Funky!Stuff!'
X		   /* xlextensions - xlisp wild extensions */
X
X#ifdef CI_86
X#include "a:stdio.h"
X#include "xlisp.h"
X#endif
X
X#ifdef AZTEC
X#include "a:stdio.h"
X#include "xlisp.h"
X#endif
X
X#ifdef unix
X#include <stdio.h>
X#include "xlisp.h"
X#endif
X
X
X			    /* external variables */
X
Xextern struct node *xlstack;
Xextern struct node *oblist;
Xextern struct node *xlapply();
Xextern int (*xlofun)();
Xextern int xeq(), xequal();
Xextern int xlstrout();
X
X			/* global variables sourced here */
Xstruct node *strstk = 0;
X
X			/* local variables */
Xstatic struct node *t;
X
X		/*************************************************
X		 * putprop - put a property indicator on a plist *
X		 *************************************************/
Xstatic struct node *putprop(args)
Xstruct node *args;
X{
X	struct node *atom,*value,*prop;
X
X	atom = xlmatch(SYM,&args);
X	value = xlarg(&args);
X	prop = xlarg(&args);
X	xllastarg(args);
X
X	return xlputprop(atom,value,prop);
X}
X
Xstruct node *xlputprop(atom,value,prop) struct node *atom,*value,*prop;
X{	struct node *oldstk,list,*lptr;
X	oldstk = xlsave(&list,NULL);
X
X	/* see if property already exists */
X	for (lptr = atom->n_plist; lptr != NULL;
X			lptr = lptr->n_listnext->n_listnext)
X	{	if (xeq(prop,lptr->n_listvalue)) {
X			lptr->n_listnext->n_listvalue = value;
X			xlstack = oldstk;
X			return value;
X		}
X	}
X	if (value != NULL)	/* if null, is to be "deleted" */
X	{	/* add property */
X		list.n_ptr = newnode(LIST);
X		list.n_ptr->n_listvalue = prop;
X		list.n_ptr->n_listnext = newnode(LIST);
X		list.n_ptr->n_listnext->n_listvalue = value;
X		list.n_ptr->n_listnext->n_listnext = atom->n_plist;
X		atom->n_plist = list.n_ptr;
X	}
X	xlstack = oldstk;
X	return value;
X}
X
X 		       /***************************************
X		       *  get - get key from property list    *
X		       ****************************************/
Xstatic struct node *get(args)
Xstruct node *args;
X{
X	struct node *atom,*val,*prop;
X
X	atom = xlmatch(SYM,&args);
X	prop = xlarg(&args);
X	xllastarg(args);
X	return xlget(atom,prop);
X}
X
Xstruct node *xlget(atom,prop) struct node *atom, *prop;
X{	struct node *lptr;
X
X	/* see if property already exists */
X	for (lptr = atom->n_plist; lptr != NULL;
X			lptr = lptr->n_listnext->n_listnext)
X	{	if (xeq(prop,lptr->n_listvalue)) {
X			return lptr->n_listnext->n_listvalue;
X		}
X	}
X	return NULL;
X}
X
X 		       /***************************************
X		       *  remprop - remove from property list *
X		       ****************************************/
Xstatic struct node *remprop(args)
Xstruct node *args;
X{
X	struct node *atom,*prop;
X
X	atom = xlmatch(SYM,&args);
X	prop = xlarg(&args);
X	xllastarg(args);
X	return xlremprop(atom,prop);
X}
X
Xstruct node *xlremprop(atom,prop) struct node *atom, *prop;
X{	struct node *val,*lptr,*last;
X
X	/* see if property already exists */
X	if (atom->n_plist == NULL) return NULL;
X	if (xeq(atom->n_plist->n_listvalue,prop))
X		atom->n_plist = atom->n_plist->n_listnext->n_listnext;
X	else
X		for (last = atom->n_plist,
X		     lptr = last->n_listnext->n_listnext;
X		     lptr != NULL;
X		     last = lptr,
X		     lptr = lptr->n_listnext->n_listnext)
X		{	if (xeq(prop,lptr->n_listvalue)) {
X			       last->n_listnext = lptr->n_listnext->n_listnext;
X				break;
X			}
X		}
X	return NULL;
X}
X
Xstatic struct node *shellc(args) struct node *args;
X{
X	struct node *thing = xlmatch(STR,&args);
X	xllastarg(args);
X	if (system(thing->n_str) == 0)
X		return t;
X	return NULL;
X}
X
X	/********************************************************
X	 * The following routines implement output to strings,  *
X	 * with recursive stacking of output strings		*
X	 ********************************************************/
X
Xstrstart()	/* strstart - begin a level of string output */
X{	struct node *oldstk, new;
X	int strout();
X
X	oldstk = xlsave(&new,NULL);
X
X	/* cons up three list cells, a string, and 2 ints */
X	new.n_ptr = newnode(LIST);
X	new.n_ptr->n_listvalue = newnode(INT);
X	new.n_ptr->n_listnext = strstk;
X	strstk = new.n_ptr;
X	strstk->n_listvalue->n_int = xlofun;	/* current output function */
X
X	new.n_ptr = newnode(LIST);
X	new.n_ptr->n_listvalue = newnode(INT);
X	new.n_ptr->n_listnext = strstk;
X	strstk = new.n_ptr;
X	strstk->n_listvalue->n_int = 1024;		/* init. buffer size */
X
X	new.n_ptr = newnode(LIST);
X	new.n_ptr->n_listvalue = newnode(STR);
X	new.n_ptr->n_listnext = strstk;
X	strstk = new.n_ptr;
X	strstk->n_listvalue->n_str = stralloc(1023);	/* initial buffer */
X	strstk->n_listvalue->n_str[0] = 0;
X
X	xlofun = &strout;
X	xlstack = oldstk;
X}
X
X#define BUFFER	(strstk->n_listvalue->n_str)
X#define SIZE	(strstk->n_listnext->n_listvalue->n_int)
X
Xstrout(s) char *s;
X{
X	int n = strlen(s);
X	char *p;
X
X	if (n + strlen(BUFFER) + 1 > SIZE) {
X		p = stralloc(SIZE += (n > 1024 ? n : 1024) - 1);
X		strcpy(p,BUFFER);
X		strfree(BUFFER);
X		BUFFER = p;
X	}
X	strcat(BUFFER,s);
X}
X
Xstruct node *strpop()		/* pop current level of string output */
X{
X	struct node *rv;
X
X	if (strstk == NULL) return NULL;
X	rv = strstk->n_listvalue;
X	strstk = strstk->n_listnext->n_listnext;
X	xlofun = strstk->n_listvalue->n_int;
X	strstk = strstk->n_listnext;
X	return rv;
X}
X
Xstroflush() 			/* flush ALL layers of string output */
X{
X	strstk = NULL;
X	xlofun = xlstrout;
X}
X
X		/*****************************************************
X		 * explode, explodec - make a list of the characters *
X		 * in the printed representation of a lisp object    *
X		 *****************************************************/
X
Xstatic struct node *explode(args) struct node *args;
X{
X	return boom(args,TRUE);	/* slashify */
X}
Xstatic struct node *xplodec(args) struct node *args;
X{
X	return boom(args,FALSE);	/* no slashify */
X}
Xstatic struct node *boom(args,flag) struct node *args;
X{
X	char buf[2], *p;
X	struct node *oldstk, *expr, *lptr = NULL, list, prt;
X
X	oldstk = xlsave(&list, &prt, NULL);
X
X	expr = xlarg(&args);	xllastarg(args);
X
X	strstart();	/* set output into a string */
X	xlprint(expr,flag);
X	prt.n_ptr = strpop();	/* get that string */
X
X	buf[1] = 0;
X	for (p = prt.n_ptr->n_str; *p; p++)
X	{	if (!list.n_ptr) {
X			list.n_ptr = lptr = newnode(LIST);
X		} else {
X			lptr->n_listnext = newnode(LIST);
X			lptr = lptr->n_listnext;
X		}
X		buf[0] = *p;
X		lptr->n_listvalue = xlenter(buf);
X	}
X	xlstack = oldstk;
X	return list.n_ptr;
X}
X
Xstatic struct node *implode(args) struct node *args;
X{
X	struct node *oldstk, arglist, *at, *sym;
X	char buffer[STRMAX], *p = buffer;
X
X	oldstk = xlsave(&arglist,NULL);
X
X	arglist.n_ptr = xlmatch(LIST,&args);
X	
X	while (arglist.n_ptr) {
X		at = xlmatch(SYM,&arglist.n_ptr);
X		if (p-buffer == STRMAX)
X			xlfail("Too many characters to maknam");
X		*p++ = at->n_symname[0];
X	}
X	*p = 0;
X	xlstack = oldstk;
X	return xlenter(buffer);
X}
X
Xstatic struct node *maknam(args) struct node *args;
X{
X	struct node *oldstk, arglist, *at, *sym;
X	char buffer[STRMAX], *p = buffer;
X
X	oldstk = xlsave(&arglist,NULL);
X
X	arglist.n_ptr = xlmatch(LIST,&args);
X	xllastarg(args);
X	
X	while (arglist.n_ptr) {
X		at = xlmatch(SYM,&arglist.n_ptr);
X		if (p-buffer == STRMAX)
X			xlfail("Too many characters to maknam");
X		*p++ = at->n_symname[0];
X	}
X	*p = 0;
X	xlstack = oldstk;
X	sym = newnode(SYM);
X	sym->n_symname = strsave(buffer);
X	return sym;
X}
X
X			/********************************************
X			 * intern - add a symbol to the oblist if it*
X			 * is not already there, or tell us which   *
X			 * symbol already has this printname	    *
X			 ********************************************/
X
Xstatic struct node *intern(args) struct node *args;
X{
X    struct node *sym = xlarg(&args), *sptr;
X    xllastarg(args);
X    if (sym->n_type == STR)
X	return xlenter(sym->n_str);
X    else if (sym->n_type != SYM)
X	xlfail("bad argument type");
X    /* else  SYM */
X    if (strcmp(sym->n_symname,"nil") == 0)      /* Check for nil */
X    return (NULL);
X
X    sptr = oblist->n_symvalue;     /* check for symbol already in table */
X    while (sptr != NULL) {
X	if (sptr->n_listvalue == NULL)		/* OOPS! */
X	{   printf("bad oblist\n");
X	    sptr = oblist->n_symvalue;
X	    while (sptr != NULL) {
X		 if (sptr->n_listvalue == NULL) xlfail("end oblist");
X		 printf("\n%s",sptr->n_listvalue->n_symname);
X		 sptr = sptr->n_listnext;
X	     }
X	}
X	else if (sptr->n_listvalue->n_symname == NULL)
X	    printf("bad oblist symbol\n");
X	else
X	if (strcmp(sptr->n_listvalue->n_symname,sym->n_symname) == 0)
X	    return (sptr->n_listvalue);
X	sptr = sptr->n_listnext;
X    }
X    /* no symbol by this name yet exists */
X    sptr = newnode(LIST);              /* Create and link new symbol */
X    sptr->n_listnext = oblist->n_symvalue;
X    oblist->n_symvalue = sptr;
X    sptr->n_listvalue = sym;
X    return sym;
X}
X
Xstatic struct node *gensym(args) struct node *args;
X{
X	static int counter = 0, letter = 'G';
X	char buffer[10];
X	struct node *sym;
X	
X	if (args) {
X		sym = xlarg(&args);
X		xllastarg(args);
X		switch(sym->n_type) {
X		case SYM:
X			letter = sym->n_symname[0];
X			break;
X		case STR:
X			letter = sym->n_str[0];
X			break;
X		case INT:
X			counter = sym->n_int - 1;
X			break;
X		default:
X			xlfail("bad argument type");
X		}
X		return NULL;
X	}
X	if (counter == 99999) counter = -1;
X	sprintf(buffer,"%c%05u",letter,++counter);
X	sym = newnode(SYM);
X	sym->n_symname = strsave(buffer);
X	return sym;
X}
X
X	/*****************************************************
X	 * assfun - look up something on an association list *
X	 *****************************************************/
X
Xstatic struct node *assfun(find,list, fun)
Xstruct node *find, *list, *(*fun)();
X{
X	while (list) {
X		if (list->n_type != LIST
X		||  list->n_listvalue->n_type != LIST)
X			xlfail("bad assoc list");
X		if ( (*fun) (find, list->n_listvalue->n_listvalue) )
X			return list->n_listvalue->n_listnext;
X		list = list->n_listnext;
X	}
X	return NULL;
X}
X
X		/* and the associative twins, assoc and assq */
Xstatic struct node *assoc(args) struct node *args;
X{
X	struct node *find, *list;
X	find = xlarg(&args);
X	list = xlarg(&args);
X	xllastarg(args);
X	return assfun(find,list, xequal);
X}
X
Xstatic struct node *assq(args) struct node *args;
X{
X	struct node *find, *list;
X	find = xlarg(&args);
X	list = xlarg(&args);
X	xllastarg(args);
X	return assfun(find,list, xeq);
X}
X
X		/************************************************
X		*  xlxinit - xlisp ext. initialization routine  *
X		************************************************/
X
Xxlxinit()
X{
X    /* find t */
X    t = xlenter("t");
X    /* builtins defined here */
X    xlsubr("putprop",putprop);
X    xlfsubr("defprop",putprop);
X    xlsubr("get",get);
X    xlsubr("remprop",remprop);
X    xlsubr("shell",shellc);
X    xlsubr("explode",explode);
X    xlsubr("explodec",xplodec);
X    xlfsubr("gensym",gensym);
X    xlsubr("implode",implode);
X    xlsubr("maknam",maknam);
X    xlsubr("intern",intern);
X    xlsubr("assoc",assoc);
X    xlsubr("assq",assq);
X}
X
!Funky!Stuff!
echo x xlfio.c
sed -n -e 's/^X//p' > xlfio.c << '!Funky!Stuff!'
X			  /* xlfio - xlisp file i/o */
X
X#ifdef CI_86
X#include "a:stdio.h"
X#include "xlisp.h"
X#endif
X
X#ifdef AZTEC
X#include "a:stdio.h"
X#include "xlisp.h"
X#endif
X
X#ifdef unix
X#include <stdio.h>
X#include "xlisp.h"
X#endif
X
X
X			    /* external variables */
X
Xextern struct node *xlstack;
X
X
X			      /* local variables */
X
Xstatic char buf[STRMAX+1];
X
X
X			   /**************************
X			   *  xlfopen - open a file  *
X			   **************************/
X
Xstatic struct node *xlfopen(args)
X  struct node *args;
X{
X    struct node *oldstk,arg,fname,mode,*val;
X    FILE *fp;
X
X    oldstk = xlsave(&arg,&fname,&mode,NULL);
X    arg.n_ptr = args;
X
X    fname.n_ptr = xlmatch(STR,&arg.n_ptr);
X    mode.n_ptr = xlmatch(STR,&arg.n_ptr);
X
X    xllastarg(arg.n_ptr);
X
X    if ((fp = fopen(fname.n_ptr->n_str,
X			mode.n_ptr->n_str)) != NULL)
X    {
X	val = newnode(FPTR);
X	val->n_fp = fp;
X    }
X    else
X	val = NULL;
X
X    xlstack = oldstk;
X    return (val);
X}
X
X
X			  /****************************
X			  *  xlfclose - close a file  *
X			  ****************************/
X
Xstatic struct node *xlfclose(args)
X  struct node *args;
X{
X    struct node *fptr;
X
X    fptr = xlmatch(FPTR,&args);
X
X    xllastarg(args);
X
X    if (fptr->n_fp == NULL)
X	xlfail("file not open");
X
X    fclose(fptr->n_fp);
X    fptr->n_fp = NULL;
X
X    return (NULL);
X}
X
X
X		   /*****************************************
X		   *  xlgetc - get a character from a file  *
X		   *****************************************/
X
Xstatic struct node *xlgetc(args)
X  struct node *args;
X{
X    struct node *val;
X    FILE *fp;
X    int ch;
X
X    if (args != NULL)
X	fp = xlmatch(FPTR,&args)->n_fp;
X    else
X	fp = stdin;
X
X    xllastarg(args);
X
X    if (fp == NULL)
X	xlfail("file not open");
X
X    if ((ch = getc(fp)) != EOF)
X    {
X	val = newnode(INT);
X	val->n_int = ch;
X    }
X    else
X	val = NULL;
X
X    return (val);
X}
X
X
X		    /***************************************
X		    *  xlputc - put a character to a file  *
X		    ***************************************/
X
Xstatic struct node *xlputc(args)
X  struct node *args;
X{
X    struct node *oldstk,arg,chr;
X    FILE *fp;
X
X    oldstk = xlsave(&arg,&chr,NULL);
X    arg.n_ptr = args;
X
X    chr.n_ptr = xlmatch(INT,&arg.n_ptr);
X
X    if (arg.n_ptr != NULL)
X	fp = xlmatch(FPTR,&arg.n_ptr)->n_fp;
X    else
X	fp = stdout;
X
X    xllastarg(arg.n_ptr);
X
X    if (fp == NULL)
X	xlfail("file not open");
X
X    putc(chr.n_ptr->n_int,fp);
X
X    xlstack = oldstk;
X    return (chr.n_ptr);
X}
X
X
X		    /***************************************
X		    *  xlfgets - get a string from a file  *
X		    ***************************************/
X
Xstatic struct node *xlfgets(args)
X  struct node *args;
X{
X    struct node *str;
X    char *sptr;
X    FILE *fp;
X
X    if (args != NULL)
X	fp = xlmatch(FPTR,&args)->n_fp;
X    else
X	fp = stdin;
X
X    xllastarg(args);
X
X    if (fp == NULL)
X	xlfail("file not open");
X
X    if (fgets(buf,STRMAX,fp) != NULL)
X    {
X	str = newnode(STR);
X	str->n_str = strsave(buf);
X
X	while (buf[strlen(buf)-1] != '\n')
X	{
X	    if (fgets(buf,STRMAX,fp) == NULL)
X		break;
X	    sptr = str->n_str;
X	    str->n_str = stralloc(strlen(sptr) + strlen(buf));
X	    strcpy(str->n_str,sptr);
X	    strcat(str->n_str,buf);
X	    strfree(sptr);
X	}
X    }
X    else
X	str = NULL;
X
X    return (str);
X}
X
X
X		     /*************************************
X		     *  xlfputs - put a string to a file  *
X		     *************************************/
X
Xstatic struct node *xlfputs(args)
X  struct node *args;
X{
X    struct node *oldstk,arg,str;
X    FILE *fp;
X
X    oldstk = xlsave(&arg,&str,NULL);
X    arg.n_ptr = args;
X
X    str.n_ptr = xlmatch(STR,&arg.n_ptr);
X
X    if (arg.n_ptr != NULL)
X	fp = xlmatch(FPTR,&arg.n_ptr)->n_fp;
X    else
X	fp = stdout;
X
X    xllastarg(arg.n_ptr);
X
X    if (fp == NULL)
X	xlfail("file not open");
X
X    fputs(str.n_ptr->n_str,fp);
X
X    xlstack = oldstk;
X    return (str.n_ptr);
X}
X
X
X		      /************************************
X		      *  xlfinit - initialize file stuff  *
X		      ************************************/
X
Xxlfinit()
X{
X    xlsubr("fopen",xlfopen);
X    xlsubr("fclose",xlfclose);
X    xlsubr("getc",xlgetc);
X    xlsubr("putc",xlputc);
X    xlsubr("fgets",xlfgets);
X    xlsubr("fputs",xlfputs);
X}
!Funky!Stuff!
echo x xlfmath.c
sed -n -e 's/^X//p' > xlfmath.c << '!Funky!Stuff!'
X
X		/* xlmath - xlisp builtin arithmetic functions */
X
X#ifdef CI_86
X#include "a:stdio.h"
X#include "xlisp.h"
X#endif
X
X#ifdef AZTEC
X#include "a:stdio.h"
X#include "xlisp.h"
X#endif
X
X#ifdef unix
X#include <stdio.h>
X#include "xlisp.h"
X#endif
X
X
X			    /* external variables */
X
Xextern struct node *xlstack;
X
X
X			      /* local variables */
X
Xstatic struct node *true;
X
X#ifdef HACK
X	   /* forward declarations (the extern hack is for decusc) */
X
Xextern struct node *iarith();
Xextern struct node *compare();
X#endif
X
X			/* Comparison operator defines */
X
X#define  lss_op    1
X#define  leq_op    2
X#define  eql_op    3
X#define  neq_op    4
X#define  geq_op    5
X#define  gtr_op    6
X
X#define  sign(n)   (((n)<0) ? -1 : (((n)>0) ? 1 : 0))
X
X
X		    /****************************************
X		    *  add - builtin function for addition  *
X		    ****************************************/
X
Xstatic struct node *add(args)
X  struct node *args;
X{
X    return iarith(args,'+');
X}
X
X
X		  /*******************************************
X		  *  sub - builtin function for subtraction  *
X		  *******************************************/
X
Xstatic struct node *sub(args)
X  struct node *args;
X{
X    return iarith(args,'-');
X}
X
X
X		 /**********************************************
X		 *  mul - builtin function for multiplication  *
X		 **********************************************/
X
Xstatic struct node *mul(args)
X  struct node *args;
X{
X    return iarith(args,'*');
X}
X
X
X		    /****************************************
X		    *  div - builtin function for division  *
X		    ****************************************/
X
Xstatic struct node *div(args)
X  struct node *args;
X{
X    return iarith(args,'/');
X}
X
X
X		    /***************************************
X		    *  mod - builtin function for modulus  *
X		    ***************************************/
X
Xstatic struct node *mod(args)
X  struct node *args;
X{
X    return iarith(args,'%');
X}
X
X
X		    /***************************************
X		    *  min - builtin function for minimum  *
X		    ***************************************/
X
Xstatic struct node *min(args)
X  struct node *args;
X{
X    return iarith(args,'m');
X}
X
X
X		    /***************************************
X		    *  max - builtin function for maximum  *
X		    ***************************************/
X
Xstatic struct node *max(args)
X  struct node *args;
X{
X    return iarith(args,'M');
X}
X
X
X		    /***************************************
X		    *  and - builtin function for modulus  *
X		    ***************************************/
X
Xstatic struct node *and(args)
X  struct node *args;
X{
X    return iarith(args,'&');
X}
X
X
X		     /**************************************
X		     *  or - builtin function for modulus  *
X		     **************************************/
X
Xstatic struct node *or(args)
X  struct node *args;
X{
X    return iarith(args,'|');
X}
X
X
X			     /**********************
X			     *  not - bitwise not  *
X			     **********************/
X
Xstatic struct node *not(args)
X  struct node *args;
X{
X    struct node *rval;
X    int val;
X
X    val = xlmatch(INT,&args)->n_int;      /* Evaluate the argument */
X    xllastarg(args);
X
X    rval = newnode(INT);
X    rval->n_int = ~val;
X    return (rval);
X}
X
Xextern double cos(), sin(), tan(), atan(), atan2(), log();
X
Xstatic struct node *lsin(args) struct node *args;
X{	return mathop(args,'S');
X}
Xstatic struct node *lcos(args) struct node *args;
X{	return mathop(args,'C');
X}
Xstatic struct node *ltan(args) struct node *args;
X{	return mathop(args,'T');
X}
Xstatic struct node *latan(args) struct node *args;
X{	return mathop(args,'t');
X}
Xstatic struct node *llog(args) struct node *args;
X{	return mathop(args,'l');
X}
Xstatic struct node *lexp(args) struct node *args;
X{	return mathop(args,'e');
X}
X
Xstatic struct node *mathop(args,op) struct node *args;
X{
X	struct node *arg1, *arg2 = NULL, *rval;
X	double a1, a2;
X	arg1 = xlarg(&args);
X	switch(arg1->n_type) {
X	default:
X		xlfail("non-numeric argument");
X	case INT:
X		a1 = (double) arg1->n_int;
X		break;
X	case REAL:
X		a1 = arg1->n_real;
X		break;
X	}
X	if (op == 't' && args != NULL)
X	{	arg2 = xlarg(&args);
X		switch(arg2->n_type) {
X		case INT:	a2 = arg2->n_int; break;
X		case REAL:	a2 = arg2->n_real; break;
X		default:	xlfail("non-numeric argument");
X		}
X	}
X	xllastarg(args);
X	rval = newnode(REAL);
X	switch(op) {
X	case 'S': rval->n_real = sin(a1); break;
X	case 'C': rval->n_real = cos(a1); break;
X	case 'T': rval->n_real = tan(a1); break;
X	case 't': if (!arg2) rval->n_real = atan(a1);
X		  else	     rval->n_real = atan2(a1,a2);
X		  break;
X	case 'l': 
X		if (a1 <= 0.0)
X			xlfail("log of non-positive number");
X		rval->n_real = log(a1);
X		break;
X	case 'e':
X		rval->n_real = exp(a1);
X		break;
X	}
X	return rval;
X}
X			   /*************************
X			   *  abs - absolute value  *
X			   *************************/
Xstatic struct node *abs(args)
X  struct node *args;
X{
X     return UOP(args,'A');
X}
X			   /*************************
X			   *  sqrt - square root    *
X			   *************************/
Xstatic struct node *Sqrt(args)
X  struct node *args;
X{
X    return UOP(args,'S');
X}
X
Xstatic struct node *add1(args)
X  struct node *args;
X{
X    return UOP(args,'+');
X}
Xstatic struct node *sub1(args)
X  struct node *args;
X{
X    return UOP(args,'-');
X}
Xstatic struct node *minus(args)
X  struct node *args;
X{
X    return UOP(args,'N');
X}
X			   /****************************
X			   *  unary operation routine  *
X			   *****************************/
X
Xstatic struct node *UOP(args,uoperator)
X  struct node *args;
X{
X    struct node *rval, *argp;
X#ifdef REALS
X    double sqrt();
X#endif
X    int i;
X
X    switch (gettype(argp = xlarg(&args)))
X    {
X    case INT:
X	xllastarg(args);
X	rval = newnode(INT);
X	switch(uoperator) {
X	case 'A':
X	    if ((rval->n_int = argp->n_int) < 0)
X		rval->n_int = -rval->n_int;
X	    break;
X	case 'S':
X	    if (argp->n_int < 0)	xlfail("sqrt of negative number");
X	    if (argp->n_int < 4) {
X		rval->n_int = 1;
X		break;
X	    }
X	    for (i = (argp->n_int+1) / 2;
X		 ! (i*i <= argp->n_int && i*i + 2*i + 1 > argp->n_int) ;
X		 i = (i + argp->n_int/i) / 2) ;
X	    rval->n_int = i;
X	    break;
X	case '+':
X	    rval->n_int = argp->n_int + 1;
X	    break;
X	case '-':
X	    rval->n_int = argp->n_int - 1;
X	    break;
X	case 'N':
X	    rval->n_int = -argp->n_int;
X	    break;
X	}
X	break;
X
X#ifdef REALS
X    case REAL:
X	 xllastarg(args);
X	 rval = newnode(REAL);
X	 switch(uoperator) {
X	 case 'A':
X		if ((rval->n_real = argp->n_real) < 0)
X			rval->n_real =  -rval->n_real;
X		break;
X	 case 'S':
X		 rval->n_real = sqrt(argp->n_real);
X		 break;
X	case '+':
X	    rval->n_real = argp->n_real + 1;
X	    break;
X	case '-':
X	    rval->n_real = argp->n_real - 1;
X	    break;
X	case 'N':
X	    rval->n_real = -argp->n_real;
X	    break;
X	}
X	break;
X#endif
X
X    default:
X	 xlfail("bad argument type");
X    }
X
X    return (rval);
X}
X
Xstatic int ipow(x, y) int x,y;
X{
X	int res = x;
X
X	if (y == 0) return 1;
X	--y;	/* since res == x already */
X	while (y>0) {
X		if ((y & 1) == 0)	/* even power */
X		{	res = res*res;	/* square it */
X			y >>= 1;
X		} else {
X			res = res*x;
X			y -= 1;
X		}
X	}
X	return res;
X}
X			   /*************************
X			   *  expt - exponent func. *
X			   *************************/
X
Xstatic struct node *Expt(args)
X  struct node *args;
X{
X    struct node *rval, *argxp, *argyp;
X    double pow();
X
X    argxp = xlarg(&args);
X    argyp = xlarg(&args);
X    xllastarg(args);
X    switch (gettype(argyp))
X    {
X    case INT:	/* integer power, can have integer result */
X	switch(gettype(argxp)) {
X		case INT:
X		    if (argyp->n_int >= 0)
X		    {	rval = newnode(INT);
X			rval->n_int = ipow(argxp->n_int,argyp->n_int);
X		    } else {
X#ifdef REALS
X			rval = newnode(REAL);
X			rval->n_real = pow((double)argxp->n_int,
X					   (double)argyp->n_int);
X#else no REALS
X			rval = newnode(INT);
X			rval->n_int = 0;
X#endif
X		    }
X		    break;
X#ifdef REALS
X		case REAL:
X		    rval = newnode(REAL);
X		    rval->n_real = pow(argxp->n_real,(double)argyp->n_int);
X		    break;
X#endif
X		default:
X		    xlfail("bad argument type");
X		}
X	break;
X
X#ifdef REALS
X    case REAL:
X	rval = newnode(REAL);
X	switch(gettype(argxp)) {
X	default:	xlfail("Bad argument type");
X	case INT:
X	    rval = newnode(REAL);
X	    rval->n_real = pow((double)argxp->n_int,argyp->n_real);
X	    break;
X	case REAL:
X	    rval = newnode(REAL);
X	    rval->n_real = pow(argxp->n_real,argyp->n_real);
X	    break;
X	}
X	break;
X#endif
X
X    default:
X	 xlfail("bad argument type");
X    }
X
X    return (rval);
X}
X
X
X#ifdef REALS
X
X			  /****************************
X			  *  fix - integer from real  *
X			  ****************************/
X
Xstatic struct node *fix(args)
X  struct node *args;
X{
X    struct node *rval, *argp;
X
X    switch (gettype(argp = xlarg(&args)))
X    {
X    case INT:
X	 xllastarg(args);
X	 rval = newnode(INT);
X	 rval->n_int = argp->n_int;
X	 break;
X
X    case REAL:
X	 xllastarg(args);
X	 rval = newnode(INT);
X	 rval->n_int = (int) argp->n_real;
X	 break;
X
X    default:
X	 xlfail("bad argument type");
X    }
X
X    return (rval);
X}
X
X
X		       /******************************
X		       *  float - real from integer  *
X		       ******************************/
X
Xstatic struct node *lfloat(args)
X  struct node *args;
X{
X    struct node *rval, *argp;
X
X    switch (gettype(argp = xlarg(&args)))
X    {
X    case INT:
X	 xllastarg(args);
X	 rval = newnode(REAL);
X	 rval->n_real = argp->n_int;
X	 break;
X
X    case REAL:
X	 xllastarg(args);
X	 rval = newnode(REAL);
X	 rval->n_real = argp->n_real;
X	 break;
X
X    default:
X	 xlfail("bad argument type");
X    }
X
X    return (rval);
X}
X
X
X	       /*************************************************
X	       *  farith - common floating arithmetic function  *
X	       *************************************************/
X
Xstatic struct node *farith(ival, oldstk, arg, val, ifunct, funct)
X    struct node *oldstk, *arg, *val;
X    int ival;
X    char ifunct, funct;
X{
X    struct node *rval;
X    long float rslt = (long float) ival, arg_val;
X    int arg_typ = REAL;
X
X    while(1)
X    {
X	if (arg_typ == INT)
X	    arg_val = (long float) (val->n_ptr)->n_int;
X	else
X	if (arg_typ == REAL)
X	    arg_val = (val->n_ptr)->n_real;
X	else
X	    xlfail("bad argument type");
X
X	switch (ifunct)
X	{
X	case '+':
X	    rslt += arg_val;
X	    break;
X
X	case '-':
X	    rslt -= arg_val;
X	    break;
X
X	case '*':
X	    rslt *= arg_val;
X	    break;
X
X	case '/':
X	    rslt /= arg_val;
X	    break;
X
X	case '%':
X	case '&':
X	case '|':
X	    xlfail("bad argument type");
X
X	case 'm':
X	    if (rslt > arg_val)
X		rslt = arg_val;
X	    break;
X
X	case 'M':
X	    if (rslt < arg_val)
X		rslt = arg_val;
X	   break;
X	}
X
X	ifunct = funct;
X
X	if (arg->n_ptr == NULL)
X	     break;
X
X	arg_typ = gettype((val->n_ptr = xlarg(&(arg->n_ptr))));
X    }
X
X    rval = newnode(REAL);
X    rval->n_real = rslt;
X
X    xlstack = oldstk;
X    return (rval);
X}
X#endif
X
X
X		    /***************************************
X		    *  arith - common arithmetic function  *
X		    ***************************************/
X
Xstatic struct node *iarith(args,funct)
X    struct node *args;
X    char funct;
X{
X    struct node *oldstk,arg,val,*rval;
X    int rslt, arg_val;
X
X    oldstk = xlsave(&arg,&val,NULL);   /* Create a new stack frame */
X
X    arg.n_ptr = args;                  /* Get first parameter */
X
X    arg_val = gettype((val.n_ptr = xlarg(&arg.n_ptr)));
X
X#ifdef REALS
X    if (arg_val == REAL)
X	 return farith(0, oldstk, &arg, &val, '+', funct);
X#endif
X
X    if (arg_val != INT)
X	xlfail("bad argument type");
X
X    rslt = val.n_ptr->n_int;
X
X    while (arg.n_ptr != NULL)
X    {
X	arg_val = gettype((val.n_ptr = xlarg(&arg.n_ptr)));
X
X#ifdef REALS
X	if (arg_val == REAL)
X	    return farith(rslt, oldstk, &arg, &val, funct, funct);
X#endif
X
X	if (arg_val != INT)
X	    xlfail("bad argument type");
X
X	arg_val = val.n_ptr->n_int;
X
X	switch (funct)
X	{
X	case '+':
X	    rslt += arg_val;
X	    break;
X
X	case '-':
X	    rslt -= arg_val;
X	    break;
X
X	case '*':
X	    rslt *= arg_val;
X	    break;
X
X	case '/':
X	    rslt /= arg_val;
X	    break;
X
X	case '%':
X	    rslt %= arg_val;
X	    break;
X
X	case '&':
X	    rslt &= arg_val;
X	    break;
X
X	case '|':
X	    rslt |= arg_val;
X	    break;
X
X	case 'm':
X	    if (rslt > arg_val)
X		rslt = arg_val;
X	    break;
X
X	case 'M':
X	    if (rslt < arg_val)
X		rslt = arg_val;
X	   break;
X	}
X    }
X
X    rval = newnode(INT);
X    rval->n_int = rslt;
X
X    xlstack = oldstk;
X    return (rval);
X}
X
X
X			    /***********************
X			    *  land - logical and  *
X			    ***********************/
X
Xstatic struct node *land(args)
X  struct node *args;
X{
X    struct node *oldstk,arg,*val;
X
X    oldstk = xlsave(&arg,NULL);
X    arg.n_ptr = args;
X
X    while (arg.n_ptr != NULL)
X	if ((val = xlevarg(&arg.n_ptr)) == NULL)
X	{
X	    break;
X	}
X
X    xlstack = oldstk;
X    return (val);
X}
X
X
X			     /*********************
X			     *  lor - logical or  *
X			     *********************/
X
Xstatic struct node *lor(args)
X  struct node *args;
X{
X    struct node *oldstk,arg,*val;
X
X    oldstk = xlsave(&arg,NULL);
X    arg.n_ptr = args;
X
X    while (arg.n_ptr != NULL)
X	if ((val = xlevarg(&arg.n_ptr)) != NULL)
X	{
X	    break;
X	}
X
X    xlstack = oldstk;
X    return (val);
X}
X
X
X			    /***********************
X			    *  lnot - logical not  *
X			    ***********************/
X
Xstatic struct node *lnot(args)
X  struct node *args;
X{
X    struct node *val;
X
X    val = xlarg(&args);
X    xllastarg(args);
X
X    if (val == NULL)
X	return (true);
X    else
X	return (NULL);
X}
X
X
X		       /*********************************
X		       *  lss - builtin function for <  *
X		       *********************************/
X
Xstatic struct node *lss(args)
X  struct node *args;
X{
X    return (compare(args,lss_op));
X}
X
X
X		       /**********************************
X		       *  leq - builtin function for <=  *
X		       **********************************/
X
Xstatic struct node *leq(args)
X  struct node *args;
X{
X    return (compare(args,leq_op));
X}
X
X
X		       /**********************************
X		       *  eql - builtin function for ==  *
X		       **********************************/
X
Xstatic struct node *eql(args)
X  struct node *args;
X{
X    return (compare(args,eql_op));
X}
X
X
X		       /**********************************
X		       *  neq - builtin function for !=  *
X		       **********************************/
X
Xstatic struct node *neq(args)
X  struct node *args;
X{
X    return (compare(args,neq_op));
X}
X
X
X		       /**********************************
X		       *  geq - builtin function for >=  *
X		       **********************************/
X
Xstatic struct node *geq(args)
X  struct node *args;
X{
X    return (compare(args,geq_op));
X}
X
X
X		       /*********************************
X		       *  gtr - builtin function for >  *
X		       *********************************/
X
Xstatic struct node *gtr(args)
X  struct node *args;
X{
X    return (compare(args,gtr_op));
X}
X
X
X		     /**************************************
X		     *  compare - common compare function  *
X		     **************************************/
X
Xstatic struct node *compare(args,funct)
X    struct node *args;
X    int funct;
X{
X    struct node *oldstk,arg,arg1,arg2;
X    int type1,type2,cmp;
X
X    oldstk = xlsave(&arg,&arg1,&arg2,NULL);
X    arg.n_ptr = args;
X
X    type1 = gettype(arg1.n_ptr = xlarg(&arg.n_ptr));
X    type2 = gettype(arg2.n_ptr = xlarg(&arg.n_ptr));
X    xllastarg(arg.n_ptr);
X
X    if ((type1 == STR) && (type2 == STR))
X	cmp = strcmp(arg1.n_ptr->n_str,arg2.n_ptr->n_str);
X    else
X
X#ifdef REALS
X    if (type1 == INT)
X    {
X	if (type2 == INT)
X	    cmp = sign(arg1.n_ptr->n_int - arg2.n_ptr->n_int);
X	else
X
X	if (type2 == REAL)
X	    cmp = sign(arg1.n_ptr->n_int - arg2.n_ptr->n_real);
X	else
X	    cmp = arg1.n_ptr - arg2.n_ptr;
X    }
X    else
X
X    if (type1 == REAL)
X    {
X	if (type2 == INT)
X	    cmp = sign(arg1.n_ptr->n_real - arg2.n_ptr->n_int);
X	else
X
X	if (type2 == REAL)
X	    cmp = sign(arg1.n_ptr->n_real - arg2.n_ptr->n_real);
X	else
X	    cmp = arg1.n_ptr - arg2.n_ptr;
X    }
X#else
X
X    if ((type1 == INT) && (type2 == INT))
X	cmp = sign(arg1.n_ptr->n_int - arg2.n_ptr->n_int);
X#endif
X
X    else
X	cmp = arg1.n_ptr - arg2.n_ptr;
X
X    xlstack = oldstk;
X
X    switch (funct)
X    {
X    case lss_op:
X	return (cmp <  0) ? true : NULL;
X
X    case leq_op:
X	return (cmp <= 0) ? true : NULL;
X
X    case eql_op:
X	return (cmp == 0) ? true : NULL;
X
X    case neq_op:
X	return (cmp != 0) ? true : NULL;
X
X    case geq_op:
X	return (cmp >= 0) ? true : NULL;
X
X    case gtr_op:
X	return (cmp >  0) ? true : NULL;
X
X    }
X    xlfail("bad compare operator");
X}
X
X
X		 /*********************************************
X		 *  gettype - return the type of an argument  *
X		 *********************************************/
X
Xstatic int gettype(arg)
X  struct node *arg;
X{
X    if (arg == NULL)
X	return (LIST);
X    else
X	return (arg->n_type);
X}
X
Xstatic struct node *gcd(args) struct node *args;
X{	struct node *arg1, *arg2, *rval;
X	int a1, a2, r;
X
X	a1 = (arg1 = xlmatch(INT,&args))->n_int;
X	a2 = (arg2 = xlmatch(INT,&args))->n_int;
X	xllastarg(args);
X
X	if (a1 == 0 || a2 == 0) xlfail("zero in gcd!");
X	if (a1 < 0) a1 = -a1;
X	if (a2 < 0) a2 = -a2;
X
X	/* euclid's algorithm */
X	if (a1 < a2) r = a1, a1 = a2, a2 = r;
Xtop:
X	if ((r = a1 % a2) == 0) {
X		(rval = newnode(INT))->n_int = a2;
X		return rval;
X	}
X	a1 = a2; a2 = r; goto top;
X}
X
Xstatic struct node *minusp(args) struct node *args;
X{
X	struct node *arg = xlarg(&args);
X	xllastarg(args);
X	switch(gettype(arg)) {
X	default:	xlfail("non-numeric arg");
X	case INT:
X		if (arg->n_int < 0) return true;
X		return NULL;
X	case REAL:
X		if (arg->n_real < 0.0) return true;
X		return NULL;
X	}
X}
X
Xstatic struct node *zerop(args) struct node *args;
X{
X	struct node *arg = xlarg(&args);
X	xllastarg(args);
X	switch(gettype(arg)) {
X	default:	xlfail("non-numeric arg");
X	case INT:
X		if (arg->n_int == 0) return true;
X		return NULL;
X	case REAL:
X		if (arg->n_real == 0.0) return true;
X		return NULL;
X	}
X}
X
X		/************************************************
X		*  xlminit - xlisp math initialization routine  *
X		************************************************/
X
Xxlminit()
X{
X    xlsubr("+",add);		xlsubr("plus",add);
X    xlsubr("-",sub);		xlsubr("difference",sub);
X    xlsubr("*",mul);		xlsubr("times",mul);
X    xlsubr("/",div);		xlsubr("quotient",div);
X    xlsubr("%",mod);		xlsubr("remainder",mod);
X    xlsubr("&",and);
X    xlsubr("|",or);
X    xlsubr("~",not);
X    xlsubr("<",lss);		xlsubr("lessp",lss);
X    xlsubr("<=",leq);
X    xlsubr("==",eql);		xlsubr("=",eql);
X    xlsubr("!=",neq);
X    xlsubr(">=",geq);
X    xlsubr(">",gtr);		xlsubr("greaterp",gtr);
X    xlfsubr("&&",land);		xlfsubr("and", land);
X    xlfsubr("||",lor);		xlfsubr("or",lor);
X    xlsubr("!",lnot);		xlsubr("not",lnot);
X    xlsubr("min",min);
X    xlsubr("max",max);
X    xlsubr("abs",abs);
X    xlsubr("expt",Expt);
X    xlsubr("sqrt",Sqrt);
X    xlsubr("gcd",gcd);
X
X    xlsubr("add1",add1);
X    xlsubr("sub1",sub1);
X    xlsubr("minus",minus);
X
X    xlsubr("minusp",minusp);
X    xlsubr("zerop",zerop);
X
X    xlsubr("cos",lcos);
X    xlsubr("sin",lsin);
X    xlsubr("tan",ltan);
X    xlsubr("atan",latan);
X    xlsubr("log",llog);
X    xlsubr("exp",lexp);
X
X#ifdef REALS
X    xlsubr("fix",fix);
X    xlsubr("float",lfloat);
X#endif
X
X    true = xlenter("t");
X    true->n_symvalue = true;
X}
!Funky!Stuff!
exit 0
-- 
John Woods, Charles River Data Systems, Framingham MA, (617) 626-1114
...!decvax!frog!john, ...!mit-eddie!jfw, JFW@MIT-XX.ARPA

I have absolutely nothing clever to say in this signature.