BSD 4_3_Tahoe development
authorCSRG <csrg@ucbvax.Berkeley.EDU>
Sun, 24 Mar 1985 04:03:18 +0000 (20:03 -0800)
committerCSRG <csrg@ucbvax.Berkeley.EDU>
Sun, 24 Mar 1985 04:03:18 +0000 (20:03 -0800)
Work on file usr/tmp/housel/franz/eval2.c
Work on file usr/src/ucb/lisp/franz/eval2.c
Work on file usr/tmp/housel/franz/inits.c
Work on file usr/src/ucb/lisp/franz/inits.c

Synthesized-from: CSRG/cd2/4.3tahoe

usr/src/ucb/lisp/franz/eval2.c [new file with mode: 0644]
usr/src/ucb/lisp/franz/inits.c [new file with mode: 0644]
usr/tmp/housel/franz/eval2.c [new file with mode: 0644]
usr/tmp/housel/franz/inits.c [new file with mode: 0644]

diff --git a/usr/src/ucb/lisp/franz/eval2.c b/usr/src/ucb/lisp/franz/eval2.c
new file mode 100644 (file)
index 0000000..c735ae1
--- /dev/null
@@ -0,0 +1,540 @@
+#ifndef lint
+static char *rcsid =
+   "$Header: eval2.c,v 1.8 85/03/24 11:03:02 sklower Exp $";
+#endif
+
+/*                                     -[Sat May  7 23:38:37 1983 by jkf]-
+ *     eval2.c                         $Locker:  $
+ * more of the evaluator
+ *
+ * (c) copyright 1982, Regents of the University of California
+ */
+
+
+#include "global.h"
+#include "frame.h"
+
+/* Iarray - handle array call.
+ *  fun - array object
+ *  args - arguments to the array call , most likely subscripts.
+ *  evalp - flag, if TRUE then the arguments should be evaluated when they
+ *     are stacked.
+ */
+lispval
+Iarray(fun,args,evalp)
+register lispval fun,args;
+{
+       Savestack(2);
+       
+       lbot = np;
+       protect(fun->ar.accfun);
+       for ( ; args != nil ; args = args->d.cdr)  /* stack subscripts */
+         if(evalp) protect(eval(args->d.car));
+         else protect(args->d.car);
+       protect(fun);
+       vtemp = Lfuncal();
+       Restorestack();
+       return(vtemp);
+}
+
+    
+dumpmydata(thing)
+int thing;
+{
+       register int *ip = &thing;
+       register int *lim = ip + nargs();
+
+       printf("Dumpdata got %d args:\n",nargs());
+       while(ip < lim) printf("%x\n",*ip++);
+       return(0);
+}
+/* Ifcall :: call foreign function/subroutine
+ *   Ifcall is handed a binary object which is the function to call.
+ * This function has already been determined to be a foreign function
+ * by noticing that its discipline field is a string.  
+ * The arguments to pass have already been evaluated and stacked.  We
+ * create on the stack a 'callg' type argument list to give to the 
+ * function.  What is passed to the foreign function depends on the
+ * type of argument.  Certain args are passes directly, others must be
+ * copied since the foreign function my want to change them.
+ * When the foreign function returns, we may have to box the result,
+ * depending on the type of foreign function.
+ */
+lispval
+Ifcall(a)
+lispval a;
+{
+       char *alloca();
+       long callg_();
+       register int *arglist;
+       register int index;
+       register struct argent *mynp;
+       register lispval ltemp;
+       pbuf pb;
+       int nargs = np - lbot, kind, mysize, *ap;
+       Keepxs();
+
+       /* put a frame on the stack which will save np and lbot in a
+          easy to find place in a standard way */
+       errp = Pushframe(F_TO_FORT,nil,nil);
+       mynp = lbot;
+       kind = (((char *)a->bcd.discipline)[0]);
+
+       /* dispatch according to whether call by reference or value semantics */
+       switch(kind) {
+       case 'f': case 'i': case 's': case 'r':
+               arglist = (int *) alloca((nargs + 1) * sizeof(int));
+               *arglist = nargs;
+               for(index = 1; index <=  nargs; index++) {
+                       switch(TYPE(ltemp=mynp->val)) {
+                               /* fixnums and flonums must be reboxed */
+                       case INT:
+                               stack(0);
+                               arglist[index] = (int) sp();
+                               *(int *) arglist[index] = ltemp->i;
+                               break;
+                       case DOUB:
+                               stack(0);
+                               stack(0);
+                               arglist[index] = (int) sp();
+                               *(double *) arglist[index] = ltemp->r;
+                               break;
+
+                               /* these cause only part of the structure to be sent */
+
+                       case ARRAY:
+                               arglist[index] = (int) ltemp->ar.data;
+                               break;
+
+
+                       case BCD:
+                               arglist[index] = (int) ltemp->bcd.start;
+                               break;
+
+                               /* anything else should be sent directly */
+
+                       default:
+                               arglist[index] = (int) ltemp;
+                               break;
+                       }
+                       mynp++;
+               }
+               break;
+       case 'v':
+               while(TYPE(mynp->val)!=VECTORI)
+                       mynp->val = error(
+"First arg to c-function-returning-vector must be of type vector-immediate",
+                                         TRUE);
+               nargs--;
+               mynp++;
+               lbot++;
+       case 'c': case 'd':
+               /* make one pass over args 
+               calculating size of arglist */
+               while(mynp < np) switch(TYPE(ltemp=mynp++->val)) {
+               case DOUB:
+                       nargs += ((sizeof(double)/sizeof(int))-1);
+                       break;
+               case VECTORI:
+                       if(ltemp->v.vector[-1]==Vpbv) {
+                           nargs += -1+VecTotSize(ltemp->vl.vectorl[-2]);
+                       }
+               }
+               arglist = (int *) alloca((nargs+1)*sizeof(int));
+               *arglist = nargs;
+               ap = arglist + 1;
+               /* make another pass over the args
+                  actually copying the arguments */
+               for(mynp = lbot; mynp < np; mynp++)
+                       switch(TYPE(ltemp=mynp->val)) {
+               case INT:
+                       *ap++ = ltemp->i;
+                       break;
+               case DOUB:
+                       *(double *)ap = ltemp->r;
+                       ap += (sizeof (double)) / (sizeof (long));
+                       break;
+               case VECTORI:
+                       if(ltemp->v.vector[-1]==Vpbv) {
+                               mysize = ltemp->vl.vectorl[-2];
+                               mysize = sizeof(long) * VecTotSize(mysize);
+                               xbcopy(ap,ltemp,mysize);
+                               ap = (long *) (mysize + (int) ap);
+                               break;
+                       }
+               default:
+                       *ap++ = (long) ltemp;
+               }
+       }
+       switch(kind) {
+               case 'i': /* integer-function */
+               case 'c': /* C-function */
+                       ltemp = inewint(callg_(a->bcd.start,arglist));
+                       break;
+
+               case 'r': /* real-function*/
+               case 'd': /* C function declared returning double */
+                       {
+                       double result =
+                          (* ((double (*)()) callg_))(a->bcd.start,arglist);
+                       ltemp = newdoub();
+                       ltemp->r = result; 
+                       }
+                       break;
+
+               case 'f':  /* function */
+                       ltemp = (lispval) callg_(a->bcd.start,arglist);
+                       break;
+
+               case 'v': /* C function returning a structure */
+                       ap = (long *) callg_(a->bcd.start,arglist);
+                       ltemp = (--lbot)->val;
+                       mysize = ltemp->vl.vectorl[-2];
+                       mysize = sizeof(long) * VecTotSize(mysize);
+                       xbcopy(ltemp,ap,mysize);
+                       break;
+
+               default:
+               case 's': /* subroutine */
+                       callg_(a->bcd.start,arglist);
+                       ltemp = tatom;
+       }
+       errp = Popframe();
+       Freexs();
+       return(ltemp);
+}
+
+xbcopy(to,from,size)
+register char *to, *from;
+register size;
+{
+       while(--size >= 0) *to++ = *from++;
+}
+
+lispval
+ftolsp_(arg1)
+lispval arg1;
+{
+       int count; 
+       register lispval *ap = &arg1;
+       lispval save;
+       pbuf pb;
+       Savestack(1);
+
+       if((count = nargs())==0) return;;
+
+       if(errp->class==F_TO_FORT)
+               np = errp->svnp;
+       errp = Pushframe(F_TO_LISP,nil,nil);
+       lbot = np;
+       for(; count > 0; count--)
+               np++->val = *ap++;
+       save = Lfuncal();
+       errp = Popframe();
+       Restorestack();
+       return(save);
+}
+
+lispval
+ftlspn_(func,arglist)
+lispval func;
+register long *arglist;
+{
+       int count; 
+       lispval save;
+       pbuf pb;
+       Savestack(1);
+
+       if(errp->class==F_TO_FORT)
+               np = errp->svnp;
+       errp = Pushframe(F_TO_LISP,nil,nil);
+       lbot = np;
+       np++->val = func;
+       count = *arglist++;
+       for(; count > 0; count--)
+               np++->val = (lispval) (*arglist++);
+       save = Lfuncal();
+       errp = Popframe();
+       Restorestack();
+       return(save);
+}
+
+
+    
+/* Ifclosure :: evaluate a fclosure  (new version)
+ * the argument clos is a vector whose property is the atom fclosure
+ * the form of the vector is
+ *   0: function to run
+ * then for each symbol there is on vector entry containing a
+ * pointer to a sequence of two list cells of this form:
+ *     (name value . count)
+ * name is the symbol name to close over
+ * value is the saved value of the closure
+ *     (if the closure is 'active', the current value will be in the
+ *      symbol itself)
+ * count is a fixnum box (which can be destructively modified safely)
+ *  it is normally 0.  Each time the variable is put on the stack, it is
+ *  incremented.  It is decremented each time the the closure is left.
+ *  If the closure is invoked recusively without a rebinding of the
+ *  closure variable X, then the count will not be incremented.
+ *
+ * when entering a fclosure, for each variable there are three
+ * possibities:
+ *  (a) this is the first instance of this closed variable
+ *  (b) this is the second or greater recursive instance of
+ *      this closure variable, however it hasn't been normally lambda
+ *     bound since the last closure invocation
+ *  (c) like (b) but it has been lambda bound before the most recent
+ *     closure.
+ *
+ * case (a) can be determined by seeing if the count is 0.
+ * if the count is >0 then we must scan from the top of the stack down
+ * until we find either the closure or a lambda binding of the variable
+ * this determines whether it is case (b) or (c).
+ *
+ * There are three actions to perform in this routine:
+ * 1.  determine the closure type (a,b or c) and do any binding necessary
+ * 2.  call the closure function
+ * 3.  unbind any necessary closure variables.
+ *
+ * Now, the details of those actions:
+ * 1. for case (b), do nothing as we are still working with the correct
+ *    value
+ *    for case (a), pushdown the symbol and give it the value from
+ *     the closure, inc the closure count
+ *      push a closure marker on the bindstack too.
+ *    for case (c), must locate the correct value to set by searching
+ *      for the last lambda binding before the previous closure.
+ *      pushdown the symbol and that value, inc the closure count
+ *      push a closure marker on the bindstack too.
+ *    a closure marker has atom == int:closure-marker and value pointing
+ *      to the closure list.  This will be noticed when unbinding.
+ *
+ *  3. unbinding is just like popnames except if a closure marker is
+ *     seen, then this must be done:
+ *     if the count is 1, just store the symbol's value in the closure
+ *      and decrement the count.
+ *      if the count is >1, then search up the stack for the last
+ *      lambda before the next occurance of this closure variable
+ *      and set its value to the current value of the closure.
+ *      decrement the closure count.
+ *
+ * clos is the fclosure, funcallp is TRUE if this is called from funcall,
+ * otherwise it is called from apply
+ */
+
+#define Case_A 0
+#define Case_B 1
+#define Case_C 2
+
+lispval
+Ifclosure(clos,funcallp)
+register lispval clos;
+{
+    struct nament *oldbnp = bnp, *lbnp, *locatevar();
+    register int i;
+    register lispval vect;
+    int numvars, vlength, tcase, foundc;
+    lispval handy, atm_dtpr, value_dtpr, Ifuncal(), Lapply();
+    Savestack(3);
+
+    /* bind variables to their values given in the fclosure */
+    vlength = VecTotSize(clos->vl.vectorl[VSizeOff]);
+    /* vector length must be positive (it has to have a function at least) */
+    if (vlength < 1)
+       errorh1(Vermisc,"funcall: fclosure has wrong size ",nil,FALSE,0, clos);
+
+    numvars = (vlength - 1);   /* number of varibles */
+    
+    for (i = 1 ; i < vlength ; i += 1)
+    {
+       atm_dtpr = clos->v.vector[i];   /* car is symbol name */
+       value_dtpr = atm_dtpr->d.cdr;   /* car: value, cdr:  fixnum count */
+
+       if(value_dtpr->d.cdr->i == 0)
+               tcase = Case_A;         /* first call */
+       else {
+           lbnp = locatevar(atm_dtpr,&foundc,bnp-1);
+           if (!foundc)
+           {
+               /* didn't find the expected closure, count must be
+                  wrong, correct it and assume case (a)
+                */
+               tcase = Case_A;
+               value_dtpr->d.cdr->i = 0;
+           }
+           else if(lbnp) tcase = Case_C ; /* found intermediate lambda bnd*/
+           else tcase = Case_B;           /* no intermediate lambda bind */
+       }
+
+       /* now bind the value if necessary */
+       switch(tcase) {
+           case Case_A: PUSHDOWN(atm_dtpr->d.car,value_dtpr->d.car);
+                        PUSHVAL(clos_marker,atm_dtpr);
+                        value_dtpr->d.cdr->i += 1;
+                        break;
+                        
+           case Case_B: break;         /* nothing to do */
+
+           case Case_C: /* push first bound value after last close */
+                        PUSHDOWN(atm_dtpr->d.car,lbnp->val);
+                        PUSHVAL(clos_marker,atm_dtpr);
+                        value_dtpr->d.cdr->i += 1;
+                        break;
+       }
+    }
+
+    if(funcallp)
+       handy = Ifuncal(clos->v.vector[0]);
+    else {
+       handy = lbot[-2].val;   /* get args to apply.  This is hacky and may
+                                          fail if apply is changed */
+       lbot = np;
+       protect(clos->v.vector[0]);
+       protect(handy);
+       handy = Lapply();
+    }
+
+    xpopnames(oldbnp); /* pop names with consideration for closure markers */
+    
+    if(!funcallp) Restorestack();
+    return(handy);
+}
+
+/* xpopnames :: pop values from bindstack, but look out for
+ *  closure markers.  This is  used (instead of the faster popnames)
+ * when we know there will be closure markers or when we can't
+ * be sure that there won't be closure markers (eg. in non-local go's)
+ */
+xpopnames(llimit)
+register struct nament *llimit;
+{
+    register struct nament *rnp, *lbnp;
+    lispval atm_dtpr, value_dtpr;
+    int foundc;
+
+    for(rnp = bnp; --rnp >= llimit;)
+    {
+        if(rnp->atm == clos_marker)
+       {
+           atm_dtpr = rnp->val;
+           value_dtpr = atm_dtpr->d.cdr;
+           if(value_dtpr->d.cdr->i <= 1)
+           {
+               /* this is the only occurance of this closure variable
+                * just restore current value to this closure.
+                */
+               value_dtpr->d.car = atm_dtpr->d.car->a.clb;
+           }
+           else {
+               /* locate the last lambda before the next occurance of
+                * this closure and store the current symbol's value
+                * there
+                */
+               lbnp = locatevar(atm_dtpr,&foundc,rnp-2);
+               if(!foundc)
+               {
+                   /* strange, there wasn't a closure to be found.
+                    * well, we will fix things up so the count is
+                    * right.
+                    */
+                   value_dtpr->d.car = atm_dtpr->d.car->a.clb;
+                   value_dtpr->d.cdr->i = 1;
+               }
+               else if (lbnp) {
+                   /* note how the closures value isn't necessarily
+                    * stored in the closure, it may be stored on
+                    * the bindstack
+                    */
+                   lbnp->val = atm_dtpr->d.car->a.clb;
+               }
+               /* the case where lbnp is 0 should never happen, but
+                  if it does, we can just do nothing safely
+                */
+           }
+           value_dtpr->d.cdr->i -= 1;
+       } else rnp->atm->a.clb = rnp->val;  /* the normal case */
+    }
+    bnp = llimit;
+}
+
+
+struct nament *
+locatevar(clos,foundc,rnp)
+struct nament *rnp;
+lispval clos;
+int *foundc;
+{
+    register struct nament  *retbnp;
+    lispval symb;
+
+    retbnp = (struct nament *) 0;
+    *foundc = 0;
+    
+    symb = clos->d.car;
+    
+    for(  ; rnp >= orgbnp ; rnp--)
+    {
+       if((rnp->atm == clos_marker) && (rnp->val == clos))
+       {
+           *foundc = 1;        /* found the closure */
+           return(retbnp);
+       }
+       if(rnp->atm == symb) retbnp = rnp;
+    }
+    return(retbnp);    
+}
+
+lispval
+LIfss()
+{
+       register lispval atm_dtpr, value_dtpr;
+       struct nament *oldbnp = bnp, *lbnp;
+       int tcase, foundc = 0;
+       lispval newval;
+       int argc = 1;
+       Savestack(2);
+
+       switch(np-lbot) {
+       case 2:
+               newval = np[-1].val;
+               argc++;
+       case 1:
+               atm_dtpr = lbot->val;
+               value_dtpr = atm_dtpr->d.cdr;
+               break;
+       default:
+               argerr("int:fclosure-symbol-stuff");
+       }
+       /* this code is copied from Ifclosure */
+
+       if(value_dtpr->d.cdr->i==0)
+               tcase = Case_A; /* closure is not active */
+       else {
+               lbnp = locatevar(atm_dtpr,&foundc,bnp-1);
+               if (!foundc)
+               {
+                       /* didn't find closure, count must be wrong,
+                          correct it and assume case (a).*/
+                       tcase = Case_A;
+                       value_dtpr->d.cdr->i = 0;
+               }
+               else if(lbnp) tcase = Case_C; /* found intermediate lambda*/
+               else tcase = Case_B;
+       }
+
+       switch(tcase) {
+       case Case_B:
+               if(argc==2) return(atm_dtpr->d.car->a.clb = newval);
+               return(atm_dtpr->d.car->a.clb);
+
+       case Case_A:
+               if(argc==2) return(value_dtpr->d.car = newval);
+               return(value_dtpr->d.car);
+
+       case Case_C:
+               if(argc==2) return(lbnp->val = newval);
+               return(lbnp->val);
+       }
+       /*NOTREACHED*/
+}
diff --git a/usr/src/ucb/lisp/franz/inits.c b/usr/src/ucb/lisp/franz/inits.c
new file mode 100644 (file)
index 0000000..05f5ecc
--- /dev/null
@@ -0,0 +1,212 @@
+#ifndef lint
+static char *rcsid =
+   "$Header: inits.c,v 1.7 85/03/24 11:03:12 sklower Exp $";
+#endif
+
+/*                                     -[Sat Jan 29 12:59:39 1983 by jkf]-
+ *     inits.c                         $Locker:  $
+ * initialization routines
+ *
+ * (c) copyright 1982, Regents of the University of California
+ */
+
+
+#include "global.h"
+#include <signal.h>
+#include "frame.h"
+
+/* initial
+ * initializes the parts of the system that cannot be automatically
+ * accomplished in the declarations.
+ */
+int reborn=0;  /*  flag to tell whether we are in fast-load version  */
+extern char *stabf;
+extern int fvirgin;
+extern int keywait;
+extern sigstruck, sigdelay;
+initial()
+{
+       int sigalrmh(), sigfpeh(),  sginth();
+       lispval Isstatus(),Istsrch();
+       extern int hashtop;
+
+       /* clear any memory of pending SIGINT's */
+       exception = FALSE;
+       sigintcnt = 0;
+
+       if( signal(SIGINT,SIG_IGN) != SIG_IGN)
+             signal(SIGINT,sginth);
+       if( signal(SIGHUP,SIG_IGN) != SIG_IGN)
+             signal(SIGHUP,sginth);
+       signal(SIGFPE,sginth);
+       signal(SIGALRM,sginth);
+       signal(SIGPIPE,sginth);
+       /* signals SIGBUS and SIGSEGV will be set up when the status list
+          is set up when the lisp is virgin, and will be set up according
+          to the current value on the status list if the lisp is reborn
+       */
+
+#ifdef SPISFP
+       {extern long *exsp; xsp = exsp;}
+#endif
+
+       if( reborn ) {
+               np = lbot = orgnp;
+               Nioreset();
+               stabf = 0;
+               fvirgin = 1;
+               loading->a.clb = nil;
+               gcrebear();
+
+               /* set up SIGBUS and SIGSEGV from current value 
+                  of status flag dumpcore
+               */
+               Isstatus(matom("dumpcore"),
+                        (Istsrch(matom("dumpcore")))->d.cdr->d.cdr->d.cdr);
+
+               makenv();
+               return;
+       }
+       for (hash=0;hash<hashtop;hash++) hasht[hash] = (struct atom *) CNIL;
+       
+       sbrk( LBPG-(((int)sbrk(0)) % LBPG) );   /* even up the break */
+       makevals();
+
+       orgnp = np;
+       makenv();
+
+}
+
+static
+makenv()
+{
+       register lispval env, temp;
+       register char *p, *q;
+       char **envp, envstr[STRBLEN];
+       extern char **environ;
+
+       lbot = np;
+       env = nil;
+       np++->val = env;
+       for (envp=environ; *envp!=NULL; envp++) ;
+       while (--envp >= environ) {
+               for(p= *envp,q=envstr; *p!='=' ; p++)
+                       if(q < envstr + STRBLEN)
+                               *q++ = *p;
+               *q = 0; p++;
+               /* at this point lbot->val==env, so it is protected
+                  from gc */
+               lbot->val = temp = newdot();
+               temp->d.cdr = env;
+               env = temp;
+               temp = newdot();
+               env->d.car = temp;
+               temp->d.car = matom(envstr);
+               temp->d.cdr = matom(p);
+       }
+       matom("environment")->a.clb = env;
+       np--;
+}
+
+sginth(signo){
+       re_enable(signo,sginth);
+       sigstruck |= (1 << signo);
+       /* handle SIGINT differently since it is the only
+          asychronous interrupt we handle              */
+       if( signo == SIGINT) {
+           if( ++sigintcnt == 1)
+           {  /* if this is the first interrupt, we just set a flag
+                 which will be checked in qfuncl and eval.  This will
+                 allow us to handle these interrupts when we are
+                 ready.
+              */
+              exception = TRUE;
+              /*putchar('A');*/
+              fflush(stdout);
+              sigstruck &= ~(1 << signo);
+              return;
+           }
+           else if (sigintcnt == 2)
+           {  /* the setting of  exception was ignored, we better
+                 make sure that all calls from compiled code
+                 go through qlinker
+               */
+               signal(SIGINT,SIG_IGN);  /* this may take a while, dont allow ints*/
+               clrtt(0);
+               /*putchar('B');*/
+               fflush(stdout);
+               signal(SIGINT,sginth);  /* ok to interrupt again */
+               sigstruck &= ~(1 << signo);
+               return;
+           }
+           else {
+               /*putchar('C');*/
+               fflush(stdout);
+           }
+       }
+
+       sigcall(signo);
+}
+sigcall(which)
+register which;
+{
+       extern lispval Lfuncal();
+       Savestack(1);
+
+       if(which == SIGINT) { sigintcnt = 0; exception = 0; }
+
+       if(sigacts[which]!=((lispval) 0)) {
+               pbuf pb;
+               int mustpop = 0;
+               if(errp && errp->class==F_TO_FORT) {
+                       np = errp->svnp;
+                       mustpop = 1;
+                       errp = Pushframe(F_TO_LISP,nil,nil);
+               }
+               lbot = np;
+               np -> val = sigacts[which];
+               INRNP;
+               np -> val = inewint((long)which);
+               INRNP;
+       {lispval temp;temp = rdrsdot, rdrsdot = rdrsdot2, rdrsdot2 = temp; /*KLUDGE*/}
+               Lfuncal();
+               if (mustpop) errp = Popframe();
+       {lispval temp;temp = rdrsdot, rdrsdot = rdrsdot2, rdrsdot2 = temp; /*KLUDGE*/}
+       }
+       sigstruck &= ~ (1<<which);
+       Restorestack();
+}
+delayoff(){
+       sigdelay = FALSE;
+       if(sigstruck)
+               dosig();
+}
+dosig()
+{
+       register int i; int which;
+       if(!sigdelay) 
+               for(which=0, i = 1;  i <= 65536;  which++,i<<=1) {
+                       keywait = FALSE;
+                       if(sigstruck & i)
+                               sigcall(which);
+               }
+}
+badmr(number)
+{
+       signal(number,badmr);
+       fflush(stdout);
+       error("Internal bad memory reference, you are advised to (reset).",FALSE);
+}
+
+#define        mask(s) (1 << ((s)-1))
+static
+re_enable(signo,handler)
+int (*handler)();
+{
+#if (os_4_2| os_4_3)
+       sigsetmask(sigblock(0) &~ mask(signo));
+#else
+       signal(signo,handler);
+#endif
+}
diff --git a/usr/tmp/housel/franz/eval2.c b/usr/tmp/housel/franz/eval2.c
new file mode 100644 (file)
index 0000000..c735ae1
--- /dev/null
@@ -0,0 +1,540 @@
+#ifndef lint
+static char *rcsid =
+   "$Header: eval2.c,v 1.8 85/03/24 11:03:02 sklower Exp $";
+#endif
+
+/*                                     -[Sat May  7 23:38:37 1983 by jkf]-
+ *     eval2.c                         $Locker:  $
+ * more of the evaluator
+ *
+ * (c) copyright 1982, Regents of the University of California
+ */
+
+
+#include "global.h"
+#include "frame.h"
+
+/* Iarray - handle array call.
+ *  fun - array object
+ *  args - arguments to the array call , most likely subscripts.
+ *  evalp - flag, if TRUE then the arguments should be evaluated when they
+ *     are stacked.
+ */
+lispval
+Iarray(fun,args,evalp)
+register lispval fun,args;
+{
+       Savestack(2);
+       
+       lbot = np;
+       protect(fun->ar.accfun);
+       for ( ; args != nil ; args = args->d.cdr)  /* stack subscripts */
+         if(evalp) protect(eval(args->d.car));
+         else protect(args->d.car);
+       protect(fun);
+       vtemp = Lfuncal();
+       Restorestack();
+       return(vtemp);
+}
+
+    
+dumpmydata(thing)
+int thing;
+{
+       register int *ip = &thing;
+       register int *lim = ip + nargs();
+
+       printf("Dumpdata got %d args:\n",nargs());
+       while(ip < lim) printf("%x\n",*ip++);
+       return(0);
+}
+/* Ifcall :: call foreign function/subroutine
+ *   Ifcall is handed a binary object which is the function to call.
+ * This function has already been determined to be a foreign function
+ * by noticing that its discipline field is a string.  
+ * The arguments to pass have already been evaluated and stacked.  We
+ * create on the stack a 'callg' type argument list to give to the 
+ * function.  What is passed to the foreign function depends on the
+ * type of argument.  Certain args are passes directly, others must be
+ * copied since the foreign function my want to change them.
+ * When the foreign function returns, we may have to box the result,
+ * depending on the type of foreign function.
+ */
+lispval
+Ifcall(a)
+lispval a;
+{
+       char *alloca();
+       long callg_();
+       register int *arglist;
+       register int index;
+       register struct argent *mynp;
+       register lispval ltemp;
+       pbuf pb;
+       int nargs = np - lbot, kind, mysize, *ap;
+       Keepxs();
+
+       /* put a frame on the stack which will save np and lbot in a
+          easy to find place in a standard way */
+       errp = Pushframe(F_TO_FORT,nil,nil);
+       mynp = lbot;
+       kind = (((char *)a->bcd.discipline)[0]);
+
+       /* dispatch according to whether call by reference or value semantics */
+       switch(kind) {
+       case 'f': case 'i': case 's': case 'r':
+               arglist = (int *) alloca((nargs + 1) * sizeof(int));
+               *arglist = nargs;
+               for(index = 1; index <=  nargs; index++) {
+                       switch(TYPE(ltemp=mynp->val)) {
+                               /* fixnums and flonums must be reboxed */
+                       case INT:
+                               stack(0);
+                               arglist[index] = (int) sp();
+                               *(int *) arglist[index] = ltemp->i;
+                               break;
+                       case DOUB:
+                               stack(0);
+                               stack(0);
+                               arglist[index] = (int) sp();
+                               *(double *) arglist[index] = ltemp->r;
+                               break;
+
+                               /* these cause only part of the structure to be sent */
+
+                       case ARRAY:
+                               arglist[index] = (int) ltemp->ar.data;
+                               break;
+
+
+                       case BCD:
+                               arglist[index] = (int) ltemp->bcd.start;
+                               break;
+
+                               /* anything else should be sent directly */
+
+                       default:
+                               arglist[index] = (int) ltemp;
+                               break;
+                       }
+                       mynp++;
+               }
+               break;
+       case 'v':
+               while(TYPE(mynp->val)!=VECTORI)
+                       mynp->val = error(
+"First arg to c-function-returning-vector must be of type vector-immediate",
+                                         TRUE);
+               nargs--;
+               mynp++;
+               lbot++;
+       case 'c': case 'd':
+               /* make one pass over args 
+               calculating size of arglist */
+               while(mynp < np) switch(TYPE(ltemp=mynp++->val)) {
+               case DOUB:
+                       nargs += ((sizeof(double)/sizeof(int))-1);
+                       break;
+               case VECTORI:
+                       if(ltemp->v.vector[-1]==Vpbv) {
+                           nargs += -1+VecTotSize(ltemp->vl.vectorl[-2]);
+                       }
+               }
+               arglist = (int *) alloca((nargs+1)*sizeof(int));
+               *arglist = nargs;
+               ap = arglist + 1;
+               /* make another pass over the args
+                  actually copying the arguments */
+               for(mynp = lbot; mynp < np; mynp++)
+                       switch(TYPE(ltemp=mynp->val)) {
+               case INT:
+                       *ap++ = ltemp->i;
+                       break;
+               case DOUB:
+                       *(double *)ap = ltemp->r;
+                       ap += (sizeof (double)) / (sizeof (long));
+                       break;
+               case VECTORI:
+                       if(ltemp->v.vector[-1]==Vpbv) {
+                               mysize = ltemp->vl.vectorl[-2];
+                               mysize = sizeof(long) * VecTotSize(mysize);
+                               xbcopy(ap,ltemp,mysize);
+                               ap = (long *) (mysize + (int) ap);
+                               break;
+                       }
+               default:
+                       *ap++ = (long) ltemp;
+               }
+       }
+       switch(kind) {
+               case 'i': /* integer-function */
+               case 'c': /* C-function */
+                       ltemp = inewint(callg_(a->bcd.start,arglist));
+                       break;
+
+               case 'r': /* real-function*/
+               case 'd': /* C function declared returning double */
+                       {
+                       double result =
+                          (* ((double (*)()) callg_))(a->bcd.start,arglist);
+                       ltemp = newdoub();
+                       ltemp->r = result; 
+                       }
+                       break;
+
+               case 'f':  /* function */
+                       ltemp = (lispval) callg_(a->bcd.start,arglist);
+                       break;
+
+               case 'v': /* C function returning a structure */
+                       ap = (long *) callg_(a->bcd.start,arglist);
+                       ltemp = (--lbot)->val;
+                       mysize = ltemp->vl.vectorl[-2];
+                       mysize = sizeof(long) * VecTotSize(mysize);
+                       xbcopy(ltemp,ap,mysize);
+                       break;
+
+               default:
+               case 's': /* subroutine */
+                       callg_(a->bcd.start,arglist);
+                       ltemp = tatom;
+       }
+       errp = Popframe();
+       Freexs();
+       return(ltemp);
+}
+
+xbcopy(to,from,size)
+register char *to, *from;
+register size;
+{
+       while(--size >= 0) *to++ = *from++;
+}
+
+lispval
+ftolsp_(arg1)
+lispval arg1;
+{
+       int count; 
+       register lispval *ap = &arg1;
+       lispval save;
+       pbuf pb;
+       Savestack(1);
+
+       if((count = nargs())==0) return;;
+
+       if(errp->class==F_TO_FORT)
+               np = errp->svnp;
+       errp = Pushframe(F_TO_LISP,nil,nil);
+       lbot = np;
+       for(; count > 0; count--)
+               np++->val = *ap++;
+       save = Lfuncal();
+       errp = Popframe();
+       Restorestack();
+       return(save);
+}
+
+lispval
+ftlspn_(func,arglist)
+lispval func;
+register long *arglist;
+{
+       int count; 
+       lispval save;
+       pbuf pb;
+       Savestack(1);
+
+       if(errp->class==F_TO_FORT)
+               np = errp->svnp;
+       errp = Pushframe(F_TO_LISP,nil,nil);
+       lbot = np;
+       np++->val = func;
+       count = *arglist++;
+       for(; count > 0; count--)
+               np++->val = (lispval) (*arglist++);
+       save = Lfuncal();
+       errp = Popframe();
+       Restorestack();
+       return(save);
+}
+
+
+    
+/* Ifclosure :: evaluate a fclosure  (new version)
+ * the argument clos is a vector whose property is the atom fclosure
+ * the form of the vector is
+ *   0: function to run
+ * then for each symbol there is on vector entry containing a
+ * pointer to a sequence of two list cells of this form:
+ *     (name value . count)
+ * name is the symbol name to close over
+ * value is the saved value of the closure
+ *     (if the closure is 'active', the current value will be in the
+ *      symbol itself)
+ * count is a fixnum box (which can be destructively modified safely)
+ *  it is normally 0.  Each time the variable is put on the stack, it is
+ *  incremented.  It is decremented each time the the closure is left.
+ *  If the closure is invoked recusively without a rebinding of the
+ *  closure variable X, then the count will not be incremented.
+ *
+ * when entering a fclosure, for each variable there are three
+ * possibities:
+ *  (a) this is the first instance of this closed variable
+ *  (b) this is the second or greater recursive instance of
+ *      this closure variable, however it hasn't been normally lambda
+ *     bound since the last closure invocation
+ *  (c) like (b) but it has been lambda bound before the most recent
+ *     closure.
+ *
+ * case (a) can be determined by seeing if the count is 0.
+ * if the count is >0 then we must scan from the top of the stack down
+ * until we find either the closure or a lambda binding of the variable
+ * this determines whether it is case (b) or (c).
+ *
+ * There are three actions to perform in this routine:
+ * 1.  determine the closure type (a,b or c) and do any binding necessary
+ * 2.  call the closure function
+ * 3.  unbind any necessary closure variables.
+ *
+ * Now, the details of those actions:
+ * 1. for case (b), do nothing as we are still working with the correct
+ *    value
+ *    for case (a), pushdown the symbol and give it the value from
+ *     the closure, inc the closure count
+ *      push a closure marker on the bindstack too.
+ *    for case (c), must locate the correct value to set by searching
+ *      for the last lambda binding before the previous closure.
+ *      pushdown the symbol and that value, inc the closure count
+ *      push a closure marker on the bindstack too.
+ *    a closure marker has atom == int:closure-marker and value pointing
+ *      to the closure list.  This will be noticed when unbinding.
+ *
+ *  3. unbinding is just like popnames except if a closure marker is
+ *     seen, then this must be done:
+ *     if the count is 1, just store the symbol's value in the closure
+ *      and decrement the count.
+ *      if the count is >1, then search up the stack for the last
+ *      lambda before the next occurance of this closure variable
+ *      and set its value to the current value of the closure.
+ *      decrement the closure count.
+ *
+ * clos is the fclosure, funcallp is TRUE if this is called from funcall,
+ * otherwise it is called from apply
+ */
+
+#define Case_A 0
+#define Case_B 1
+#define Case_C 2
+
+lispval
+Ifclosure(clos,funcallp)
+register lispval clos;
+{
+    struct nament *oldbnp = bnp, *lbnp, *locatevar();
+    register int i;
+    register lispval vect;
+    int numvars, vlength, tcase, foundc;
+    lispval handy, atm_dtpr, value_dtpr, Ifuncal(), Lapply();
+    Savestack(3);
+
+    /* bind variables to their values given in the fclosure */
+    vlength = VecTotSize(clos->vl.vectorl[VSizeOff]);
+    /* vector length must be positive (it has to have a function at least) */
+    if (vlength < 1)
+       errorh1(Vermisc,"funcall: fclosure has wrong size ",nil,FALSE,0, clos);
+
+    numvars = (vlength - 1);   /* number of varibles */
+    
+    for (i = 1 ; i < vlength ; i += 1)
+    {
+       atm_dtpr = clos->v.vector[i];   /* car is symbol name */
+       value_dtpr = atm_dtpr->d.cdr;   /* car: value, cdr:  fixnum count */
+
+       if(value_dtpr->d.cdr->i == 0)
+               tcase = Case_A;         /* first call */
+       else {
+           lbnp = locatevar(atm_dtpr,&foundc,bnp-1);
+           if (!foundc)
+           {
+               /* didn't find the expected closure, count must be
+                  wrong, correct it and assume case (a)
+                */
+               tcase = Case_A;
+               value_dtpr->d.cdr->i = 0;
+           }
+           else if(lbnp) tcase = Case_C ; /* found intermediate lambda bnd*/
+           else tcase = Case_B;           /* no intermediate lambda bind */
+       }
+
+       /* now bind the value if necessary */
+       switch(tcase) {
+           case Case_A: PUSHDOWN(atm_dtpr->d.car,value_dtpr->d.car);
+                        PUSHVAL(clos_marker,atm_dtpr);
+                        value_dtpr->d.cdr->i += 1;
+                        break;
+                        
+           case Case_B: break;         /* nothing to do */
+
+           case Case_C: /* push first bound value after last close */
+                        PUSHDOWN(atm_dtpr->d.car,lbnp->val);
+                        PUSHVAL(clos_marker,atm_dtpr);
+                        value_dtpr->d.cdr->i += 1;
+                        break;
+       }
+    }
+
+    if(funcallp)
+       handy = Ifuncal(clos->v.vector[0]);
+    else {
+       handy = lbot[-2].val;   /* get args to apply.  This is hacky and may
+                                          fail if apply is changed */
+       lbot = np;
+       protect(clos->v.vector[0]);
+       protect(handy);
+       handy = Lapply();
+    }
+
+    xpopnames(oldbnp); /* pop names with consideration for closure markers */
+    
+    if(!funcallp) Restorestack();
+    return(handy);
+}
+
+/* xpopnames :: pop values from bindstack, but look out for
+ *  closure markers.  This is  used (instead of the faster popnames)
+ * when we know there will be closure markers or when we can't
+ * be sure that there won't be closure markers (eg. in non-local go's)
+ */
+xpopnames(llimit)
+register struct nament *llimit;
+{
+    register struct nament *rnp, *lbnp;
+    lispval atm_dtpr, value_dtpr;
+    int foundc;
+
+    for(rnp = bnp; --rnp >= llimit;)
+    {
+        if(rnp->atm == clos_marker)
+       {
+           atm_dtpr = rnp->val;
+           value_dtpr = atm_dtpr->d.cdr;
+           if(value_dtpr->d.cdr->i <= 1)
+           {
+               /* this is the only occurance of this closure variable
+                * just restore current value to this closure.
+                */
+               value_dtpr->d.car = atm_dtpr->d.car->a.clb;
+           }
+           else {
+               /* locate the last lambda before the next occurance of
+                * this closure and store the current symbol's value
+                * there
+                */
+               lbnp = locatevar(atm_dtpr,&foundc,rnp-2);
+               if(!foundc)
+               {
+                   /* strange, there wasn't a closure to be found.
+                    * well, we will fix things up so the count is
+                    * right.
+                    */
+                   value_dtpr->d.car = atm_dtpr->d.car->a.clb;
+                   value_dtpr->d.cdr->i = 1;
+               }
+               else if (lbnp) {
+                   /* note how the closures value isn't necessarily
+                    * stored in the closure, it may be stored on
+                    * the bindstack
+                    */
+                   lbnp->val = atm_dtpr->d.car->a.clb;
+               }
+               /* the case where lbnp is 0 should never happen, but
+                  if it does, we can just do nothing safely
+                */
+           }
+           value_dtpr->d.cdr->i -= 1;
+       } else rnp->atm->a.clb = rnp->val;  /* the normal case */
+    }
+    bnp = llimit;
+}
+
+
+struct nament *
+locatevar(clos,foundc,rnp)
+struct nament *rnp;
+lispval clos;
+int *foundc;
+{
+    register struct nament  *retbnp;
+    lispval symb;
+
+    retbnp = (struct nament *) 0;
+    *foundc = 0;
+    
+    symb = clos->d.car;
+    
+    for(  ; rnp >= orgbnp ; rnp--)
+    {
+       if((rnp->atm == clos_marker) && (rnp->val == clos))
+       {
+           *foundc = 1;        /* found the closure */
+           return(retbnp);
+       }
+       if(rnp->atm == symb) retbnp = rnp;
+    }
+    return(retbnp);    
+}
+
+lispval
+LIfss()
+{
+       register lispval atm_dtpr, value_dtpr;
+       struct nament *oldbnp = bnp, *lbnp;
+       int tcase, foundc = 0;
+       lispval newval;
+       int argc = 1;
+       Savestack(2);
+
+       switch(np-lbot) {
+       case 2:
+               newval = np[-1].val;
+               argc++;
+       case 1:
+               atm_dtpr = lbot->val;
+               value_dtpr = atm_dtpr->d.cdr;
+               break;
+       default:
+               argerr("int:fclosure-symbol-stuff");
+       }
+       /* this code is copied from Ifclosure */
+
+       if(value_dtpr->d.cdr->i==0)
+               tcase = Case_A; /* closure is not active */
+       else {
+               lbnp = locatevar(atm_dtpr,&foundc,bnp-1);
+               if (!foundc)
+               {
+                       /* didn't find closure, count must be wrong,
+                          correct it and assume case (a).*/
+                       tcase = Case_A;
+                       value_dtpr->d.cdr->i = 0;
+               }
+               else if(lbnp) tcase = Case_C; /* found intermediate lambda*/
+               else tcase = Case_B;
+       }
+
+       switch(tcase) {
+       case Case_B:
+               if(argc==2) return(atm_dtpr->d.car->a.clb = newval);
+               return(atm_dtpr->d.car->a.clb);
+
+       case Case_A:
+               if(argc==2) return(value_dtpr->d.car = newval);
+               return(value_dtpr->d.car);
+
+       case Case_C:
+               if(argc==2) return(lbnp->val = newval);
+               return(lbnp->val);
+       }
+       /*NOTREACHED*/
+}
diff --git a/usr/tmp/housel/franz/inits.c b/usr/tmp/housel/franz/inits.c
new file mode 100644 (file)
index 0000000..05f5ecc
--- /dev/null
@@ -0,0 +1,212 @@
+#ifndef lint
+static char *rcsid =
+   "$Header: inits.c,v 1.7 85/03/24 11:03:12 sklower Exp $";
+#endif
+
+/*                                     -[Sat Jan 29 12:59:39 1983 by jkf]-
+ *     inits.c                         $Locker:  $
+ * initialization routines
+ *
+ * (c) copyright 1982, Regents of the University of California
+ */
+
+
+#include "global.h"
+#include <signal.h>
+#include "frame.h"
+
+/* initial
+ * initializes the parts of the system that cannot be automatically
+ * accomplished in the declarations.
+ */
+int reborn=0;  /*  flag to tell whether we are in fast-load version  */
+extern char *stabf;
+extern int fvirgin;
+extern int keywait;
+extern sigstruck, sigdelay;
+initial()
+{
+       int sigalrmh(), sigfpeh(),  sginth();
+       lispval Isstatus(),Istsrch();
+       extern int hashtop;
+
+       /* clear any memory of pending SIGINT's */
+       exception = FALSE;
+       sigintcnt = 0;
+
+       if( signal(SIGINT,SIG_IGN) != SIG_IGN)
+             signal(SIGINT,sginth);
+       if( signal(SIGHUP,SIG_IGN) != SIG_IGN)
+             signal(SIGHUP,sginth);
+       signal(SIGFPE,sginth);
+       signal(SIGALRM,sginth);
+       signal(SIGPIPE,sginth);
+       /* signals SIGBUS and SIGSEGV will be set up when the status list
+          is set up when the lisp is virgin, and will be set up according
+          to the current value on the status list if the lisp is reborn
+       */
+
+#ifdef SPISFP
+       {extern long *exsp; xsp = exsp;}
+#endif
+
+       if( reborn ) {
+               np = lbot = orgnp;
+               Nioreset();
+               stabf = 0;
+               fvirgin = 1;
+               loading->a.clb = nil;
+               gcrebear();
+
+               /* set up SIGBUS and SIGSEGV from current value 
+                  of status flag dumpcore
+               */
+               Isstatus(matom("dumpcore"),
+                        (Istsrch(matom("dumpcore")))->d.cdr->d.cdr->d.cdr);
+
+               makenv();
+               return;
+       }
+       for (hash=0;hash<hashtop;hash++) hasht[hash] = (struct atom *) CNIL;
+       
+       sbrk( LBPG-(((int)sbrk(0)) % LBPG) );   /* even up the break */
+       makevals();
+
+       orgnp = np;
+       makenv();
+
+}
+
+static
+makenv()
+{
+       register lispval env, temp;
+       register char *p, *q;
+       char **envp, envstr[STRBLEN];
+       extern char **environ;
+
+       lbot = np;
+       env = nil;
+       np++->val = env;
+       for (envp=environ; *envp!=NULL; envp++) ;
+       while (--envp >= environ) {
+               for(p= *envp,q=envstr; *p!='=' ; p++)
+                       if(q < envstr + STRBLEN)
+                               *q++ = *p;
+               *q = 0; p++;
+               /* at this point lbot->val==env, so it is protected
+                  from gc */
+               lbot->val = temp = newdot();
+               temp->d.cdr = env;
+               env = temp;
+               temp = newdot();
+               env->d.car = temp;
+               temp->d.car = matom(envstr);
+               temp->d.cdr = matom(p);
+       }
+       matom("environment")->a.clb = env;
+       np--;
+}
+
+sginth(signo){
+       re_enable(signo,sginth);
+       sigstruck |= (1 << signo);
+       /* handle SIGINT differently since it is the only
+          asychronous interrupt we handle              */
+       if( signo == SIGINT) {
+           if( ++sigintcnt == 1)
+           {  /* if this is the first interrupt, we just set a flag
+                 which will be checked in qfuncl and eval.  This will
+                 allow us to handle these interrupts when we are
+                 ready.
+              */
+              exception = TRUE;
+              /*putchar('A');*/
+              fflush(stdout);
+              sigstruck &= ~(1 << signo);
+              return;
+           }
+           else if (sigintcnt == 2)
+           {  /* the setting of  exception was ignored, we better
+                 make sure that all calls from compiled code
+                 go through qlinker
+               */
+               signal(SIGINT,SIG_IGN);  /* this may take a while, dont allow ints*/
+               clrtt(0);
+               /*putchar('B');*/
+               fflush(stdout);
+               signal(SIGINT,sginth);  /* ok to interrupt again */
+               sigstruck &= ~(1 << signo);
+               return;
+           }
+           else {
+               /*putchar('C');*/
+               fflush(stdout);
+           }
+       }
+
+       sigcall(signo);
+}
+sigcall(which)
+register which;
+{
+       extern lispval Lfuncal();
+       Savestack(1);
+
+       if(which == SIGINT) { sigintcnt = 0; exception = 0; }
+
+       if(sigacts[which]!=((lispval) 0)) {
+               pbuf pb;
+               int mustpop = 0;
+               if(errp && errp->class==F_TO_FORT) {
+                       np = errp->svnp;
+                       mustpop = 1;
+                       errp = Pushframe(F_TO_LISP,nil,nil);
+               }
+               lbot = np;
+               np -> val = sigacts[which];
+               INRNP;
+               np -> val = inewint((long)which);
+               INRNP;
+       {lispval temp;temp = rdrsdot, rdrsdot = rdrsdot2, rdrsdot2 = temp; /*KLUDGE*/}
+               Lfuncal();
+               if (mustpop) errp = Popframe();
+       {lispval temp;temp = rdrsdot, rdrsdot = rdrsdot2, rdrsdot2 = temp; /*KLUDGE*/}
+       }
+       sigstruck &= ~ (1<<which);
+       Restorestack();
+}
+delayoff(){
+       sigdelay = FALSE;
+       if(sigstruck)
+               dosig();
+}
+dosig()
+{
+       register int i; int which;
+       if(!sigdelay) 
+               for(which=0, i = 1;  i <= 65536;  which++,i<<=1) {
+                       keywait = FALSE;
+                       if(sigstruck & i)
+                               sigcall(which);
+               }
+}
+badmr(number)
+{
+       signal(number,badmr);
+       fflush(stdout);
+       error("Internal bad memory reference, you are advised to (reset).",FALSE);
+}
+
+#define        mask(s) (1 << ((s)-1))
+static
+re_enable(signo,handler)
+int (*handler)();
+{
+#if (os_4_2| os_4_3)
+       sigsetmask(sigblock(0) &~ mask(signo));
+#else
+       signal(signo,handler);
+#endif
+}