john@x.UUCP (John Woods) (08/27/84)
This represents part 4 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 xllist.c sed -n -e 's/^X//p' > xllist.c << '!Funky!Stuff!' X /* xllist - xlisp list 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; Xextern struct node *xlapply(); X X /* local variables */ Xstatic struct node *t; Xstatic struct node *a_subr; Xstatic struct node *a_fsubr; Xstatic struct node *a_list; Xstatic struct node *a_sym; Xstatic struct node *a_int; Xstatic struct node *a_real; Xstatic struct node *a_str; Xstatic struct node *a_obj; Xstatic struct node *a_fptr; Xstatic struct node *a_kmap; Xstatic struct node *NCONC; X X /********************************** X * xlist - builtin function list * X **********************************/ X Xstatic struct node *xlist(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 = xlarg(&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 /********************************* X * cond - builtin function cond * X *********************************/ X Xstatic struct node *cond(args) X struct node *args; X{ X struct node *oldstk,arg,list,*val; X X oldstk = xlsave(&arg,&list,NULL); X arg.n_ptr = args; X X val = NULL; X while (arg.n_ptr != NULL) X { X list.n_ptr = xlmatch(LIST,&arg.n_ptr); X if ((val = xlevarg(&list.n_ptr)) != NULL) X { X while (list.n_ptr != NULL) X val = xlevarg(&list.n_ptr); X break; X } X } X X xlstack = oldstk; X return (val); X} X X X /**************************** X * atom - is this an atom? * X ****************************/ X Xstatic struct node *atom(args) X struct node *args; X{ X struct node *arg; X X if ((arg = xlarg(&args)) == NULL || arg->n_type != LIST) X return (t); X else X return (NULL); X} X X X /************************* X * null - is this null? * X *************************/ X Xstatic struct node *null(args) X struct node *args; X{ X if (xlarg(&args) == NULL) X return (t); X else X return (NULL); X} X X /********************************* X * numberp - is this a number? * X ********************************/ X Xstatic struct node *numberp(args) X struct node *args; X{ X struct node *arg; X X if (!(arg = xlarg(&args))) X return NULL; X if (arg->n_type == INT || arg->n_type == REAL) X return (t); X return NULL; X} X X X /********************************** X * type - return type of a thing * X **********************************/ X Xstatic struct node *type(args) X struct node *args; X{ X struct node *arg; X X if (!(arg = xlarg(&args))) X return (NULL); X X switch (arg->n_type) X { X case SUBR: return (a_subr); X case FSUBR: return (a_fsubr); X X case LIST: return (a_list); X X case SYM: return (a_sym); X X case INT: return (a_int); X#ifdef REALS X case REAL: return (a_real); X#endif X case STR: return (a_str); X X case OBJ: return (a_obj); X X case FPTR: return (a_fptr); X X case KMAP: return (a_kmap); X X default: xlfail("Bad node."); X X } X} X X X /**************************** X * listp - is this a list? * X ****************************/ X Xstatic struct node *listp(args) X struct node *args; X{ X if (xlistp(xlarg(&args))) X return (t); X else X return (NULL); X} X X X /************************************* X * xlistp - internal listp function * X *************************************/ X Xstatic int xlistp(arg) X struct node *arg; X{ X return (arg == NULL || arg->n_type == LIST); X} X X X /************************** X * eq - are these equal? * X **************************/ X Xstatic struct node *eq(args) X struct node *args; X{ X struct node *oldstk,arg,arg1,arg2,*val; X X oldstk = xlsave(&arg,&arg1,&arg2,NULL); X arg.n_ptr = args; X X arg1.n_ptr = xlarg(&arg.n_ptr); X arg2.n_ptr = xlarg(&arg.n_ptr); X xllastarg(arg.n_ptr); X X if (xeq(arg1.n_ptr,arg2.n_ptr)) X val = t; X else X val = NULL; X X xlstack = oldstk; X return (val); X} X X X /******************************* X * xeq - internal eq function * X *******************************/ X Xint xeq(arg1,arg2) X struct node *arg1,*arg2; X{ X if (arg1 != NULL && arg1->n_type == INT && X arg2 != NULL && arg2->n_type == INT) X return (arg1->n_int == arg2->n_int); X else X return (arg1 == arg2); X} X X X /***************************** X * equal - are these equal? * X *****************************/ X Xstatic struct node *equal(args) X struct node *args; X{ X struct node *oldstk,arg,arg1,arg2,*val; X X oldstk = xlsave(&arg,&arg1,&arg2,NULL); X arg.n_ptr = args; X X arg1.n_ptr = xlarg(&arg.n_ptr); X arg2.n_ptr = xlarg(&arg.n_ptr); X xllastarg(arg.n_ptr); X X if (xequal(arg1.n_ptr,arg2.n_ptr)) X val = t; X else X val = NULL; X X xlstack = oldstk; X return (val); X} X X X /************************************* X * xequal - internal equal function * X *************************************/ X Xint xequal(arg1,arg2) X struct node *arg1,*arg2; X{ X if (xeq(arg1,arg2)) X return (TRUE); X else X if (xlistp(arg1) && xlistp(arg2)) X return (xequal(arg1->n_listvalue,arg2->n_listvalue) && X xequal(arg1->n_listnext, arg2->n_listnext)); X else X return (FALSE); X} X X /************************************* X * rplaca - damage the car of a cons * X *************************************/ Xstatic struct node *rplaca(args) X struct node *args; X{ X struct node *list, *with; X X if ((list = xlmatch(LIST,&args)) == NULL) X xlfail("null list"); X with = xlarg(&args); X xllastarg(args); X list->n_listvalue = with; X return list; X} X X /************************************* X * rplacd - damage the cdr of a cons * X *************************************/ Xstatic struct node *rplacd(args) X struct node *args; X{ X struct node *list, *with; X X if ((list = xlmatch(LIST,&args)) == NULL) X xlfail("null list"); X with = xlarg(&args); X xllastarg(args); X list->n_listnext = with; X return list; X} X X /************************************* X * head - return the head of a list * X *************************************/ X Xstatic struct node *head(args) X struct node *args; X{ X struct node *list; X X if ((list = xlmatch(LIST,&args)) == NULL) X/* xlfail("null list"); */ X return NULL; /* (car ()) => () */ X X xllastarg(args); X X return (list->n_listvalue); X} X X X /************************************* X * tail - return the tail of a list * X *************************************/ X Xstatic struct node *tail(args) X struct node *args; X{ X struct node *list; X X if ((list = xlmatch(LIST,&args)) == NULL) X/* xlfail("null list"); */ X return NULL; /* (cdr () ) => () */ X X xllastarg(args); X X return (list->n_listnext); X} X X /************************************* X * caar - return the caar of a list * X *************************************/ X Xstatic struct node *caar(args) X struct node *args; X{ X struct node *list; X X if ((list = xlmatch(LIST,&args)) == NULL) X return NULL; X xllastarg(args); X if (list->n_listvalue->n_type != LIST) X xlfail("car of non-list"); X return (list->n_listvalue->n_listvalue); X} X X X /************************************* X * cadr - return the cadr of a list * X *************************************/ X Xstatic struct node *cadr(args) X struct node *args; X{ X struct node *list; X X if ((list = xlmatch(LIST,&args)) == NULL) X return NULL; X xllastarg(args); X X if (list->n_listnext->n_type != LIST) X xlfail("car of non-list"); X return (list->n_listnext->n_listvalue); X} X X /************************************* X * cdar - return the cdar of a list * X *************************************/ X Xstatic struct node *cdar(args) X struct node *args; X{ X struct node *list; X X if ((list = xlmatch(LIST,&args)) == NULL) X return NULL; X xllastarg(args); X X if (list->n_listvalue->n_type != LIST) X xlfail("cdr of non-list"); X return (list->n_listvalue->n_listnext); X} X X /************************************* X * cddr - return the cddr of a list * X *************************************/ X Xstatic struct node *cddr(args) X struct node *args; X{ X struct node *list; X X if ((list = xlmatch(LIST,&args)) == NULL) X return NULL; X xllastarg(args); X X if (list->n_listnext->n_type != LIST) X xlfail("cdr of non-list"); X return (list->n_listnext->n_listnext); X} X X X /******************************************* X * nth - return the nth element of a list * X *******************************************/ X Xstatic struct node *nth(args) X struct node *args; X{ X struct node *oldstk,arg,list; X int n; X X oldstk = xlsave(&arg,&list,NULL); X arg.n_ptr = args; X X if ((n = xlmatch(INT,&arg.n_ptr)->n_int) < 1) X xlfail("invalid argument"); X X if ((list.n_ptr = xlmatch(LIST,&arg.n_ptr)) == NULL) X xlfail("invalid argument"); X X xllastarg(arg.n_ptr); X X for (; n > 1; n--) X { X list.n_ptr = list.n_ptr->n_listnext; X if (list.n_ptr == NULL || list.n_ptr->n_type != LIST) X xlfail("invalid argument"); X } X X xlstack = oldstk; X return (list.n_ptr->n_listvalue); X} X X /********************************************* X * last - return the last element of a list * X *********************************************/ X Xstatic struct node *last(args) X struct node *args; X{ X struct node *oldstk,arg,list; X X oldstk = xlsave(&arg,&list,NULL); X arg.n_ptr = args; X X if ((list.n_ptr = xlmatch(LIST,&arg.n_ptr)) == NULL) X xlfail("invalid argument"); X xllastarg(arg.n_ptr); X X for (; list.n_ptr->n_listnext; ) X { X list.n_ptr = list.n_ptr->n_listnext; X if (list.n_ptr == NULL || list.n_ptr->n_type != LIST) X xlfail("invalid argument"); X } X X xlstack = oldstk; X return (list.n_ptr->n_listvalue); X} X X /********************************************** X * memq - is a thing eq to a member of a list * X ***********************************************/ X Xstatic struct node *memq(args) X struct node *args; X{ X struct node *oldstk,list,*val = NULL,thing; X X oldstk = xlsave(&list,&thing,NULL); X X thing.n_ptr = xlarg(&args); X list.n_ptr = xlmatch(LIST,&args); X xllastarg(args); X X for (; list.n_ptr != NULL; list.n_ptr = list.n_ptr->n_listnext) X { if (xeq(list.n_ptr->n_listvalue,thing.n_ptr)) X { val = t; X break; X } X if (!xlistp(list.n_ptr->n_listnext)) X break; X } X xlstack = oldstk; X return (val); X} X X /******************************************* X * member - is a thing a member of a list * X ********************************************/ X Xstatic struct node *member(args) X struct node *args; X{ X struct node *oldstk,list,*val = NULL,thing; X X oldstk = xlsave(&list,&thing,NULL); X X thing.n_ptr = xlarg(&args); X list.n_ptr = xlmatch(LIST,&args); X xllastarg(args); X X for (; list.n_ptr != NULL; list.n_ptr = list.n_ptr->n_listnext) X if (xequal(list.n_ptr->n_listvalue,thing.n_ptr)) X { val = t; X break; X } X else if (!xlistp(list.n_ptr->n_listnext)) X break; X X xlstack = oldstk; X return (val); X} X X /************************************************ X * subst - subst one sexp for another in a list * X *************************************************/ X Xstatic struct node *subst(args) X struct node *args; X{ X struct node *oldstk,list,*val = NULL,ptr,from,to; X X oldstk = xlsave(&list,&from,&to,&ptr,NULL); X X to.n_ptr = xlarg(&args); X from.n_ptr = xlarg(&args); X list.n_ptr = xlmatch(LIST,&args); X xllastarg(args); X X for (; list.n_ptr != NULL; list.n_ptr = list.n_ptr->n_listnext) X { X if (val == NULL) val = ptr.n_ptr = newnode(LIST); X else { X ptr.n_ptr->n_listnext = newnode(LIST); X ptr.n_ptr = ptr.n_ptr->n_listnext; X ptr.n_ptr->n_listnext = NULL; X } X if (xequal(list.n_ptr->n_listvalue,from.n_ptr)) X ptr.n_ptr->n_listvalue = to.n_ptr; X else X ptr.n_ptr->n_listvalue = list.n_ptr->n_listvalue; X } X xlstack = oldstk; X return (val); X} X X /************************************************ X * efface - splice an s-expression from a list * X *************************************************/ X Xstatic struct node *efface(args, fun) X struct node *args; X int (*fun)(); X{ X struct node *oldstk,*list,*val = NULL,*kill, *last = NULL; X X kill = xlarg(&args); X val = list = xlmatch(LIST,&args); X xllastarg(args); X X for (; list != NULL; list = list->n_listnext) X { X if ((*fun)(list->n_listvalue,kill)) { X if (last == NULL) { X /* delete from top of list */ X val = val->n_listnext; X continue; X } X last->n_listnext = list->n_listnext; X continue; X } X last = list; X } X xlstack = oldstk; X return (val); X} X X /****************************************************** X * delete - delete an s-expression (equal) from a list * X *******************************************************/ X Xstatic struct node *delete(args) X struct node *args; X{ X return efface(args,xequal); X} X X /************************************************* X * delq - delete an s-expression (eq) from a list * X **************************************************/ X Xstatic struct node *delq(args) X struct node *args; X{ X return efface(args,xeq); X} X X /***************************************** X * length - return the length of a list * X *****************************************/ X Xstatic struct node *length(args) X struct node *args; X{ X struct node *list,*val; X int n; X X list = xlmatch(LIST,&args); X xllastarg(args); X X for (n = 0; list != NULL; n++) X list = list->n_listnext; X X val = newnode(INT); X val->n_int = n; X return (val); X} X X X /*********************************** X * nconc - builtin function nconc * X ***********************************/ X Xstatic struct node *nconc(args) X struct node *args; X{ X struct node *oldstk,arg,*list,**last = NULL,val; X X oldstk = xlsave(&arg,&val,NULL); X arg.n_ptr = args; X X while (arg.n_ptr != NULL) X { X list = xlmatch(LIST,&arg.n_ptr); X if (!val.n_ptr) X val.n_ptr = list; X else X *last = list; /* hook this list onto last one */ X X while (list != NULL && list->n_type == LIST) X { X if (list->n_listnext == NULL) X last = &list->n_listnext; X list = list->n_listnext; X } X X if (list != NULL) X xlfail("bad list"); X } X X xlstack = oldstk; X return (val.n_ptr); X} X X /************************************* X * append - builtin function append * X *************************************/ X Xstatic struct node *append(args) X struct node *args; X{ X struct node *oldstk,arg,list,last,val,*lptr; X X oldstk = xlsave(&arg,&list,&last,&val,NULL); X arg.n_ptr = args; X X while (arg.n_ptr != NULL) X { X list.n_ptr = xlmatch(LIST,&arg.n_ptr); X while (list.n_ptr != NULL && list.n_ptr->n_type == LIST) X { X lptr = newnode(LIST); X if (last.n_ptr == NULL) X val.n_ptr = lptr; X else X last.n_ptr->n_listnext = lptr; X lptr->n_listvalue = list.n_ptr->n_listvalue; X last.n_ptr = lptr; X list.n_ptr = list.n_ptr->n_listnext; X } X X if (list.n_ptr != NULL) X xlfail("bad list"); X } X X xlstack = oldstk; X return (val.n_ptr); X} X X /*************************************** X * reverse - builtin function reverse * X ***************************************/ X Xstatic struct node *reverse(args) X struct node *args; X{ X struct node *oldstk,list,val,*lptr; X X oldstk = xlsave(&list,&val,NULL); X X list.n_ptr = xlmatch(LIST,&args); X xllastarg(args); X X while (list.n_ptr != NULL && list.n_ptr->n_type == LIST) X { X lptr = newnode(LIST); X lptr->n_listvalue = list.n_ptr->n_listvalue; X lptr->n_listnext = val.n_ptr; X val.n_ptr = lptr; X X list.n_ptr = list.n_ptr->n_listnext; X } X X if (list.n_ptr != NULL) X xlfail("bad list"); X X xlstack = oldstk; X return (val.n_ptr); X} X X X /************************************* X * cons - construct a new list cell * X *************************************/ X Xstatic struct node *cons(args) X struct node *args; X{ X struct node *oldstk,arg,arg1,arg2,*lptr; X X oldstk = xlsave(&arg,&arg1,&arg2,NULL); X arg.n_ptr = args; X X arg1.n_ptr = xlarg(&arg.n_ptr); X arg2.n_ptr = xlarg(&arg.n_ptr); X xllastarg(arg.n_ptr); X X lptr = newnode(LIST); X lptr->n_listvalue = arg1.n_ptr; X lptr->n_listnext = arg2.n_ptr; X X xlstack = oldstk; X return (lptr); X} X X /************************************* X * mapcar - builtin function mapcar * X *************************************/ X Xstatic struct node *mapcar(args) X struct node *args; X{ X struct node *oldstk,fun,arglist,list,val,thisarg, X *argtop,*arg,*last,*lptr, *buildptr, *buildlast; X oldstk = xlsave(&fun,&arglist,&thisarg,&list,&val,NULL); X X fun.n_ptr = xlarg(&args); X X arglist.n_ptr = xlist(args); /* copy arglist */ X X for (last = NULL; arglist.n_ptr->n_listvalue != NULL; last = lptr) X { X /* build list of args for this pass */ X for (buildlast = NULL, buildptr = arglist.n_ptr; buildptr != NULL; X buildptr = buildptr->n_listnext) X { X /* get a cell */ X if (buildlast == NULL) X buildlast = thisarg.n_ptr = newnode(LIST); X else { X buildlast->n_listnext = newnode(LIST); X buildlast = buildlast->n_listnext; X } X /* from the list now pointed to by buildptr, pop the top X item from that sublist */ X buildlast->n_listvalue = xlarg(&buildptr->n_listvalue); X } X val.n_ptr = xlapply(fun.n_ptr,thisarg.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 thisarg.n_ptr = NULL; /* ensure storage is reclaimed */ X } X X xlstack = oldstk; X return (list.n_ptr); X} X Xstatic struct node *mapcan(args) struct node *args; X{ X struct node *oldstk, list, *val; X oldstk = xlsave(&list,NULL); X list.n_ptr = mapcar(args); X val = xlapply(NCONC,list.n_ptr); X xlstack = oldstk; X return val; X} X X /************************************************ X * xllinit - xlisp list initialization routine * X ************************************************/ X Xxllinit() X{ X /* define some symbols */ X t = xlenter("t"); X a_fsubr = xlenter("FSUBR"); X a_subr = xlenter("SUBR"); X a_list = xlenter("LIST"); X a_sym = xlenter("SYM"); X a_int = xlenter("INT"); X a_real = xlenter("REAL"); X a_str = xlenter("STR"); X a_obj = xlenter("OBJ"); X a_fptr = xlenter("FPTR"); X a_kmap = xlenter("KMAP"); X X /* functions with reasonable names */ X xlsubr("head",head); X xlsubr("tail",tail); X xlsubr("nth",nth); X X /* real lisp functions */ X xlsubr("atom",atom); X xlsubr("eq",eq); X xlsubr("equal",equal); X xlsubr("null",null); X xlsubr("type",type); X xlsubr("listp",listp); X xlsubr("numberp",numberp); X xlfsubr("cond",cond); X xlsubr("list",xlist); X xlsubr("cons",cons); X xlsubr("car",head); X xlsubr("cdr",tail); X xlsubr("caar",caar); X xlsubr("cadr",cadr); X xlsubr("cdar",cdar); X xlsubr("cddr",cddr); X xlsubr("rplaca",rplaca); X xlsubr("rplacd",rplacd); X xlsubr("member",member); X xlsubr("memq",memq); X xlsubr("subst",subst); X xlsubr("append",append); X xlsubr("nconc",nconc); X NCONC = xlget(xlenter("nconc"),a_subr); X xlsubr("reverse",reverse); X xlsubr("length",length); X xlsubr("last",last); X xlsubr("mapcar",mapcar); X xlsubr("mapcan",mapcan); X xlsubr("delete",delete); X xlsubr("delq",delq); X} !Funky!Stuff! echo x xlobj.c sed -n -e 's/^X//p' > xlobj.c << '!Funky!Stuff!' X /* xlobj - xlisp object functions */ 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 "xlisp.h" X#endif X X X#ifdef unix X#include <stdio.h> X#include "xlisp.h" X#endif X X X /* global variables */ X Xstruct node *self; X X X /* external variables */ X Xextern struct node *xlstack; Xextern struct node *xlenv; Xextern int (*xlofun)(); X X /* local variables */ X Xstatic struct node *class; Xstatic struct node *object; Xstatic struct node *new; Xstatic struct node *isnew; Xstatic struct node *msgcls; Xstatic struct node *msgclass; Xstatic struct node *lambda; Xstatic int varcnt; X X /* instance variable numbers for the class 'Class' */ X X#define MESSAGES 0 /* list of messages */ X#define IVARS 1 /* list of instance variable names */ X#define CVARS 2 /* list of class variable names */ X#define CVALS 3 /* list of class variable values */ X#define SUPERCLASS 4 /* pointer to the superclass */ X#define IVARCNT 5 /* number of class instance variables */ X#define IVARTOTAL 6 /* total number of instance variables */ X X X /* number of instance variables for the class 'Class' */ X X#define CLASSSIZE 7 X X X#ifdef HACK X /* forward declarations (the extern hack is because of decusc) */ X Xextern struct node *findmsg(); Xextern struct node *findvar(); Xextern struct node *defvars(); Xextern struct node *makelist(); X#endif X X /***************************** X * xlclass - define a class * X *****************************/ X Xstruct node *xlclass(name,vcnt) X char *name; int vcnt; X{ X struct node *sym,*cls; X X sym = xlenter(name); /* Create the class */ X cls = sym->n_symvalue = newnode(OBJ); X cls->n_obclass = class; X cls->n_obdata = makelist(CLASSSIZE); X X if (vcnt > 0) /* Set instance var count */ X { X (xlivar(cls,IVARCNT)->n_listvalue = newnode(INT))->n_int = vcnt; X (xlivar(cls,IVARTOTAL)->n_listvalue = newnode(INT))->n_int = vcnt; X } X X xlivar(cls,SUPERCLASS)->n_listvalue = object; /* superclass = object */ X X return (cls); X} X X X /****************************************************************** X * xlmfind - find the message binding for a message to an object * X ******************************************************************/ X Xstruct node *xlmfind(obj,msym) X struct node *obj,*msym; X{ X return (findmsg(obj->n_obclass,msym)); X} X X X /****************************************** X * xlxsend - send a message to an object * X ******************************************/ X Xstruct node *xlxsend(obj,msg,args) X struct node *obj,*msg,*args; X{ X struct node *oldstk,method,cptr,val,*isnewmsg,*oldenv; X X oldenv = xlenv; /* Save old environment */ X oldstk = xlsave(&method,&cptr,&val,NULL); X X method.n_ptr = msg->n_msgcode; /* Get method for this msg */ X if (method.n_ptr->n_type != FSUBR && method.n_ptr->n_type != SUBR X && method.n_ptr->n_type != LIST) X xlfail("bad method"); X X xlbind(self,obj); /* Bind 'self' and 'msgclass' */ X xlbind(msgclass,msgcls); X X if (method.n_ptr->n_type == FSUBR) /* Evaluate function */ X { X xlfixbindings(oldenv); /* make above bindings visible */ X val.n_ptr = (*method.n_ptr->n_subr)(args); X } X else if (method.n_ptr->n_type == SUBR) X { X cptr.n_ptr = xlevlis(args); /* evaluate args in old env */ X xlfixbindings(oldenv); /* make above bindings visible */ X val.n_ptr = (*method.n_ptr->n_subr)( cptr.n_ptr ); X } X else X { /* cons up a lambda to apply */ Xprintf("XLEVLIS[ "); xlprint(args,TRUE); printf(" ]\n"); X val.n_ptr = xlevlis(args); /* evaluate args in old env */ X xlfixbindings(oldenv); /* now make above bindings visible */ X cptr.n_ptr = newnode(LIST); X cptr.n_ptr->n_listvalue = lambda; X cptr.n_ptr->n_listnext = method.n_ptr; X val.n_ptr = xlapply(cptr.n_ptr,val.n_ptr); X } X xlunbind(oldenv); /* Restore environment */ X X /* after creating an object, send it the "isnew" message */ X if (msg->n_msg == new && val.n_ptr != NULL) X { X if ((isnewmsg = xlmfind(val.n_ptr,isnew)) == NULL) X xlfail("no method for the isnew message"); X val.n_ptr = xlxsend(val.n_ptr,isnewmsg,args); X } X X xlstack = oldstk; /* Restore old stack frame */ X return (val.n_ptr); X} X X X /*************************************************************** X * xlsend - send a message to an object (message in arg list) * X ***************************************************************/ X Xstruct node *xlsend(obj,args) X struct node *obj,*args; X{ X struct node *msg; X X if ((msg = xlmfind(obj,xlevmatch(SYM,&args))) == NULL) X xlfail("no method for this message"); X X return (xlxsend(obj,msg,args)); X} X X X /*********************************************************************** X * xlobsym - find a class or instance variable for the current object * X ***********************************************************************/ X Xstruct node *xlobsym(sym) X struct node *sym; X{ X struct node *obj; X X if ((obj = self->n_symvalue) != NULL && obj->n_type == OBJ) X return (findvar(obj,sym)); X else X return (NULL); X} X X /**************************************** X * mnew - create a new object instance * X ****************************************/ X Xstatic struct node *mnew() X{ X struct node *oldstk,obj,*cls; X X oldstk = xlsave(&obj,NULL); /* New stack frame */ X X cls = self->n_symvalue; /* Get class name */ X X obj.n_ptr = newnode(OBJ); /* Generate new object */ X obj.n_ptr->n_obclass = cls; X obj.n_ptr->n_obdata = makelist(getivcnt(cls,IVARTOTAL)); X X xlstack = oldstk; /* Restore old stack frame */ X return (obj.n_ptr); X} X X X /************************************ X * misnew - initialize a new class * X ************************************/ X Xstatic struct node *misnew(args) X struct node *args; X{ X struct node *oldstk,super,*obj; X X oldstk = xlsave(&super,NULL); /* Create new stack frame */ X X if (args != NULL) /* Get superclass is present */ X super.n_ptr = xlevmatch(OBJ,&args); X else X super.n_ptr = object; X X xllastarg(args); /* Check no more args */ X X obj = self->n_symvalue; /* Get the object */ X xlivar(obj,SUPERCLASS)->n_listvalue = super.n_ptr; X (xlivar(obj,IVARTOTAL)->n_listvalue = newnode(INT))->n_int = X getivcnt(super.n_ptr,IVARTOTAL); X X xlstack = oldstk; /* Restore stack frame */ X return (obj); X} X X X /******************************************* X * xladdivar - enter an instance variable * X *******************************************/ X Xxladdivar(cls,var) X struct node *cls; char *var; X{ X struct node *ivar,*lptr; X X ivar = xlivar(cls,IVARS); /* Find 'ivars' instance var */ X X lptr = newnode(LIST); /* add instance var */ X lptr->n_listnext = ivar->n_listvalue; X ivar->n_listvalue = lptr; X lptr->n_listvalue = xlenter(var); X} X X X /**************************************** X * entermsg - add a message to a class * X ****************************************/ X Xstatic struct node *entermsg(cls,msg) X struct node *cls,*msg; X{ X struct node *ivar,*lptr,*mptr; X X ivar = xlivar(cls,MESSAGES); /* Find 'messages' iv */ X X for (lptr = ivar->n_listvalue; lptr != NULL; lptr = lptr->n_listnext) X if ((mptr = lptr->n_listvalue)->n_msg == msg) X return (mptr); X X /* allocate a new message entry if one wasn't found */ X lptr = newnode(LIST); X lptr->n_listnext = ivar->n_listvalue; X ivar->n_listvalue = lptr; X lptr->n_listvalue = mptr = newnode(LIST); X mptr->n_msg = msg; X X return (mptr); /* Return the symbol node */ X} X X X /***************************************************** X * answer - define a method for answering a message * X *****************************************************/ X Xstatic struct node *answer(args) X struct node *args; X{ X struct node *oldstk,arg,msg,fargs,code; X struct node *obj,*mptr,*fptr; X X oldstk = xlsave(&arg,&msg,&fargs,&code,NULL); /* New stack frame */ X arg.n_ptr = args; X X msg.n_ptr = xlevmatch(SYM,&arg.n_ptr); /* Message symbol */ X X fargs.n_ptr = xlevmatch(LIST,&arg.n_ptr); /* Formal arg list */ X code.n_ptr = xlevmatch(LIST,&arg.n_ptr); /* the code */ X xllastarg(arg.n_ptr); /* End of args */ X X obj = self->n_symvalue; /* Object node */ X mptr = entermsg(obj,msg.n_ptr); /* New message list entry */ X X mptr->n_msgcode = fptr = newnode(LIST); /* Set up message node */ X fptr->n_listvalue = fargs.n_ptr; X fptr->n_listnext = code.n_ptr; X X xlstack = oldstk; /* Restore old stack frame */ X return (obj); X} X X X /*************************************************** X * mivars - define the list of instance variables * X ***************************************************/ X Xstatic struct node *mivars(args) X struct node *args; X{ X struct node *cls,*super; X int scnt; X X cls = defvars(args,IVARS); /* Define list of ivs */ X X if ((super = xlivar(cls,SUPERCLASS)->n_listvalue) != NULL) X scnt = getivcnt(super,IVARTOTAL); X else X scnt = 0; X X (xlivar(cls,IVARCNT)->n_listvalue = newnode(INT))->n_int = varcnt; X (xlivar(cls,IVARTOTAL)->n_listvalue = newnode(INT))->n_int = scnt+varcnt; X X return (cls); X} X X X X /**************************************************************** X * getivcnt - get the number of instance variables for a class * X ****************************************************************/ X Xstatic int getivcnt(cls,ivar) X struct node *cls; int ivar; X{ X struct node *cnt; X X if ((cnt = xlivar(cls,ivar)->n_listvalue) != NULL) X if (cnt->n_type == INT) X return (cnt->n_int); X else X xlfail("bad value for instance variable count"); X else X return (0); X} X X X X /************************************************ X * mcvars - define the list of class variables * X ************************************************/ X Xstatic struct node *mcvars(args) X struct node *args; X{ X struct node *cls; X X cls = defvars(args,CVARS); /* define list of class vars */ X xlivar(cls,CVALS)->n_listvalue = makelist(varcnt); /* make new list */ X X return (cls); X} X X X X /******************************************************* X * defvars - define a class or instance variable list * X *******************************************************/ X Xstatic struct node *defvars(args,varnum) X struct node *args; int varnum; X{ X struct node *oldstk,vars,*vptr,*cls,*sym; X X oldstk = xlsave(&vars,NULL); /* Create new stack frame */ X vars.n_ptr = xlevmatch(LIST,&args); /* Get ivar list */ X xllastarg(args); /* Last argument ! */ X X cls = self->n_symvalue; /* Class node */ X X varcnt = 0; /* Check each var in list */ X for (vptr = vars.n_ptr; X vptr != NULL && vptr->n_type == LIST; X vptr = vptr->n_listnext) X { X /* make sure this is a valid symbol in the list */ X if ((sym = vptr->n_listvalue) == NULL || sym->n_type != SYM) X xlfail("bad variable list"); X X if (checkvar(cls,sym)) /* Check not already defined */ X xlfail("multiply defined variable"); X varcnt++; /* Count the variable */ X } X X if (vptr != NULL) /* Check for correct end */ X xlfail("bad variable list"); X X xlivar(cls,varnum)->n_listvalue = vars.n_ptr; /* Define new list */ X X xlstack = oldstk; /* Restore old stack frame */ X return (cls); X} X X X X /**************************************** X * xladdmsg - add a message to a class * X ****************************************/ X Xxladdmsg(cls,msg,code) X struct node *cls; char *msg; struct node *(*code)(); X{ X struct node *mptr; X X mptr = entermsg(cls,xlenter(msg)); /* enter message selector */ X mptr->n_msgcode = newnode(FSUBR); /* Store the method */ X mptr->n_msgcode->n_subr = code; X} X X X X /****************************************** X * getclass - get the class of an object * X ******************************************/ X Xstatic struct node *getclass(args) X struct node *args; X{ X xllastarg(args); /* Check no arguments */ X return (self->n_symvalue->n_obclass); X} X X X X /****************************** X * obprint - print an object * X ******************************/ X Xstatic struct node *obprint(args) X struct node *args; X{ X char buf[20]; X xllastarg(args); /* Check no arguments */ X X sprintf(buf,"<Object: #%o>",self->n_symvalue); X (*xlofun)(buf); X return (self->n_symvalue); X} X X X X /****************************************************** X * obshow - show the instance variables of an object * X ******************************************************/ X Xstatic struct node *obshow(args) X struct node *args; X{ X xllastarg(args); /* Check no arguments */ X X xlprint(self->n_symvalue->n_obdata,TRUE); X return (self->n_symvalue); X} X X X X /************************************** X * defisnew - default 'isnew' method * X **************************************/ X Xstatic struct node *defisnew(args) X struct node *args; X{ X xllastarg(args); /* Check for null arg list */ X return (self->n_symvalue); X} X X X X /********************************************************* X * sendsuper - send a message to an object's superclass * X *********************************************************/ X Xstatic struct node *sendsuper(args) X struct node *args; X{ X struct node *obj,*super,*msg; X X obj = self->n_symvalue; /* Get the object and its super class */ X super = xlivar(obj->n_obclass,SUPERCLASS)->n_listvalue; X X /* Find message binding */ X if ((msg = findmsg(super,xlevmatch(SYM,&args))) == NULL) X xlfail("no method for this message"); X X return (xlxsend(obj,msg,args)); /* and send it */ X} X X X /******************************************************************* X * findmsg - find the message binding given an object and a class * X *******************************************************************/ X Xstatic struct node *findmsg(cls,sym) X struct node *cls,*sym; X{ X struct node *lptr,*msg; X X msgcls = cls; /* Start at specified class */ X while (msgcls != NULL) /* Look for the message */ X { X for (lptr = xlivar(msgcls,MESSAGES)->n_listvalue; X lptr != NULL; X lptr = lptr->n_listnext) X if ((msg = lptr->n_listvalue) != NULL && msg->n_msg == sym) X return (msg); X X msgcls = xlivar(msgcls,SUPERCLASS)->n_listvalue; X } X X return (NULL); /* Message not found */ X} X X X /************************************************ X * findvar - find a class or instance variable * X ************************************************/ X Xstatic struct node *findvar(obj,sym) X struct node *obj,*sym; X{ X struct node *cls,*lptr; X int base,varnum; X int found; X X cls = obj->n_obclass; /* Get class of object */ X base = getivcnt(cls,IVARTOTAL); /* Get number of ivs */ X found = FALSE; /* Find the var */ X for (; cls != NULL; cls = xlivar(cls,SUPERCLASS)->n_listvalue) X { X if ((base -= getivcnt(cls,IVARCNT)) < 0) X xlfail("error finding instance variable"); X X if (!found && cls == msgclass->n_symvalue) X found = TRUE; X X varnum = 0; /* Lookup the iv */ X for (lptr = xlivar(cls,IVARS)->n_listvalue; X lptr != NULL; X lptr = lptr->n_listnext) { X if (found && lptr->n_listvalue == sym) X return (xlivar(obj,base + varnum)); X else X varnum++; X } X X if (!found) /* Skip class vars if found */ X continue; X X varnum = 0; /* Lookup class vars */ X for (lptr = xlivar(cls,CVARS)->n_listvalue; X lptr != NULL; X lptr = lptr->n_listnext) X if (lptr->n_listvalue == sym) X return (xlcvar(cls,varnum)); X else X varnum++; X } X X return (NULL); /* Var not found */ X} X X X /**************************************************************** X * checkvar - check for an existing class or instance variable * X ****************************************************************/ X Xstatic int checkvar(cls,sym) X struct node *cls,*sym; X{ X struct node *lptr; X X for (; cls != NULL; cls = xlivar(cls,SUPERCLASS)->n_listvalue) X { X for (lptr = xlivar(cls,IVARS)->n_listvalue; /* Lookup instance var */ X lptr != NULL; X lptr = lptr->n_listnext) X if (lptr->n_listvalue == sym) X return (TRUE); X X for (lptr = xlivar(cls,CVARS)->n_listvalue; /* Lookup class var */ X lptr != NULL; X lptr = lptr->n_listnext) X if (lptr->n_listvalue == sym) X return (TRUE); X } X X return (FALSE); /* Var not found */ X} X X X /************************************** X * xlivar - get an instance variable * X **************************************/ X Xstruct node *xlivar(obj,num) X struct node *obj; int num; X{ X struct node *ivar; X X for (ivar = obj->n_obdata; num > 0; num--) /* Get instance var */ X if (ivar != NULL) X ivar = ivar->n_listnext; X else X xlfail("bad instance variable list"); X X return (ivar); X} X X X /********************************** X * xlcvar - get a class variable * X **********************************/ X Xstruct node *xlcvar(cls,num) X struct node *cls; int num; X{ X struct node *cvar; X X for (cvar = xlivar(cls,CVALS)->n_listvalue; num > 0; num--) X if (cvar != NULL) X cvar = cvar->n_listnext; X else X xlfail("bad class variable list"); X X return (cvar); X} X X X X /************************************ X * makelist - make a list of nodes * X ************************************/ X Xstatic struct node *makelist(cnt) X int cnt; X{ X struct node *oldstk,list,*lnew; X X oldstk = xlsave(&list,NULL); /* Create a new stack frame */ X X for (; cnt > 0; cnt--) /* Make the list */ X { X lnew = newnode(LIST); X lnew->n_listnext = list.n_ptr; X list.n_ptr = lnew; X } X X xlstack = oldstk; /* Restore the old stack frame */ X return (list.n_ptr); X} X X X /***************************************************** X * xloinit - object function initialization routine * X *****************************************************/ X Xxloinit() X{ X class = NULL; /* Dont confuse gc */ X object = NULL; X X new = xlenter("new"); /* Enter object realtaed symbols */ X isnew = xlenter("isnew"); X self = xlenter("self"); X msgclass = xlenter("msgclass"); X lambda = xlenter("lambda"); X X class = xlclass("Class",CLASSSIZE); /* Create 'Class' object */ X class->n_obclass = class; X X object = xlclass("Object",0); /* Create 'Object class */ X X xlivar(class,SUPERCLASS)->n_listvalue = object; X xladdivar(class,"ivartotal"); /* ivar number 6 */ X xladdivar(class,"ivarcnt"); /* ivar number 5 */ X xladdivar(class,"superclass"); /* ivar number 4 */ X xladdivar(class,"cvals"); /* ivar number 3 */ X xladdivar(class,"cvars"); /* ivar number 2 */ X xladdivar(class,"ivars"); /* ivar number 1 */ X xladdivar(class,"messages"); /* ivar number 0 */ X xladdmsg(class,"new",mnew); X xladdmsg(class,"answer",answer); X xladdmsg(class,"ivars",mivars); X xladdmsg(class,"cvars",mcvars); X xladdmsg(class,"isnew",misnew); X X xladdmsg(object,"class",getclass); X xladdmsg(object,"print",obprint); X xladdmsg(object,"show",obshow); X xladdmsg(object,"isnew",defisnew); X xladdmsg(object,"sendsuper",sendsuper); X} !Funky!Stuff! echo x xlprin.c sed -n -e 's/^X//p' > xlprin.c << '!Funky!Stuff!' X X /* xlprint - xlisp print routine */ 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#include <ctype.h> X#endif X X X /* external variables */ X Xextern struct node *xlstack; Xextern FILE *ofp; Xextern xlfout(); X /* global variables */ Xextern int (*xlofun)() = xlstrout; /* current output function */ X X /* local variables */ Xstatic struct node *printsym; X X X /*********************************** X * print - builtin function print * X ***********************************/ X Xstatic struct node *print(args) X struct node *args; X{ struct node *r; X r = xprint(args,TRUE); X (*xlofun)("\n"); X return r; X} X Xstatic struct node *prin1(args) X struct node *args; X{ X return xprint(args,TRUE); X} X X /*********************************** X * princ - builtin function princ * X ***********************************/ X Xstatic struct node *princ(args) X struct node *args; X{ X return xprint(args,FALSE); X} X X X /*********************************** X * xprint - common print function * X ***********************************/ X Xxprint(args,flag) X struct node *args; int flag; X{ X struct node *oldstk,arg,val; X X oldstk = xlsave(&arg,&val,NULL); /* New stack frame */ X arg.n_ptr = args; X X while (arg.n_ptr != NULL) /* Evaluate an print each arg */ X xlprint(xlarg(&arg.n_ptr),flag); X xlstack = oldstk; /* Restore old stack frame */ X return (NULL); X} X X /***************************************************************** X * anyfunny - do any of the characters deserve to be |protected| * X *****************************************************************/ Xstatic anyfunny(s) char *s; X{ X if (isallnumeric(s)) return 1; /* see xlread.c */ X while (*s) { X if (isspace(*s)) return 1; X if (index("() .'\";\\",*s)) X return 1; X s++; X } X return 0; X} X /*********************************** X * xlprint - print an xlisp value * X ***********************************/ X Xxlprint(vptr,flag) X struct node *vptr; int flag; X{ X struct node *nptr,*next,*msg; X char obuf[512]; X#ifdef FGETNAME X char buffer[128]; X#endif X X if (vptr == NULL) /* Print NULL as the empty list */ X { X (*xlofun)("()"); X return; X } X X switch (vptr->n_type) /* Check value type */ X { X case FSUBR: X sprintf(obuf,"<FSUBR: #%o>",vptr); X (*xlofun)(obuf); X break; X X case SUBR: X sprintf(obuf,"<SUBR: #%o>",vptr); X (*xlofun)(obuf); X break; X X case LIST: X (*xlofun)("("); X for (nptr = vptr; nptr != NULL; nptr = next) X { X xlprint(nptr->n_listvalue,flag); X if ((next = nptr->n_listnext) != NULL) X if (next->n_type == LIST) X (*xlofun)(" "); X else X { X (*xlofun)(" . "); X xlprint(next,flag); X break; X } X } X (*xlofun)(")"); X break; X X case SYM: X if (flag && anyfunny(vptr->n_symname)) { X if (vptr->n_symname[1] == 0 || isallnumeric(vptr->n_symname)) X sprintf(obuf,"\\%s",vptr->n_symname); X else X sprintf(obuf,"|%s|",vptr->n_symname); X } X else X sprintf(obuf,"%s",vptr->n_symname); X (*xlofun)(obuf); X break; X X case INT: X sprintf(obuf,"%d",vptr->n_int); X (*xlofun)(obuf); X break; X X#ifdef REALS X case REAL: X sprintf(obuf,"%g",vptr->n_real); X (*xlofun)(obuf); X break; X#endif X X case STR: X if (flag) X putstring(vptr->n_str); X else { X sprintf(obuf,"%s",vptr->n_str); X (*xlofun)(obuf); X } X break; X X case FPTR: X X#ifdef FGETNAME X sprintf(obuf,"<File: %s>",fgetname(vptr->n_fp, buffer)); X#else X sprintf(obuf,"<File: #%o>",vptr); X#endif X (*xlofun)(obuf); X break; X X case OBJ: X if ((msg = xlmfind(vptr,printsym)) == NULL) X xlfail("no print message"); X xlxsend(vptr,msg,NULL); X break; X X case KMAP: X sprintf(obuf,"<Kmap: #%o>",vptr); X (*xlofun)(obuf); X break; X X default: X printf("Invalid node type %d", vptr->n_type); X break; X } X} X X X /******************************** X * putstring - output a string * X ********************************/ X Xstatic putstring(str) X char *str; X{ X int ch; X char obuf[6]; X X (*xlofun)("\""); X while (ch = *str++) X if (ch < 040 || ch == '\\') /* Check for control char */ X { X (*xlofun)("\\"); X switch (ch) X { X case '\033': X (*xlofun)("e"); X break; X X case '\n': X (*xlofun)("n"); X break; X X case '\r': X (*xlofun)("r"); X break; X X case '\t': X (*xlofun)("t"); X break; X X case '\\': X (*xlofun)("\\"); X break; X X default: X sprintf(obuf,"%03o",ch); X (*xlofun)(obuf); X break; X } X } X else /* Output a normal char */ X { obuf[0] = ch; obuf[1] = 0; X (*xlofun)(obuf); X } X X (*xlofun)("\""); X} X Xstatic struct node *terpri(args) struct node *args; { X xllastarg(args); X (*xlofun)("\n"); X return NULL; X} X X /********************************************** X * temporarily redirect the standard output * X **********************************************/ X Xstatic struct node *redirect(args) struct node *args; { X struct node *argp; X if (args == NULL) X xlfout(0); X else { X argp = xlmatch(STR,&args); X xllastarg(args); X xlfout(argp->n_str); X } X return NULL; X} X X /********************************* X * normal output routine * X ********************************/ Xxlstrout(s) char *s; X{ X fputs(s,ofp); X} X X /******************************************** X * xlpinit - initialize the print routines * X ********************************************/ X Xxlpinit() X{ X printsym = xlenter("print"); /* Find the print symbol */ X X xlsubr("prin1",prin1); X xlsubr("print",print); /* Enter the built in functions */ X xlsubr("princ",princ); X xlsubr("terpri",terpri); X xlsubr("redirect",redirect); X} 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.