XLISP, part 2 of 4
jcw at cvl.UUCP
jcw at cvl.UUCP
Sat Jul 21 01:12:04 AEST 1984
This portion contains the first third of the C source for David
Betz' XLISP interpreter.
Tear at the dotted line, run sh(1) over it.
Jay Weber
---------------------------------------------------------------
: Run this shell script with "sh" not "csh"
PATH=:/bin:/usr/bin:/usr/ucb
export PATH
/bin/echo 'Extracting xlbind.c'
sed 's/^X//' <<'//go.sysin dd *' >xlbind.c
X /* xlbind - xlisp symbol binding routines */
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 /* global variables */
X
Xstruct node *xlenv;
X
X
X /********************************************************
X * xlunbind - unbind symbols bound in this environment *
X ********************************************************/
X
Xxlunbind(env)
X struct node *env;
X{
X struct node *bnd;
X
X for (; xlenv != env; xlenv = xlenv->n_listnext)
X {
X bnd = xlenv->n_listvalue;
X bnd->n_bndsym->n_symvalue = bnd->n_bndvalue;
X }
X}
X
X
X /**************************************
X * xlbind - bind a symbol to a value *
X **************************************/
X
Xxlbind(sym,val)
X struct node *sym,*val;
X{
X struct node *lptr,*bptr;
X
X lptr = newnode(LIST); /* Create new environment list entry */
X lptr->n_listnext = xlenv;
X xlenv = lptr;
X
X lptr->n_listvalue = bptr = newnode(LIST); /* New variable binding */
X bptr->n_bndsym = sym;
X bptr->n_bndvalue = val;
X}
X
X
X /*******************************************************
X * xlfixbindings - make a new set of bindings visible *
X *******************************************************/
X
Xxlfixbindings(env)
X struct node *env;
X{
X struct node *eptr,*bnd,*sym,*oldvalue;
X
X for (eptr = xlenv; eptr != env; eptr = eptr->n_listnext) {
X bnd = eptr->n_listvalue;
X sym = bnd->n_bndsym;
X oldvalue = sym->n_symvalue;
X sym->n_symvalue = bnd->n_bndvalue;
X bnd->n_bndvalue = oldvalue;
X }
X}
//go.sysin dd *
/bin/chmod 664 xlbind.c
/bin/echo -n ' '; /bin/ls -ld xlbind.c
/bin/echo 'Extracting xldebug.c'
sed 's/^X//' <<'//go.sysin dd *' >xldebug.c
X /* xldebug - some debug routines */
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
Xint debug_level = 0;
XFILE *debug_fp = NULL;
X
X
X
X /***************************************************
X * xldbgmsg : Display a message in the debug file *
X ***************************************************/
X
Xxldbgmsg(s)
X char *s;
X{
X if (debug_fp)
X fprintf(debug_fp, "\n%s", s);
X}
X
X
X /*******************************************
X * xldump : dump a node to the debug file *
X *******************************************/
X
Xxldump(nptr)
X struct node *nptr;
X{
X
X if (debug_fp == NULL) /* Debug file open ? */
X return;
X
X fprintf(debug_fp, "\n@%4x : %2x ", nptr, nptr->n_flags);
X
X switch(nptr->n_type)
X {
X case FREE:
X fprintf(debug_fp, "FREE node");
X return;
X
X case SYM:
X fprintf(debug_fp, "SYM %s = @%4x", nptr->n_symname, nptr->n_symvalue);
X return;
X
X case LIST:
X fprintf(debug_fp, "LIST @%4x , @%4x", nptr->n_listvalue,
X nptr->n_listnext);
X return;
X
X case SUBR:
X fprintf(debug_fp, "SUBR %4x", nptr->n_subr);
X return;
X
X case INT:
X fprintf(debug_fp, "INT = %d", nptr->n_int);
X return;
X
X case STR:
X fprintf(debug_fp, "STRING = %s", nptr->n_str);
X return;
X
X case OBJ:
X fprintf(debug_fp, "OBJ @%4x , @%4x", nptr->n_obclass,
X nptr->n_obdata);
X return;
X
X case FPTR:
X fprintf(debug_fp, "FILE %4x", nptr->n_fp);
X return;
X
X case KMAP:
X fprintf(debug_fp, "KMAP");
X return;
X
X#ifdef REALS
X case REAL:
X fprintf(debug_fp, "REAL = %g", nptr->n_real);
X return;
X#endif
X
X default:
X fprintf(debug_fp, "Type %d ?????????", nptr->n_type);
X return;
X }
X}
X
X
X /************************************************
X * debug : xlisp function to set debug options *
X ************************************************/
X
Xstatic struct node *debug(args)
X struct node *args;
X{
X debug_level = xlevmatch(INT, &args)->n_int;
X
X if (args != NULL)
X {
X if (debug_fp)
X fclose(debug_fp);
X if ((debug_fp = fopen(xlevmatch(STR, &args)->n_str, "w")) == NULL)
X xlfail("Cannot open debug file");
X xllastarg(args);
X }
X
X return (NULL);
X}
X
X
X /*******************************************
X * xldebuginit : initialize debug package *
X *******************************************/
X
Xxldebuginit()
X{
X debug_level = 0;
X debug_fp = NULL;
X
X xlsubr("debug", debug);
X}
//go.sysin dd *
/bin/chmod 664 xldebug.c
/bin/echo -n ' '; /bin/ls -ld xldebug.c
/bin/echo 'Extracting xldmem.c'
sed 's/^X//' <<'//go.sysin dd *' >xldmem.c
X /* xldmem - xlisp dynamic memory management routines */
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
X /* useful definitions */
X
X#define ALLOCSIZE (sizeof(struct segment) + anodes * sizeof(struct node))
X
X
X /* memory segment structure definition */
X
Xstruct segment {
X int sg_size;
X struct segment *sg_next;
X struct node sg_nodes[];
X};
X
X /* external variables */
X
Xextern struct node *oblist;
Xextern struct node *xlstack;
Xextern struct node *xlenv;
X
X
X /* external procedures */
X
Xextern char *malloc();
Xextern char *calloc();
X
X
X /* local variables */
X
Xint anodes,nnodes,nsegs,nfree,gccalls;
Xstatic struct segment *segs;
Xstatic struct node *fnodes;
X
X
X /**********************************
X * newnode - allocate a new node *
X **********************************/
X
Xstruct node *newnode(type)
X int type;
X{
X struct node *nnode;
X
X /* get a free node */
X if ((nnode = fnodes) == NULL) {
X gc();
X if ((nnode = fnodes) == NULL)
X xlfail("insufficient node space");
X }
X
X /* unlink the node from the free list */
X fnodes = nnode->n_right;
X nfree -= 1;
X
X /* initialize the new node */
X nnode->n_type = type;
X nnode->n_left = NULL;
X nnode->n_right = NULL;
X
X /* return the new node */
X return (nnode);
X}
X
X
X /*****************************************************************************
X * stralloc - allocate memory for a string adding a byte for the terminator *
X *****************************************************************************/
X
Xchar *stralloc(size)
X int size;
X{
X char *sptr;
X
X /* allocate memory for the string copy */
X if ((sptr = malloc(size+1)) == NULL) {
X gc();
X if ((sptr = malloc(size+1)) == NULL)
X xlfail("insufficient string space");
X }
X
X /* return the new string memory */
X return (sptr);
X}
X
X
X /**************************************************
X * strsave - generate a dynamic copy of a string *
X **************************************************/
X
Xchar *strsave(str)
X char *str;
X{
X char *sptr;
X
X /* */
X sptr = stralloc(strlen(str));
X strcpy(sptr,str);
X
X /* return the new string */
X return (sptr);
X}
X
X
X /*********************************
X * strfree - free string memory *
X *********************************/
X
Xstrfree(str)
X char *str;
X{
X free(str);
X}
X
X
X /*************************
X * gc - garbage collect *
X *************************/
X
Xstatic gc()
X{
X unmark(); /* Unmark all nodes */
X
X#ifdef DEBUG
X xldbgmsg("\n\tOBLIST mark");
X mark(oblist);
X xldbgmsg("\n\tSTACK mark");
X mark(xlstack);
X xldbgmsg("\n\tENVIRONMENT");
X mark(xlenv);
X#else
X mark(oblist); /* Mark all accessible nodes */
X mark(xlstack);
X mark(xlenv);
X#endif
X
X sweep(); /* Sweep up the grabage */
X
X if (fnodes == NULL) /* Allocate more if necessary */
X addseg();
X
X gccalls += 1;
X}
X
X
X /******************************
X * unmark - unmark each node *
X ******************************/
X
Xstatic unmark()
X{
X struct node *n = xlstack;
X
X while (n != NULL) /* Unmark the stack */
X {
X n->n_flags &= ~(MARK | LEFT);
X n = n->n_listnext;
X }
X}
X
X /*************************************
X * mark - mark all accessible nodes *
X *************************************/
X
Xstatic mark(ptr)
X struct node *ptr;
X{
X struct node *this,*prev,*tmp;
X
X if (ptr == NULL) /* Return on null */
X return;
X
X prev = NULL; /* Initialize */
X this = ptr;
X
X while (TRUE) /* Mark this list */
X {
X while (TRUE) /* Descend as far as we can */
X {
X if (this->n_flags & MARK) /* Node already marked ? */
X break;
X else /* NO : mark it and its descendents */
X {
X
X#ifdef DEBUG
X xldump(this);
X#endif
X this->n_flags |= MARK; /* This node ...*/
X
X if (left(this)) /* .. the left sublist */
X {
X this->n_flags |= LEFT;
X tmp = prev;
X prev = this;
X this = prev->n_left;
X prev->n_left = tmp;
X }
X else
X if (right(this)) /* .. the right sublist */
X {
X this->n_flags &= ~LEFT;
X tmp = prev;
X prev = this;
X this = prev->n_right;
X prev->n_right = tmp;
X }
X else
X break;
X }
X }
X
X while (TRUE) /* Backup to last restart point */
X {
X if (prev == NULL) /* Finished yet ? */
X return;
X
X if (prev->n_flags & LEFT) /* Coming from left side ? */
X {
X if (right(prev))
X {
X prev->n_flags &= ~LEFT;
X tmp = prev->n_left;
X prev->n_left = this;
X this = prev->n_right;
X prev->n_right = tmp;
X break;
X }
X else
X {
X tmp = prev;
X prev = tmp->n_left;
X tmp->n_left = this;
X this = tmp;
X }
X }
X else /* came from the right side */
X {
X tmp = prev;
X prev = tmp->n_right;
X tmp->n_right = this;
X this = tmp;
X }
X }
X }
X}
X
X
X /*******************************************************************
X * sweep - sweep all unmarked nodes and add them to the free list *
X *******************************************************************/
X
Xstatic sweep()
X{
X struct segment *seg;
X struct node *n;
X int i;
X
X fnodes = NULL; /* Empty the free list */
X nfree = 0;
X
X /* add all unmarked nodes */
X for (seg = segs; seg != NULL; seg = seg->sg_next)
X for (i = 0; i < seg->sg_size; i++)
X if (!((n = &seg->sg_nodes[i])->n_flags & MARK))
X {
X switch (n->n_type)
X {
X case STR:
X if (n->n_strtype == DYNAMIC && n->n_str != NULL)
X strfree(n->n_str);
X break;
X
X case SYM:
X if (n->n_symname != NULL)
X strfree(n->n_symname);
X break;
X
X#ifdef KEYMAPCLASS
X case KMAP:
X xlkmfree(n);
X break;
X#endif
X }
X
X n->n_type = FREE;
X n->n_left = NULL;
X n->n_right = fnodes;
X fnodes = n;
X nfree += 1;
X }
X else
X n->n_flags &= ~MARK;
X}
X
X
X /***************************************************
X * addseg - add a segment to the available memory *
X ***************************************************/
X
Xstatic int addseg()
X{
X struct segment *newseg;
X int i;
X
X /* allocate a new segment */
X if ((newseg = (struct segment *) calloc(1,ALLOCSIZE)) != NULL)
X {
X newseg->sg_size = anodes; /* Initialize the new segment */
X newseg->sg_next = segs;
X segs = newseg;
X /* add each new node to the free list */
X for (i = 0; i < newseg->sg_size; i++)
X {
X newseg->sg_nodes[i].n_right = fnodes;
X fnodes = &newseg->sg_nodes[i];
X }
X
X nnodes += anodes; /* Update the statistics */
X nfree += anodes;
X nsegs += 1;
X
X return (TRUE); /* return success */
X }
X else
X return (FALSE);
X}
X
X
X /************************************
X * left - check for a left sublist *
X ************************************/
X
Xstatic int left(n)
X struct node *n;
X{
X switch (n->n_type)
X {
X case SYM:
X case SUBR:
X case INT:
X case STR:
X case FPTR:
X case REAL:
X return (FALSE);
X
X#ifdef KEYMAPCLASS
X case KMAP:
X xlkmmark(n);
X return (FALSE);
X#endif
X
X case LIST:
X case OBJ:
X return (n->n_left != NULL);
X
X default:
X printf("bad node type (%d) found during left scan\n",n->n_type);
X exit();
X }
X}
X
X
X /**************************************
X * right - check for a right sublist *
X **************************************/
X
Xstatic int right(n)
X struct node *n;
X{
X switch (n->n_type)
X {
X case SUBR:
X case INT:
X case REAL:
X case STR:
X case FPTR:
X case KMAP:
X return (FALSE);
X
X case SYM:
X case LIST:
X case OBJ:
X return (n->n_right != NULL);
X
X default:
X printf("bad node type (%d) found during right scan\n",n->n_type);
X exit();
X }
X}
X
X
X /************************************
X * stats - print memory statistics *
X ************************************/
X
Xstatic stats()
X{
X printf("\nNodes: %d\n",nnodes);
X printf("Free nodes: %d\n",nfree);
X printf("Segments: %d\n",nsegs);
X printf("Allocate: %d\n",anodes);
X printf("Collections: %d\n\n",gccalls);
X}
X
X
X /*****************************************************
X * fgc - xlisp function to force garbage collection *
X *****************************************************/
X
Xstatic struct node *fgc(args)
X struct node *args;
X{
X xllastarg(args); /* No arguments */
X gc(); /* Collect that garbage */
X return (NULL);
X}
X
X
X /*******************************************************
X * fexpand - xlisp function to force memory expansion *
X *******************************************************/
X
Xstatic struct node *fexpand(args)
X struct node *args;
X{
X struct node *val;
X int n,i;
X
X /* get new number to allocate */
X n = (args == NULL) ? 1 : xlevmatch(INT, &args)->n_int;
X xllastarg(args); /* No more arguments */
X
X for (i = 0; i < n; i++) /* Allocate more segments */
X if (!addseg())
X break;
X
X val = newnode(INT); /* Return number of segments added */
X val->n_int = i;
X return (val);
X}
X
X /*******************************************************************
X * falloc - xlisp function to set the number of nodes to allocate *
X *******************************************************************/
X
Xstatic struct node *falloc(args)
X struct node *args;
X{
X struct node *val;
X int n,oldn;
X
X n = xlevmatch(INT,&args)->n_int; /* new number to allocate */
X xllastarg(args); /* No more arguments */
X
X oldn = anodes; /* Set new number */
X anodes = n;
X
X val = newnode(INT); /* Return old value */
X val->n_int = oldn;
X return (val);
X}
X
X
X /*****************************************************
X * fmem - xlisp function to print memory statistics *
X *****************************************************/
X
Xstatic struct node *fmem(args)
X struct node *args;
X{
X xllastarg(args); /* No arguments */
X stats(); /* Print statistics */
X return (NULL);
X}
X
X
X /******************************************************
X * xldmeminit - initialize the dynamic memory module *
X ******************************************************/
X
Xxldmeminit()
X{
X anodes = NNODES; /* Default number of nodes */
X nnodes = nsegs = nfree = gccalls = 0;
X
X xlsubr("gc",fgc); /* Define some xlisp functions */
X xlsubr("expand",fexpand);
X xlsubr("alloc",falloc);
X xlsubr("mem",fmem);
X}
//go.sysin dd *
/bin/chmod 664 xldmem.c
/bin/echo -n ' '; /bin/ls -ld xldmem.c
/bin/echo 'Extracting xleval.c'
sed 's/^X//' <<'//go.sysin dd *' >xleval.c
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
X /* trace stack */
X static struct node *trace_stack[TDEPTH];
X static int trace_pointer;
X
X /* external variables */
X extern struct node *xlenv;
X
X /* local variables */
X static struct node *slash;
X
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
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 = xlevarg(&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 REAL:
X return (expr);
X
X default:
X xlfail("can't evaluate expression");
X }
X}
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
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;
X
X oldstk = xlsave(&fun,&args,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 = xleval(fun.n_ptr)) == NULL) /* Evaluate first expression */
X xlfail("null function");
X
X switch (fun.n_ptr->n_type) /* Evaluate function */
X {
X case SUBR:
X val = (*fun.n_ptr->n_subr)(args.n_ptr);
X break;
X
X case LIST:
X val = evfun(fun.n_ptr,args.n_ptr);
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 }
X
X xlstack = oldstk; /* Restore old stack frame */
X tpop(); /* Remove trace entry */
X return (val); /* and return result value */
X}
X
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
X oldstk = xlsave(&cptr,NULL); /* Creat a new stack frame */
X
X /* get the formal argument list */
X if ((fargs = fun->n_listvalue) != NULL && fargs->n_type != LIST)
X xlfail("bad formal argument list");
X
X oldenv = xlenv; /* Bind the formal parameters*/
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);
X
X xlunbind(oldenv); /* Restore environment */
X xlstack = oldstk; /* ..then the stack frame */
X return (val); /* ...and return result */
X}
X
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 *oldstk,farg,aarg,val;
X
X oldstk = xlsave(&farg,&aarg,&val,NULL); /* Create a stack frame */
X
X farg.n_ptr = fargs; /* Initialze the pointers */
X aarg.n_ptr = aargs;
X
X while (farg.n_ptr != NULL && aarg.n_ptr != NULL) /* evaluate and bind */
X {
X if (farg.n_ptr->n_listvalue == slash) /* Check for local separator*/
X break;
X
X val.n_ptr = xlevarg(&aarg.n_ptr); /* Evaluate the arg */
X xlbind(farg.n_ptr->n_listvalue,val.n_ptr); /* ..and bind to formal */
X
X farg.n_ptr = farg.n_ptr->n_listnext; /* Move pointer ahead */
X }
X
X /* check for local variables */
X if (farg.n_ptr != NULL && farg.n_ptr->n_listvalue == slash)
X while ((farg.n_ptr = farg.n_ptr->n_listnext) != NULL)
X xlbind(farg.n_ptr->n_listvalue,NULL);
X
X xlstack = oldstk; /* Restore old stack frame */
X
X if (farg.n_ptr != aarg.n_ptr) /* Check for correct # */
X xlfail("incorrect number of arguments to a function");
X}
X
X
X
X /************************************
X * xlfail - error handling routine *
X ************************************/
X
Xxlfail(err)
X char *err;
X{
X printf("error: %s\n",err); /* Print the error message */
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
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}
//go.sysin dd *
/bin/chmod 664 xleval.c
/bin/echo -n ' '; /bin/ls -ld xleval.c
/bin/echo 'Extracting xlfio.c'
sed 's/^X//' <<'//go.sysin dd *' >xlfio.c
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 = xlevmatch(STR,&arg.n_ptr);
X mode.n_ptr = xlevmatch(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 = xlevmatch(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 = xlevmatch(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 = xlevmatch(INT,&arg.n_ptr);
X
X if (arg.n_ptr != NULL)
X fp = xlevmatch(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 = xlevmatch(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(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 = xlevmatch(STR,&arg.n_ptr);
X
X if (arg.n_ptr != NULL)
X fp = xlevmatch(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}
//go.sysin dd *
/bin/chmod 664 xlfio.c
/bin/echo -n ' '; /bin/ls -ld xlfio.c
/bin/echo 'Extracting xlsubr.c'
sed 's/^X//' <<'//go.sysin dd *' >xlsubr.c
X /* xlsubr - xlisp builtin functions */
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 int (*xlgetc)();
Xextern struct node *xlstack;
X
X
X /* local variables */
X
Xstatic char *sgetptr;
X
X
X /***************************************
X * xlsubr - define a builtin function *
X ***************************************/
X
Xxlsubr(sname,subr)
X char *sname; struct node *(*subr)();
X{
X struct node *sym;
X
X sym = xlenter(sname); /* Enter the symbol */
X
X sym->n_symvalue = newnode(SUBR); /* Initialize the value */
X sym->n_symvalue->n_subr = subr;
X}
X
X
X /**********************************************
X * xlsvar - define a builtin string variable *
X **********************************************/
X
Xxlsvar(sname,str)
X char *sname,*str;
X{
X struct node *sym;
X
X sym = xlenter(sname); /* Enter the symbol */
X
X sym->n_symvalue = newnode(STR); /* Initialize the value */
X sym->n_symvalue->n_str = strsave(str);
X}
X
X
X /**********************************
X * xlarg - get the next argument *
X **********************************/
X
Xstruct node *xlarg(pargs)
X struct node **pargs;
X{
X struct node *arg;
X
X if (*pargs == NULL) /* Does argument exist ? */
X xlfail("too few arguments");
X
X arg = (*pargs)->n_listvalue; /* If so get its value */
X *pargs = (*pargs)->n_listnext; /* and mov arg pointer ahead */
X
X return (arg);
X}
X
X
X /*************************************************
X * xlmatch - get an argument and match its type *
X *************************************************/
X
Xstruct node *xlmatch(type,pargs)
X int type; struct node **pargs;
X{
X struct node *arg;
X
X arg = xlarg(pargs); /* Get the argument */
X if (type == LIST) /* Check its type */
X {
X if (arg != NULL && arg->n_type != LIST)
X xlfail("bad argument type");
X }
X else
X {
X if (arg == NULL || arg->n_type != type)
X xlfail("bad argument type");
X }
X
X return (arg);
X}
X
X
X /****************************************************
X * xlevarg - get the next argument and evaluate it *
X ****************************************************/
X
Xstruct node *xlevarg(pargs)
X struct node **pargs;
X{
X struct node *oldstk,val;
X
X oldstk = xlsave(&val,NULL); /* Creat new stack frame */
X
X val.n_ptr = xlarg(pargs); /* Get and evaluate the argument */
X val.n_ptr = xleval(val.n_ptr);
X
X xlstack = oldstk; /* Restore old stack frame */
X return (val.n_ptr);
X}
X
X
X /*************************************************************
X * xlevmatch - get an evaluated argument and match its type *
X *************************************************************/
X
Xstruct node *xlevmatch(type,pargs)
X int type; struct node **pargs;
X{
X struct node *arg;
X
X arg = xlevarg(pargs); /* Get argument and check type */
X if (type == LIST)
X {
X if (arg != NULL && arg->n_type != LIST)
X xlfail("bad argument type");
X }
X else
X {
X if (arg == NULL || arg->n_type != type)
X xlfail("bad argument type");
X }
X
X return (arg);
X}
X
X
X /**********************************************************************
X * xllastarg - make sure the remainder of the argument list is empty *
X **********************************************************************/
X
Xxllastarg(args)
X struct node *args;
X{
X if (args != NULL)
X xlfail("too many arguments");
X}
X
X
X /****************************************
X * assign - assign a value to a symbol *
X ****************************************/
X
Xstatic assign(sym,val)
X struct node *sym,*val;
X{
X struct node *lptr;
X
X if ((lptr = xlobsym(sym)) != NULL) /* Check for a current object */
X lptr->n_listvalue = val;
X else
X sym->n_symvalue = val;
X}
X
X
X /*******************************
X * set - builtin function set *
X *******************************/
X
Xstatic struct node *set(args)
X struct node *args;
X{
X struct node *oldstk,arg,sym,val;
X
X oldstk = xlsave(&arg,&sym,&val,NULL); /* Create new stack frame */
X arg.n_ptr = args;
X
X sym.n_ptr = xlevmatch(SYM,&arg.n_ptr); /* Get symbol */
X val.n_ptr = xlevarg(&arg.n_ptr);
X xllastarg(arg.n_ptr);
X assign(sym.n_ptr,val.n_ptr);
X
X xlstack = oldstk; /* Restore old stack frame */
X return (val.n_ptr);
X}
X
X
X /*********************************
X * setq - builtin function setq *
X *********************************/
X
Xstatic struct node *setq(args)
X struct node *args;
X{
X struct node *oldstk,arg,sym,val;
X
X oldstk = xlsave(&arg,&sym,&val,NULL); /* Create new stack frame */
X arg.n_ptr = args;
X
X sym.n_ptr = xlmatch(SYM,&arg.n_ptr); /* get symbol */
X val.n_ptr = xlevarg(&arg.n_ptr);
X xllastarg(arg.n_ptr);
X assign(sym.n_ptr,val.n_ptr);
X
X xlstack = oldstk; /* Restore old stack frame */
X return (val.n_ptr);
X}
X
X
X /************************************
X * load - direct input from a file *
X ************************************/
X
Xstatic struct node *load(args)
X struct node *args;
X{
X struct node *fname;
X
X fname = xlevmatch(STR,&args); /* Get file name */
X xllastarg(args);
X
X xlfin(fname->n_str);
X
X return (fname);
X}
X
X
X /***********************************
X * defun - builtin function defun *
X ***********************************/
X
Xstatic struct node *defun(args)
X struct node *args;
X{
X struct node *oldstk,arg,sym,fargs,fun;
X
X /* create a new stack frame */
X oldstk = xlsave(&arg,&sym,&fargs,&fun,NULL);
X
X /* initialize */
X arg.n_ptr = args;
X
X /* get the function symbol */
X sym.n_ptr = xlmatch(SYM,&arg.n_ptr);
X
X /* get the formal argument list */
X fargs.n_ptr = xlmatch(LIST,&arg.n_ptr);
X
X /* create a new function definition */
X fun.n_ptr = newnode(LIST);
X fun.n_ptr->n_listvalue = fargs.n_ptr;
X fun.n_ptr->n_listnext = arg.n_ptr;
X
X /* make the symbol point to a new function definition */
X assign(sym.n_ptr,fun.n_ptr);
X
X /* restore the previous stack frame */
X xlstack = oldstk;
X
X /* return the function symbol */
X return (sym.n_ptr);
X}
X
X
X /******************************************
X * sgetc - get a character from a string *
X ******************************************/
X
Xstatic int sgetc()
X{
X if (*sgetptr == 0)
X return (-1);
X else
X return (*sgetptr++);
X}
X
X
X /******************************
X * read - read an expression *
X ******************************/
X
Xstatic struct node *read(args)
X struct node *args;
X{
X struct node *val;
X int (*oldgetc)();
X
X /* save the old input stream */
X oldgetc = xlgetc;
X
X /* get the string or file pointer */
X if (args != NULL) {
X sgetptr = xlevmatch(STR,&args)->n_str;
X xlgetc = sgetc;
X }
X
X /* make sure there aren't any more arguments */
X xllastarg(args);
X
X val = xlread();
X xlgetc = oldgetc;
X
X return (val);
X}
X
X
X /************************************
X * fwhile - builtin function while *
X ************************************/
X
Xstatic struct node *fwhile(args)
X struct node *args;
X{
X struct node *oldstk,farg,arg,*val;
X
X /* create a new stack frame */
X oldstk = xlsave(&farg,&arg,NULL);
X
X /* initialize */
X farg.n_ptr = arg.n_ptr = args;
X
X /* loop until test fails */
X val = NULL;
X for (; TRUE; arg.n_ptr = farg.n_ptr) {
X
X /* evaluate the test expression */
X if (!testvalue(xlevarg(&arg.n_ptr)))
X break;
X
X /* evaluate each remaining argument */
X while (arg.n_ptr != NULL)
X val = xlevarg(&arg.n_ptr);
X }
X
X /* restore the previous stack frame */
X xlstack = oldstk;
X
X /* return the last test expression value */
X return (val);
X}
X
X
X /**************************************
X **************************************/
X
Xstatic struct node *frepeat(args)
X struct node *args;
X{
X struct node *oldstk,farg,arg,*val;
X int cnt;
X
X /* create a new stack frame */
X oldstk = xlsave(&farg,&arg,NULL);
X
X /* initialize */
X arg.n_ptr = args;
X
X cnt = xlevmatch(INT,&arg.n_ptr)->n_int;
X
X /* save the first expression to repeat */
X farg.n_ptr = arg.n_ptr;
X
X /* loop until test fails */
X val = NULL;
X for (; cnt > 0; cnt--) {
X
X /* evaluate each remaining argument */
X while (arg.n_ptr != NULL)
X val = xlevarg(&arg.n_ptr);
X
X /* restore pointer to first expression */
X }
X
X /* restore the previous stack frame */
X xlstack = oldstk;
X
X /* return the last test expression value */
X return (val);
X}
X
X
X /***************************************
X * foreach - builtin function foreach *
X ***************************************/
X
Xstatic struct node *foreach(args)
X struct node *args;
X{
X struct node *oldstk,arg,sym,list,code,oldbnd,*val;
X
X /* create a new stack frame */
X oldstk = xlsave(&arg,&sym,&list,&code,&oldbnd,NULL);
X
X /* initialize */
X arg.n_ptr = args;
X
X /* get the symbol to bind to each list element */
X sym.n_ptr = xlmatch(SYM,&arg.n_ptr);
X /* save the old binding of the symbol */
X oldbnd.n_ptr = sym.n_ptr->n_symvalue;
X
X /* get the list to iterate over */
X list.n_ptr = xlevmatch(LIST,&arg.n_ptr);
X
X /* save the pointer to the code */
X code.n_ptr = arg.n_ptr;
X
X /* loop until test fails */
X val = NULL;
X while (list.n_ptr != NULL) {
X
X /* check the node type */
X if (list.n_ptr->n_type != LIST)
X xlfail("bad node type in list");
X
X /* bind the symbol to the list element */
X sym.n_ptr->n_symvalue = list.n_ptr->n_listvalue;
X
X /* evaluate each remaining argument */
X while (arg.n_ptr != NULL)
X val = xlevarg(&arg.n_ptr);
X
X /* point to the next list element */
X list.n_ptr = list.n_ptr->n_listnext;
X
X /* restore the pointer to the code */
X arg.n_ptr = code.n_ptr;
X }
X
X /* restore the previous stack frame */
X xlstack = oldstk;
X
X /* restore the old binding of the symbol */
X sym.n_ptr->n_symvalue = oldbnd.n_ptr;
X
X /* return the last test expression value */
X return (val);
X}
X
X
X /******************************
X * fif - builtin function if *
X ******************************/
X
Xstatic struct node *fif(args)
X struct node *args;
X{
X struct node *oldstk,arg,testexpr,thenexpr,elseexpr,*val;
X int dothen;
X
X /* create a new stack frame */
X oldstk = xlsave(&arg,&testexpr,&thenexpr,&elseexpr,NULL);
X
X /* initialize */
X arg.n_ptr = args;
X
X /* evaluate the test expression */
X testexpr.n_ptr = xlevarg(&arg.n_ptr);
X
X /* get the then clause */
X thenexpr.n_ptr = xlmatch(LIST,&arg.n_ptr);
X
X /* get the else clause */
X if (arg.n_ptr != NULL)
X elseexpr.n_ptr = xlmatch(LIST,&arg.n_ptr);
X else
X elseexpr.n_ptr = NULL;
X
X /* make sure there aren't any more arguments */
X xllastarg(arg.n_ptr);
X
X /* figure out which expression to evaluate */
X dothen = testvalue(testexpr.n_ptr);
X
X /* default the result value to the value of the test expression */
X val = testexpr.n_ptr;
X
X /* evaluate the appropriate clause */
X if (dothen)
X while (thenexpr.n_ptr != NULL)
X val = xlevarg(&thenexpr.n_ptr);
X else
X while (elseexpr.n_ptr != NULL)
X val = xlevarg(&elseexpr.n_ptr);
X
X /* restore the previous stack frame */
X xlstack = oldstk;
X
X /* return the last value */
X return (val);
X}
X
X
X /****************************************************
X * quote - builtin function to quote an expression *
X ****************************************************/
X
Xstatic struct node *quote(args)
X struct node *args;
X{
X /* make sure there is exactly one argument */
X if (args == NULL || args->n_listnext != NULL)
X xlfail("incorrect number of arguments");
X
X /* return the quoted expression */
X return (args->n_listvalue);
X}
X
X
X /*****************************
X * fexit - get out of xlisp *
X *****************************/
X
Xfexit()
X{
X exit();
X}
X
X
X /***********************************************
X * testvalue - test a value for true or false *
X ***********************************************/
X
Xstatic int testvalue(val)
X struct node *val;
X{
X /* check for a nil value */
X if (val == NULL)
X return (FALSE);
X
X /* check the value type */
X switch (val->n_type) {
X case INT:
X return (val->n_int != 0);
X
X case STR:
X return (strlen(val->n_str) != 0);
X
X default:
X return (TRUE);
X }
X}
X
X
X /******************************************
X * xlinit - xlisp initialization routine *
X ******************************************/
X
Xxlinit()
X{
X /* enter a copyright notice into the oblist */
X xlenter("Copyright-1983-by-David-Betz");
X
X /* enter the builtin functions */
X xlsubr("set",set);
X xlsubr("setq",setq);
X xlsubr("load",load);
X xlsubr("read",read);
X xlsubr("quote",quote);
X xlsubr("while",fwhile);
X xlsubr("repeat",frepeat);
X xlsubr("foreach",foreach);
X xlsubr("defun",defun);
X xlsubr("if",fif);
X xlsubr("exit",fexit);
X}
//go.sysin dd *
/bin/chmod 664 xlsubr.c
/bin/echo -n ' '; /bin/ls -ld xlsubr.c
More information about the Comp.sources.unix
mailing list