Modified XLISP, part 5 of 5
John Woods
john at x.UUCP
Tue Aug 28 00:26:55 AEST 1984
This represents part 5 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 xlread.c
sed -n -e 's/^X//p' > xlread.c << '!Funky!Stuff!'
X
X /* xlread - xlisp expression input routine */
X#define static
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 <ctype.h>
X#include "xlisp.h"
X#endif
X
X /* global variables */
X
Xstruct node *oblist;
X
X /* external variables */
X
Xextern struct node *xlstack;
Xextern int (*xlgetc)();
Xextern int xlplevel;
X
X /* local variables */
X
Xstatic int savech;
X#ifdef HACK
X /* forward declarations (the extern hack is for decusc) */
X
Xextern struct node *parse();
Xextern struct node *plist();
Xextern struct node *pstring();
Xextern struct node *pnumber();
Xextern struct node *pquote();
Xextern struct node *pname();
X#endif
X#ifdef REALS
Xextern struct node *pfloat();
X#endif
X
X /**************************************
X * xlread - read an xlisp expression *
X **************************************/
X
Xstruct node *xlread()
X{
X savech = -1; /* initialize */
X xlplevel = 0;
X
X return (parse()); /* Parse an expression */
X}
X
X
X /**************************************
X * parse - parse an xlisp expression *
X **************************************/
X
Xstatic struct node *parse()
X{
X int ch;
X
X while (TRUE) /* Look for a node, skipp comments */
X {
X switch (ch = nextch()) /* Switch on next character */
X {
X case '\'': /* a quoted expression */
X return (pquote());
X
X case '(': /* a sublist */
X return (plist());
X
X case ')': /* closing paren - shouldn't happen */
X/* xlfail("extra right paren"); */
X getch();
X break;
X
X case '.':
X#ifdef REALS
X return (pfloat(0)); /* Real fractional only */
X#else
X xlfail("misplaced dot");/* dot - shouldn't happen */
X#endif
X
X case ';': /* a comment */
X pcomment();
X break;
X
X case '|': /* a superquoted symbol */
X case '"': /* a string */
X return (pstring(ch));
X
X default:
X if (!issym(ch))
X xlfail("invalid character");
X /* else ... */
X case '\\':
X return (pword());
X }
X }
X}
X
X
X /*******************************
X * pcomment - parse a comment *
X *******************************/
X
Xstatic pcomment()
X{
X while (getch() != '\n') /* Skip to end of line */
X ;
X}
X
X
X /*************************
X * plist - parse a list *
X *************************/
X
Xstatic struct node *plist()
X{
X struct node *oldstk,val,*lastnptr,*nptr;
X int ch;
X
X xlplevel += 1; /* Increment nesting level */
X oldstk = xlsave(&val,NULL); /* Create .... */
X savech = -1; /* Skip opend paren */
X
X /* keep appending nodes until a closing paren is found */
X for (lastnptr = NULL; (ch = nextch()) > 0 && ch != ')'; lastnptr = nptr)
X {
X if (ch == '.') /* Check for a dotted pair */
X {
X savech = -1; /* Skip the dot */
X
X if (lastnptr == NULL) /* Make sure there is a node */
X xlfail("invalid dotted pair");
X
X lastnptr->n_listnext = parse(); /* Parse expression */
X
X if (nextch() != ')') /* Check for closing paren */
X xlfail("invalid dotted pair");
X
X break; /* Done with this list */
X }
X
X nptr = newnode(LIST); /* Allocate and link new node */
X if (lastnptr == NULL)
X val.n_ptr = nptr;
X else
X lastnptr->n_listnext = nptr;
X
X nptr->n_listvalue = parse(); /* Initialize it */
X }
X
X savech = -1; /* Skip the closing paren */
X
X xlstack = oldstk; /* Restore previous stack frame */
X xlplevel -= 1; /* Decrement nesting level */
X
X return (val.n_ptr); /* Successful return */
X}
X
X /*****************************
X * pstring - parse a string *
X *****************************/
X
Xstatic struct node *pstring(term)
X int term; /* terminator */
X{
X struct node *oldstk,val;
X char sbuf[STRMAX+1];
X int ch,i,d1,d2,d3;
X
X oldstk = xlsave(&val,NULL); /* Create a new stack frame */
X savech = -1; /* Skip opening quote */
X
X /* loop looking for a closing qte */
X for (i = 0; i < STRMAX && (ch = getch()) != term; i++)
X {
X switch (ch)
X {
X case '\\':
X switch (ch = getch())
X {
X case 'e':
X ch = '\033';
X break;
X
X case 'n':
X ch = '\n';
X break;
X
X case 'r':
X ch = '\r';
X break;
X
X case 't':
X ch = '\t';
X break;
X
X case '0':
X case '1':
X case '2':
X case '3':
X case '4':
X case '5':
X case '6':
X case '7':
X d1 = ch - '0';
X while (((ch = getch()) >= '0') && (ch < '8'))
X d1 = d1 <<3 + (ch - '0');
X ch = d1;
X break;
X
X default:
X break;
X }
X }
X sbuf[i] = ch;
X }
X sbuf[i] = 0;
X
X if (term == '|')
X return xlenter(sbuf);
X
X val.n_ptr = newnode(STR); /* Initialize the node */
X val.n_ptr->n_str = strsave(sbuf);
X
X xlstack = oldstk; /* Restore old stack frame */
X return (val.n_ptr); /* .. and return */
X}
X
X
X#ifdef REALS
X /********************************************************
X * pfloat - parse the fractional part of a real number *
X ********************************************************/
X
Xstatic struct node *pfloat(i)
X int i;
X{
X struct node *val;
X int ch;
X long float rval = (float) ((i<0) ? -i : i), fp= 1;
X
X for ( ; isdigit(ch = thisch()); savech = -1)
X rval = rval + (ch - '0')/(fp *= 10);
X
X if (issym(ch)) /* ensure correct termination */
X xlfail("badly formed number");
X
X val = newnode(REAL); /* Initialze the new node */
X val->n_real = (i < 0) ? -rval : rval;
X
X return (val);
X}
X#endif
X
X /*****************************
X * pnumber - parse a number *
X *****************************/
X
Xstruct node *pnumber(buf)
X char *buf;
X{
X struct node *val;
X int ch,ival = 0, sign = 1;
X
X if (*buf == '+') buf++;
X else if (*buf == '-') sign = -1, buf++;
X
X for ( ; isdigit(*buf); ++buf) /* loop while digits */
X ival = ival * 10 + *buf - '0';
X
X#ifdef REALS
X if (thisch() == '.')
X {
X savech = -1;
X return pfloat(sign*ival);
X }
X#endif
X
X val = newnode(INT); /* Initialze the new node */
X val->n_int = sign * ival;
X
X return (val);
X}
X
X /* isallnumeric - is all of this char buffer numeric? */
Xint isallnumeric(s) char *s;
X{
X if (*s == '+' || *s == '-') {
X s++;
X if (!*s) return 0;
X }
X while (*s) if (!isdigit(*s)) return 0; else s++;
X return 1;
X}
X
X /***************************************************
X * xlenter - enter a symbol into the symbol table *
X ***************************************************/
X
Xstruct node *xlenter(sname)
X char *sname;
X{
X struct node *sptr;
X
X if (strcmp(sname,"nil") == 0) /* Check for nil */
X return (NULL);
X
X if (oblist == NULL) /* Create oblist if required */
X {
X oblist = newnode(SYM);
X oblist->n_symname = strsave("oblist");
X oblist->n_symvalue = newnode(LIST);
X oblist->n_symvalue->n_listvalue = oblist;
X }
X
X sptr = oblist->n_symvalue; /* check for symbol already in table */
X while (sptr != NULL)
X {
X if (sptr->n_listvalue == NULL)
X {
X printf("bad oblist\n");
X sptr = oblist->n_symvalue;
X while (sptr != NULL)
X {
X if (sptr->n_listvalue == NULL)
X 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,sname) == 0)
X return (sptr->n_listvalue);
X sptr = sptr->n_listnext;
X }
X
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 = newnode(SYM);
X sptr->n_listvalue->n_symname = strsave(sname);
X
X return (sptr->n_listvalue);
X}
X
X
X /***************************************
X * pquote - parse a quoted expression *
X ***************************************/
X
Xstatic struct node *pquote()
X{
X struct node *oldstk,val;
X
X oldstk = xlsave(&val,NULL); /* Create new stack frame */
X savech = -1; /* Skip the quote character */
X
X val.n_ptr = newnode(LIST); /* Allocate two new nodes */
X val.n_ptr->n_listvalue = xlenter("quote");
X val.n_ptr->n_listnext = newnode(LIST);
X val.n_ptr->n_listnext->n_listvalue = parse();
X
X xlstack = oldstk; /* Restore old stack frame */
X return (val.n_ptr); /* .. return quoted expression */
X}
X
X
X /********************************************
X * pword - parse a symbol name or a number *
X *********************************************/
X
Xstruct node *pword()
X{
X char sname[STRMAX+1];
X int ch,i, quoted = 0;
X
X /* get symbol name */
X for (i = 0; i < STRMAX && (issym(ch = thisch()) || ch == '\\'); i++)
X { if (ch == '\\')
X { quoted = 1;
X savech = -1;
X }
X sname[i] = getch();
X }
X sname[i] = 0;
X
X if (!quoted && isallnumeric(sname))
X return (pnumber(sname)); /* create number */
X
X return (xlenter(sname)); /* Create symbol */
X}
X
X
X /**************************************************
X * nextch - look at the next non-blank character *
X **************************************************/
X
Xstatic int nextch()
X{
X while (isspace(thisch())) /* Find non blank character */
X savech = -1;
X
X return savech; /* .. and return it */
X}
X
X
X /*******************************************
X * thisch - look at the current character *
X *******************************************/
X
Xstatic int thisch()
X{
X return (savech = getch()); /* return and save next character */
X}
X
X
X /***********************************
X * getch - get the next character *
X ***********************************/
X
Xstatic int getch()
X{
X int ch;
X
X if ((ch = savech) >= 0) /* Check for saved character */
X savech = -1;
X else
X ch = (*xlgetc)();
X
X if (ch == EOF) /* Check for abort character */
X if (xlplevel > 0)
X {
X putchar('\n');
X xltin(FALSE);
X xlfail("input aborted");
X }
X else
X exit();
X
X return (ch); /* Return char */
X}
X
X
X /****************************************************************
X * issym - check whether a character if valid in a symbol name *
X ****************************************************************/
X
Xstatic int issym(ch)
X int ch;
X{
X if (isspace(ch))
X return FALSE;
X
X return (index("();.\"'|\\",ch) == 0);
X
X}
!Funky!Stuff!
echo x xlstr.c
sed -n -e 's/^X//p' > xlstr.c << '!Funky!Stuff!'
X /* xlstr - xlisp string builtin 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 /* external procedures */
X
Xextern char *strcat();
X
X
X /*********************************
X * xstrlen - length of a string *
X *********************************/
X
Xstatic struct node *xstrlen(args)
X struct node *args;
X{
X struct node *oldstk,arg,*val;
X int total;
X
X oldstk = xlsave(&arg,NULL);
X arg.n_ptr = args;
X total = 0;
X
X while (arg.n_ptr != NULL)
X total += strlen(xlmatch(STR,&arg.n_ptr)->n_str);
X
X xlstack = oldstk;
X
X val = newnode(INT);
X val->n_int = total;
X
X return (val);
X}
X
X
X /*********************************************
X * xstrcat - concatenate a bunch of strings *
X *********************************************/
X
X
Xstatic struct node *xstrcat(args)
X struct node *args;
X{
X/* this routine does it the dumb way -- one at a time */
X struct node *oldstk,arg,val,rval;
X int newlen;
X char *result,*argstr,*newstr;
X
X oldstk = xlsave(&arg,&val,&rval,NULL);
X arg.n_ptr = args;
X rval.n_ptr = newnode(STR);
X rval.n_ptr->n_str = result = stralloc(0);
X *result = 0;
X
X while (arg.n_ptr != NULL) {
X val.n_ptr = xlmatch(STR,&arg.n_ptr);
X argstr = val.n_ptr->n_str;
X newlen = strlen(result) + strlen(argstr);
X newstr = stralloc(newlen);
X strcpy(newstr,result);
X strfree(result);
X rval.n_ptr->n_str = result = strcat(newstr,argstr);
X }
X
X xlstack = oldstk;
X return (rval.n_ptr);
X}
X
X
X /********************************
X * substr - return a substring *
X ********************************/
X
Xstatic struct node *substr(args)
X struct node *args;
X{
X struct node *oldstk,arg,src,val;
X int start,forlen,srclen;
X char *srcptr,*dstptr;
X
X oldstk = xlsave(&arg,&src,&val,NULL);
X arg.n_ptr = args;
X
X src.n_ptr = xlmatch(STR,&arg.n_ptr);
X srcptr = src.n_ptr->n_str;
X srclen = strlen(srcptr);
X
X start = xlmatch(INT,&arg.n_ptr)->n_int;
X
X if (arg.n_ptr != NULL)
X forlen = xlmatch(INT,&arg.n_ptr)->n_int;
X else
X forlen = srclen; /* use len and fix below */
X
X xllastarg(arg.n_ptr);
X
X if (start + forlen > srclen)
X forlen = srclen - start + 1;
X
X if (start > srclen)
X {
X start = 1;
X forlen = 0;
X }
X
X val.n_ptr = newnode(STR);
X val.n_ptr->n_str = dstptr = stralloc(forlen);
X
X for (srcptr += start-1; forlen--; *dstptr++ = *srcptr++)
X ;
X
X *dstptr = 0;
X
X xlstack = oldstk;
X return (val.n_ptr);
X}
X
X
X /*******************************
X * ascii - return ascii value *
X *******************************/
X
Xstatic struct node *ascii(args)
X struct node *args;
X{
X struct node *oldstk,val;
X
X oldstk = xlsave(&val,NULL);
X
X val.n_ptr = newnode(INT);
X val.n_ptr->n_int = *(xlmatch(STR,&args)->n_str);
X
X xllastarg(args);
X
X xlstack = oldstk;
X return (val.n_ptr);
X}
X
X
X /***********************************************************
X * chr - convert an INT into a one character ascii string *
X ***********************************************************/
X
Xstatic struct node *chr(args)
X struct node *args;
X{
X struct node *oldstk,val;
X char *sptr;
X
X oldstk = xlsave(&val,NULL);
X
X val.n_ptr = newnode(STR);
X val.n_ptr->n_str = sptr = stralloc(1);
X *sptr++ = xlmatch(INT,&args)->n_int;
X *sptr = 0;
X
X xllastarg(args);
X
X xlstack = oldstk;
X return (val.n_ptr);
X}
X
X
X /**************************************************
X * xatoi - convert an ascii string to an integer *
X **************************************************/
X
Xstatic struct node *xatoi(args)
X struct node *args;
X{
X struct node *val;
X int n;
X
X n = atoi(xlmatch(STR,&args)->n_str);
X
X xllastarg(args);
X
X val = newnode(INT);
X val->n_int = n;
X return (val);
X}
X
X
X /**************************************************
X * xitoa - convert an integer to an ascii string *
X **************************************************/
X
Xstatic struct node *xitoa(args)
X struct node *args;
X{
X struct node *val;
X char buf[20];
X
X sprintf(buf,"%d",xlmatch(INT,&args)->n_int);
X
X xllastarg(args);
X
X val = newnode(STR);
X val->n_str = strsave(buf);
X return (val);
X}
X
X
X /**************************************************
X * xlsinit - xlisp string initialization routine *
X **************************************************/
X
Xxlsinit()
X{
X xlsubr("strlen",xstrlen);
X xlsubr("strcat",xstrcat);
X xlsubr("substr",substr);
X xlsubr("ascii",ascii);
X xlsubr("chr", chr);
X xlsubr("atoi",xatoi);
X xlsubr("itoa",xitoa);
X}
!Funky!Stuff!
echo x xlsubr.c
sed -n -e 's/^X//p' > xlsubr.c << '!Funky!Stuff!'
X /* xlfsubr - 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 /* external variables */
X
Xextern int (*xlgetc)();
Xextern struct node *xlstack;
X
X /* global variables */
X
Xstruct node *Lambda, *Fexpr, *Macro;
Xstruct node *Subrprop, *Fsubrprop, *Exprop, *Fexprop, *Macprop;
X
X /* local variables */
Xstatic char *sgetptr;
Xstatic struct node *t;
X
X /***************************************
X * xlsubr - define a builtin function *
X ***************************************/
X
Xxlsubr(sname,subr)
X char *sname; struct node *(*subr)();
X{
X struct node *sym, *newsubr;
X
X sym = xlenter(sname); /* Enter the symbol */
X
X (newsubr = newnode(SUBR))->n_subr = subr;
X xlputprop(sym,newsubr,Subrprop);
X}
X
X
X /*********************************************
X * xlfsubr - define a builtin funny function *
X **********************************************/
X
Xxlfsubr(sname,fsubr)
X char *sname; struct node *(*fsubr)();
X{
X struct node *sym, *newsubr;
X
X sym = xlenter(sname); /* Enter the symbol */
X
X (newsubr = newnode(FSUBR))->n_subr = fsubr;
X xlputprop(sym,newsubr,Fsubrprop);
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 = xlmatch(SYM,&arg.n_ptr); /* Get symbol */
X val.n_ptr = xlarg(&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 = xlmatch(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, *p;
X int macro = 0, fexpr = 0;
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 = xlarg(&arg.n_ptr);
X
X /* is this a magic form? */
X if ((xeq(fargs.n_ptr,Macro) && (macro=1))
X || (xeq(fargs.n_ptr,Fexpr) && (fexpr=1)))
X { fargs.n_ptr = xlmatch(LIST,&arg.n_ptr);
X } else
X if (fargs.n_ptr->n_type != LIST
X && fargs.n_ptr->n_type != SYM) xlfail("bad argument type");
X
X /* create a new function definition */
X fun.n_ptr = newnode(LIST);
X fun.n_ptr->n_listvalue = Lambda;
X p = fun.n_ptr->n_listnext = newnode(LIST);
X p->n_listvalue = fargs.n_ptr;
X p->n_listnext = arg.n_ptr;
X
X /* make the symbol point to a new function definition */
X xlputprop(sym.n_ptr,fun.n_ptr,(macro?Macprop: (fexpr?Fexprop:Exprop)));
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 * 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 * 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 = xlmatch(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 * frepeat - builtin function repeat *
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 arg.n_ptr = farg.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 * 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
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
Xstatic struct node *comment() { return t; }
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 t = xlenter("t");
X Lambda = xlenter("lambda");
X Fexpr = xlenter("fexpr");
X Macro = xlenter("macro");
X Subrprop = xlenter("SUBR");
X Fsubrprop = xlenter("FSUBR");
X Exprop = xlenter("EXPR");
X Fexprop = xlenter("FEXPR");
X Macprop = xlenter("MACRO");
X
X /* enter the builtin functions */
X xlsubr("set",set);
X xlfsubr("setq",setq);
X xlsubr("load",load);
X xlsubr("read",read);
X xlfsubr("comment",comment);
X xlfsubr("quote",quote);
X xlfsubr("while",fwhile);
X xlfsubr("repeat",frepeat);
X xlfsubr("foreach",foreach);
X xlfsubr("defun",defun);
X xlfsubr("if",fif);
X xlfsubr("exit",fexit);
X}
!Funky!Stuff!
exit 0
--
John Woods, Charles River Data Systems, Framingham MA, (617) 626-1114
...!decvax!frog!john, ...!mit-eddie!jfw, JFW at MIT-XX.ARPA
I have absolutely nothing clever to say in this signature.
More information about the Comp.sources.unix
mailing list