BSD 4_3_Tahoe development
authorCSRG <csrg@ucbvax.Berkeley.EDU>
Mon, 14 Dec 1987 11:39:33 +0000 (03:39 -0800)
committerCSRG <csrg@ucbvax.Berkeley.EDU>
Mon, 14 Dec 1987 11:39:33 +0000 (03:39 -0800)
Work on file usr/tmp/housel/franz/lam1.c
Work on file usr/src/ucb/lisp/franz/lam1.c

Synthesized-from: CSRG/cd2/4.3tahoe

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

diff --git a/usr/src/ucb/lisp/franz/lam1.c b/usr/src/ucb/lisp/franz/lam1.c
new file mode 100644 (file)
index 0000000..8ff097a
--- /dev/null
@@ -0,0 +1,971 @@
+#ifndef lint
+static char *rcsid =
+   "$Header: lam1.c,v 1.8 87/12/14 18:39:12 sklower Exp $";
+#endif
+
+/*                                     -[Fri Feb 17 16:44:24 1984 by layer]-
+ *     lam1.c                          $Locker:  $
+ * lambda functions
+ *
+ * (c) copyright 1982, Regents of the University of California
+ */
+
+# include "global.h"
+# include <sgtty.h>
+# include "chkrtab.h"
+# include "frame.h"
+
+lispval
+Leval()
+{
+       register lispval temp;
+
+       chkarg(1,"eval");
+       temp = lbot->val;
+           return(eval(temp));
+}
+
+lispval
+Lxcar()
+{      register int typ;
+       register lispval temp, result;
+
+       chkarg(1,"xcar");
+       temp = lbot->val;
+       if (((typ = TYPE(temp)) == DTPR) || (typ == ATOM) || HUNKP(temp))
+           return(temp->d.car);
+       else if(typ == SDOT) {
+               result = inewint(temp->i);
+               return(result);
+       } else if(Schainp!=nil && typ==ATOM)
+               return(nil);
+       else
+               return(error("Bad arg to car",FALSE));
+
+}
+
+lispval
+Lxcdr()
+{      register int typ;
+       register lispval temp;
+
+       chkarg(1,"xcdr");
+       temp = lbot->val;
+       if(temp==nil) return (nil);
+
+       if (((typ = TYPE(temp)) == DTPR) || HUNKP(temp)) 
+           return(temp->d.cdr);
+       else if(typ==SDOT) {
+               if(temp->s.CDR==0) return(nil);
+               temp = temp->s.CDR;
+               if(TYPE(temp)==DTPR)
+                   errorh1(Vermisc,"Fell off the end of a bignum",nil,FALSE,5,lbot->val);
+               return(temp);
+       } else if(Schainp!=nil && typ==ATOM)
+               return(nil);
+       else
+               return(error("Bad arg to cdr", FALSE));
+}
+
+lispval
+cxxr(as,ds)
+register int as,ds;
+{
+
+       register lispval temp, temp2;
+       int i, typ;
+       lispval errorh();
+
+       chkarg(1,"c{ad}+r");
+       temp = lbot->val;
+
+       for( i=0 ; i<ds ; i++)
+       {
+           if( temp != nil)
+           {
+               typ = TYPE(temp);
+               if ((typ == DTPR) || HUNKP(temp))
+                   temp = temp->d.cdr;
+               else
+                   if(typ==SDOT)
+                   {
+                       if(temp->s.CDR==0)
+                           temp = nil;
+                       else
+                           temp = temp->s.CDR;
+                       if(TYPE(temp)==DTPR)
+                           errorh1(Vermisc,"Fell off the end of a bignum",nil,FALSE,5,lbot->val);
+                   }
+               else
+                   if(Schainp!=nil && typ==ATOM)
+                       return(nil);
+               else
+                   return(errorh1(Vermisc,"Bad arg to cdr",nil,FALSE,5,temp));
+           }
+       }
+
+       for( i=0 ; i<as ; i++)
+       {
+           if( temp != nil )
+           {
+               typ = TYPE(temp);
+               if ((typ == DTPR) || HUNKP(temp))
+                   temp = temp->d.car;
+               else if(typ == SDOT)
+                       temp2 = inewint(temp->i), temp = temp2;
+               else if(Schainp!=nil && typ==ATOM)
+                   return(nil);
+               else
+                   return(errorh1(Vermisc,"Bad arg to car",nil,FALSE,5,temp));
+           }
+       }
+
+       return(temp);
+}
+
+lispval
+Lcar()
+{      return(cxxr(1,0)); }
+
+lispval
+Lcdr()
+{      return(cxxr(0,1)); }
+
+lispval
+Lcadr()
+{      return(cxxr(1,1)); }
+
+lispval
+Lcaar()
+{      return(cxxr(2,0)); }
+
+lispval
+Lc02r()
+{      return(cxxr(0,2)); }    /* cddr */
+
+lispval
+Lc12r()
+{      return(cxxr(1,2)); }    /* caddr */
+
+lispval
+Lc03r()
+{      return(cxxr(0,3)); }    /* cdddr */
+
+lispval
+Lc13r()
+{      return(cxxr(1,3)); }    /* cadddr */
+
+lispval
+Lc04r()
+{      return(cxxr(0,4)); }    /* cddddr */
+
+lispval
+Lc14r()
+{      return(cxxr(1,4)); }    /* caddddr */
+
+/*
+ *  
+ *     (nthelem num list)
+ *
+ * Returns the num'th element of the list, by doing a caddddd...ddr
+ * where there are num-1 d's. If num<=0 or greater than the length of
+ * the list, we return nil.
+ *
+ */
+
+lispval
+Lnthelem()
+{
+       register lispval temp;
+       register int i;
+
+       chkarg(2,"nthelem");
+
+       if( TYPE(temp = lbot->val) != INT)
+       return (error ("First arg to nthelem must be a fixnum",FALSE));
+
+       i = temp->i;    /* pick up the first arg */
+
+       if( i <= 0) return(nil);
+
+       ++lbot;                 /* fix lbot for call to cxxr() 'cadddd..r' */
+       temp = cxxr(1,i-1);
+       --lbot;
+
+       return(temp);
+}
+
+lispval
+Lscons()
+{
+       register struct argent *argp = lbot;
+       register lispval retp, handy;
+
+       chkarg(2,"scons");
+       retp = newsdot();
+       handy = (argp) -> val;
+       if(TYPE(handy)!=INT)
+               error("First arg to scons must be an int.",FALSE);
+       retp->s.I = handy->i;
+       handy = (argp+1)->val;
+       if(handy==nil)
+               retp->s.CDR = (lispval) 0;
+       else {
+               if(TYPE(handy)!=SDOT)
+                   error("Currently you may only link sdots to sdots.",FALSE);
+               retp->s.CDR = handy;
+       }
+       return(retp);
+}
+
+lispval
+Lbigtol(){
+       register lispval handy,newp;
+
+       chkarg(1,"Bignum-to-list");
+       handy = lbot->val;
+       while(TYPE(handy)!=SDOT)
+               handy = errorh1(Vermisc,
+                               "Non bignum argument to Bignum-to-list",
+                               nil,TRUE,5755,handy);
+       protect(newp = newdot());
+       while(handy) {
+               newp->d.car = inewint((long)handy->s.I);
+               if(handy->s.CDR==(lispval) 0) break;
+               newp->d.cdr = newdot();
+               newp = newp->d.cdr;
+               handy = handy->s.CDR;
+       }
+       handy = (--np)->val;
+       return(handy);
+}
+
+lispval
+Lcons()
+{
+       register lispval retp;
+       register struct argent *argp;
+
+       chkarg(2,"cons");
+       retp = newdot();
+       retp->d.car = ((argp = lbot) -> val);
+       retp->d.cdr = argp[1].val;
+       return(retp);
+}
+#define CA 0
+#define CD 1
+
+lispval
+rpla(what)
+int what;
+{      register struct argent *argp;
+       register int typ; register lispval first, second;
+
+       chkarg(2,"rplac[ad]");
+       argp = np-1;
+       first = (argp-1)->val;
+       while(first==nil)
+               first = error("Attempt to rplac[ad] nil.",TRUE);
+       second = argp->val;
+       if (((typ = TYPE(first)) == DTPR) || (typ == ATOM) || HUNKP(first)) {
+               if (what == CA)
+                       first->d.car = second;
+               else 
+                       first->d.cdr = second;
+               return(first);
+       }
+       if (typ==SDOT) {
+               if(what == CA) {
+                       typ = TYPE(second);
+                       if(typ!=INT) error("Rplacca of a bignum will only replace INTS",FALSE);
+                       first->s.I = second->i;
+               } else {
+                       if(second==nil)
+                               first->s.CDR = (lispval) 0;
+                       else
+                               first->s.CDR = second;
+               }
+               return(first);
+       }
+       return(error("Bad arg to rpla",FALSE));
+}
+lispval
+Lrplca()
+{      return(rpla(CA));       }
+
+lispval
+Lrplcd()
+{      return(rpla(CD));       }
+
+
+lispval
+Leq()
+{
+       register struct argent *mynp = lbot + AD;
+
+       chkarg(2,"eq");
+       if(mynp->val==(mynp+1)->val) return(tatom);
+       return(nil);
+}
+
+
+
+lispval
+Lnull()
+{      chkarg(1,"null");
+       return ((lbot->val == nil) ? tatom : nil);
+}
+
+
+
+/* Lreturn **************************************************************/
+/* Returns the first argument - which is nill if not specified.                */
+
+lispval
+Lreturn()
+{
+       if(lbot==np) protect (nil);
+       Inonlocalgo(C_RET,lbot->val,nil);
+       /* NOT REACHED */
+}
+
+
+lispval
+Linfile()
+{
+       FILE *port;
+       register lispval name;
+
+       chkarg(1,"infile");
+       name = lbot->val;
+loop:
+       name = verify(name,"infile: file name must be atom or string");
+       /* return nil if file couldnt be opened
+       if ((port = fopen((char *)name,"r")) == NULL) return(nil); */   
+
+       if ((port = fopen((char *)name,"r")) == NULL) {
+               name = errorh1(Vermisc,"Unable to open file for reading.",nil,TRUE,31,name);
+               goto loop;
+       }
+       ioname[PN(port)] = (lispval) inewstr((char *)name); /* remember name */
+       return(P(port));
+}
+
+/* outfile - open a file for writing.  
+ * 27feb81 [jkf] - modifed to accept two arguments, the second one being a
+ *   string or atom, which if it begins with an `a' tells outfile to open the
+ *   file in append mode
+ */
+lispval
+Loutfile()
+{
+       FILE *port; register lispval name;
+       char *mode ="w";    /* mode is w for create new file, a for append */
+       char *given;
+
+       if(lbot+1== np) protect(nil);
+       chkarg(2,"outfile");
+       name = lbot->val;
+       given = (char *)verify((lbot+1)->val,"Illegal file open mode.");
+       if(*given == 'a') mode = "a";
+loop:
+       name = verify(name,"Please supply atom or string name for port.");
+#ifdef os_vms
+       /*
+        *      If "w" mode, open it as a "txt" file for convenience in VMS
+        */
+       if (strcmp(mode,"w") == 0) {
+               int fd;
+
+               if ((fd = creat(name,0777,"txt")) < 0) {
+                       name = errorh1(Vermisc,"Unable to open file for writing.",nil,TRUE,31,name);
+                       goto loop;
+               }
+               port = fdopen(fd,mode);
+       } else
+#endif
+       if ((port = fopen((char *)name,mode)) == NULL) {
+               name = errorh1(Vermisc,"Unable to open file for writing.",nil,TRUE,31,name);
+               goto loop;
+       }
+       ioname[PN(port)] = (lispval) inewstr((char *)name);
+       return(P(port));
+}
+
+lispval
+Lterpr()
+{
+       register lispval handy;
+       FILE *port;
+
+       if(lbot==np) handy = nil;
+       else 
+       { 
+           chkarg(1,"terpr");
+           handy = lbot->val;
+       }
+
+       port = okport(handy,okport(Vpoport->a.clb,stdout));
+       putc('\n',port);
+       fflush(port);
+       return(nil);
+}
+
+lispval
+Lclose()
+{
+       lispval port;
+
+       chkarg(1,"close");
+       port = lbot->val;
+       if((TYPE(port))==PORT) {
+               fclose(port->p);
+               ioname[PN(port->p)] = nil;
+               return(tatom);
+       }
+       errorh1(Vermisc,"close:Non-port",nil,FALSE,987,port);
+       /* not reached */
+}
+
+lispval
+Ltruename()
+{
+    chkarg(1,"truename");
+    if(TYPE(lbot->val) != PORT)
+       errorh1(Vermisc,"truename: non port argument",nil,FALSE,0,lbot->val);
+
+    return(ioname[PN(lbot->val->p)]);
+}
+
+lispval
+Lnwritn()
+{
+       register FILE *port;
+       register value;
+       register lispval handy;
+
+       if(lbot==np) handy = nil;
+       else 
+       {
+           chkarg(1,"nwritn");
+           handy = lbot->val;
+       }
+
+       port = okport(handy,okport(Vpoport->a.clb,stdout));
+       value = port->_ptr - port->_base;
+       return(inewint(value));
+}
+
+lispval
+Ldrain()
+{
+       register FILE *port;
+       register int iodes;
+       register lispval handy;
+       struct sgttyb arg;
+
+       if(lbot==np) handy = nil;
+       else 
+       {
+           chkarg(1,"nwritn");
+           handy = lbot->val;
+       }
+       port = okport(handy, okport(Vpoport->a.clb,stdout));
+       if(port->_flag & _IOWRT) {
+               fflush(port);
+               return(nil);
+       }
+       if(! port->_flag & _IOREAD) return(nil);
+       port->_cnt = 0;
+       port->_ptr = port->_base;
+       iodes = fileno(port);
+       if(gtty(iodes,&arg) != -1) stty(iodes,&arg);
+       return(P(port));
+}
+
+lispval
+Llist()
+{
+       /* added for the benefit of mapping functions. */
+       register struct argent *ulim, *namptr;
+       register lispval temp, result;
+       Savestack(4);
+
+       ulim = np;
+       namptr = lbot + AD;
+       temp = result = (lispval) np;
+       protect(nil);
+       for(; namptr < ulim;) {
+               temp = temp->l = newdot();
+               temp->d.car = (namptr++)->val;
+       }
+       temp->l = nil;
+       Restorestack();
+       return(result->l);
+}
+
+lispval
+Lnumberp()
+{
+       chkarg(1,"numberp");
+       switch(TYPE(lbot->val)) {
+       case INT: case DOUB: case SDOT:
+               return(tatom);
+       }
+       return(nil);
+}
+
+lispval
+Latom()
+{
+       register struct argent *lb = lbot;
+       chkarg(1,"atom");
+       if(TYPE(lb->val)==DTPR || (HUNKP(lb->val)))
+               return(nil);
+       else
+               return(tatom);
+}
+
+lispval
+Ltype()
+{
+       chkarg(1,"type");
+       switch(TYPE(lbot->val)) {
+       case INT:
+               return(int_name);
+       case ATOM:
+               return(atom_name);
+       case SDOT:
+               return(sdot_name);
+       case DOUB:
+               return(doub_name);
+       case DTPR:
+               return(dtpr_name);
+       case STRNG:
+               return(str_name);
+       case ARRAY:
+               return(array_name);
+       case BCD:
+               return(funct_name);
+       case OTHER:
+               return(other_name);
+
+       case HUNK2:
+               return(hunk_name[0]);
+       case HUNK4:
+               return(hunk_name[1]);
+       case HUNK8:
+               return(hunk_name[2]);
+       case HUNK16:
+               return(hunk_name[3]);
+       case HUNK32:
+               return(hunk_name[4]);
+       case HUNK64:
+               return(hunk_name[5]);
+       case HUNK128:
+               return(hunk_name[6]);
+               
+       case VECTOR:
+               return(vect_name);
+       case VECTORI:
+               return(vecti_name);
+
+       case VALUE:
+               return(val_name);
+       case PORT:
+               return(port_name);
+       }
+       return(nil);
+}
+
+lispval
+Ldtpr()
+{
+       chkarg(1,"dtpr");
+       return(typred(DTPR, lbot->val));
+}
+
+lispval
+Lbcdp()
+{
+       chkarg(1,"bcdp");
+       return(typred(BCD, lbot->val));
+}
+
+lispval
+Lportp()
+{
+       chkarg(1,"portp");
+       return(typred(PORT, lbot->val));
+}
+
+lispval
+Larrayp()
+{
+       chkarg(1,"arrayp");
+       return(typred(ARRAY, lbot->val));
+}
+
+/*
+ *     (hunkp 'g_arg1)
+ * Returns t if g_arg1 is a hunk, otherwise returns nil.
+ */
+
+lispval
+Lhunkp()
+{
+       chkarg(1,"hunkp");
+       if (HUNKP(lbot->val))
+               return(tatom);          /* If a hunk, return t */
+       else
+               return(nil);            /* else nil */
+}
+
+lispval
+Lset()
+{
+       lispval varble;
+
+       chkarg(2,"set");
+       varble = lbot->val;
+       switch(TYPE(varble))
+               {
+       case ATOM:      return(varble->a.clb = lbot[1].val);
+
+       case VALUE:     return(varble->l = lbot[1].val);
+               }
+
+       error("IMPROPER USE OF SET",FALSE);
+       /* NOTREACHED */
+}
+
+lispval
+Lequal()
+{
+       register lispval first, second;
+       register type1, type2;
+       lispval Lsub(),Lzerop();
+       long *oldsp;
+       Keepxs();
+       chkarg(2,"equal");
+
+
+       if(lbot->val==lbot[1].val) return(tatom);
+
+       oldsp=sp(); stack((long)lbot->val);stack((long)lbot[1].val);
+       for(;oldsp > sp();) {
+
+           first = (lispval) unstack(); second = (lispval) unstack();
+    again:
+           if(first==second) continue;
+
+           type1=TYPE(first); type2=TYPE(second);
+           if(type1!=type2) {
+               if((type1==SDOT&&type2==INT)||(type1==INT&&type2==SDOT))
+                   goto dosub;
+               {Freexs(); return(nil);}
+           }
+           switch(type1) {
+           case DTPR:
+               stack((long)first->d.cdr); stack((long)second->d.cdr);
+               first = first->d.car; second = second->d.car;
+               goto again;
+           case DOUB:
+               if(first->r!=second->r)
+                   {Freexs(); return(nil);}
+               continue;
+           case INT:
+               if(first->i!=second->i)
+                   {Freexs(); return(nil);}
+               continue;
+           case VECTOR:
+               if(!vecequal(first,second)) {Freexs(); return(nil);}
+               continue;
+           case VECTORI:
+               if(!veciequal(first,second)) {Freexs(); return(nil);}
+               continue;
+    dosub:
+           case SDOT: {
+               lispval temp;
+               struct argent *OLDlbot = lbot;
+               lbot = np;
+               np++->val = first;
+               np++->val = second;
+               temp = Lsub();
+               np = lbot;
+               lbot = OLDlbot;
+               if(TYPE(temp)!=INT || temp->i!=0)
+                   {Freexs(); return(nil);}
+               }
+               continue;
+           case VALUE:
+               if(first->l!=second->l)
+                   {Freexs(); return(nil);}
+               continue;
+           case STRNG:
+               if(strcmp((char *)first,(char *)second)!=0)
+                   {Freexs(); return(nil);}
+               continue;
+
+           default:
+               {Freexs(); return(nil);}
+           }
+       }
+       {Freexs(); return(tatom);}
+}
+lispval
+oLequal()
+{
+       chkarg(2,"equal");
+
+       if( lbot[1].val == lbot->val ) return(tatom);
+       if(Iequal(lbot[1].val,lbot->val)) return(tatom); else return(nil);
+}
+
+Iequal(first,second) 
+register lispval first, second;
+{
+       register type1, type2;
+       lispval Lsub(),Lzerop();
+
+       if(first==second)
+               return(1);
+       type1=TYPE(first);
+       type2=TYPE(second);
+       if(type1!=type2) {
+               if((type1==SDOT&&type2==INT)||(type1==INT&&type2==SDOT))
+                       goto dosub;
+               return(0);
+       }
+       switch(type1) {
+       case DTPR:
+                return(
+                       Iequal(first->d.car,second->d.car) &&
+                       Iequal(first->d.cdr,second->d.cdr) );
+       case DOUB:
+               return(first->r==second->r);
+       case INT:
+               return( (first->i==second->i));
+dosub:
+       case SDOT:
+       {
+               lispval temp;
+               struct argent *OLDlbot = lbot;
+               lbot = np;
+               np++->val = first;
+               np++->val = second;
+               temp = Lsub();
+               np = lbot;
+               lbot = OLDlbot;
+               return(TYPE(temp)==INT&& temp->i==0);
+       }
+       case VALUE:
+               return( first->l==second->l );
+       case STRNG:
+               return(strcmp((char *)first,(char *)second)==0);
+       }
+       return(0);
+}
+lispval
+Zequal()
+{
+       register lispval first, second;
+       register type1, type2;
+       lispval Lsub(),Lzerop();
+       long *oldsp;
+       Keepxs();
+       chkarg(2,"equal");
+
+
+       if(lbot->val==lbot[1].val) return(tatom);
+
+       oldsp=sp(); stack((long)lbot->val);stack((long)lbot[1].val);
+
+       for(;oldsp > sp();) {
+
+           first = (lispval) unstack(); second = (lispval) unstack();
+    again:
+           if(first==second) continue;
+
+           type1=TYPE(first); type2=TYPE(second);
+           if(type1!=type2) {
+               if((type1==SDOT&&type2==INT)||(type1==INT&&type2==SDOT))
+                   goto dosub;
+               {Freexs(); return(nil);}
+           }
+           switch(type1) {
+           case DTPR:
+               stack((long)first->d.cdr); stack((long)second->d.cdr);
+               first = first->d.car; second = second->d.car;
+               goto again;
+           case DOUB:
+               if(first->r!=second->r)
+                   {Freexs(); return(nil);}
+               continue;
+           case INT:
+               if(first->i!=second->i)
+                   {Freexs(); return(nil);}
+               continue;
+    dosub:
+           case SDOT:
+           {
+               lispval temp;
+               struct argent *OLDlbot = lbot;
+               lbot = np;
+               np++->val = first;
+               np++->val = second;
+               temp = Lsub();
+               np = lbot;
+               lbot = OLDlbot;
+               if(TYPE(temp)!=INT || temp->i!=0)
+                   {Freexs(); return(nil);}
+           }
+               continue;
+           case VALUE:
+               if(first->l!=second->l)
+                   {Freexs(); return(nil);}
+               continue;
+           case STRNG:
+               if(strcmp((char *)first,(char *)second)!=0)
+                   {Freexs(); return(nil);}
+               continue;
+           }
+       }
+       {Freexs(); return(tatom);}
+}
+
+/*
+ * (print 'expression ['port]) prints the given expression to the given
+ * port or poport if no port is given.  The amount of structure
+ * printed is a function of global lisp variables plevel and
+ * plength.
+ */
+lispval
+Lprint()
+{
+       register lispval handy;
+       extern int plevel,plength;
+
+
+       handy = nil;                    /* port is optional, default nil */
+       switch(np-lbot) 
+       {
+           case 2: handy = lbot[1].val;
+           case 1: break;
+           default: argerr("print");
+       }
+
+       chkrtab(Vreadtable->a.clb);
+       if(TYPE(Vprinlevel->a.clb) == INT)
+       { 
+          plevel = Vprinlevel->a.clb->i;
+       }
+       else plevel = -1;
+       if(TYPE(Vprinlength->a.clb) == INT)
+       {
+           plength = Vprinlength->a.clb->i;
+       }
+       else plength = -1;
+       printr(lbot->val,okport(handy,okport(Vpoport->a.clb,poport)));
+       return(nil);
+}
+
+/* patom does not use plevel or plength 
+ *
+ * form is (patom 'value ['port])
+ */
+lispval
+Lpatom()
+{
+       register lispval temp;
+       register lispval handy;
+       register int typ;
+       FILE *port;
+
+       handy = nil;                    /* port is optional, default nil */
+       switch(np-lbot) 
+       {
+           case 2: handy = lbot[1].val;
+           case 1: break;
+           default: argerr("patom");
+       }
+
+       temp = Vreadtable->a.clb;
+       chkrtab(temp);
+       port = okport(handy, okport(Vpoport->a.clb,stdout));
+       if ((typ= TYPE((temp = (lbot)->val))) == ATOM)
+               fputs(temp->a.pname, port);
+       else if(typ == STRNG)
+               fputs((char *)temp,port);
+       else
+       {
+               if(TYPE(Vprinlevel->a.clb) == INT)
+               {
+                   plevel = Vprinlevel->a.clb->i;
+               }
+               else plevel = -1;
+               if(TYPE(Vprinlength->a.clb) == INT)
+               {
+                   plength = Vprinlength->a.clb->i;
+               }
+               else plength = -1;
+
+               printr(temp, port);
+       }
+       return(temp);
+}
+
+/*
+ * (pntlen thing) returns the length it takes to print out
+ * an atom or number.
+ */
+
+lispval
+Lpntlen()
+{
+       return(inewint((long)Ipntlen()));
+}
+Ipntlen()
+{
+       register lispval temp;
+       register char *handy;
+
+       temp = np[-1].val;
+loop:  switch(TYPE(temp)) {
+
+       case ATOM:
+               handy = temp->a.pname;
+               break;
+
+       case STRNG:
+               handy = (char *) temp;
+               break;
+
+       case INT:
+               sprintf(strbuf,"%d",temp->i);
+               handy =strbuf;
+               break;
+
+       case DOUB:
+               sprintf(strbuf,"%g",temp->r);
+               handy =strbuf;
+               break;
+
+       default:
+               temp = error("Non atom or number to pntlen\n",TRUE);
+               goto loop;
+       }
+
+       return( strlen(handy));
+}
+#undef okport
+FILE *
+okport(arg,proper) 
+lispval arg;
+FILE *proper;
+{
+       if(TYPE(arg)!=PORT)
+               return(proper);
+       else
+               return(arg->p);
+}
diff --git a/usr/tmp/housel/franz/lam1.c b/usr/tmp/housel/franz/lam1.c
new file mode 100644 (file)
index 0000000..8ff097a
--- /dev/null
@@ -0,0 +1,971 @@
+#ifndef lint
+static char *rcsid =
+   "$Header: lam1.c,v 1.8 87/12/14 18:39:12 sklower Exp $";
+#endif
+
+/*                                     -[Fri Feb 17 16:44:24 1984 by layer]-
+ *     lam1.c                          $Locker:  $
+ * lambda functions
+ *
+ * (c) copyright 1982, Regents of the University of California
+ */
+
+# include "global.h"
+# include <sgtty.h>
+# include "chkrtab.h"
+# include "frame.h"
+
+lispval
+Leval()
+{
+       register lispval temp;
+
+       chkarg(1,"eval");
+       temp = lbot->val;
+           return(eval(temp));
+}
+
+lispval
+Lxcar()
+{      register int typ;
+       register lispval temp, result;
+
+       chkarg(1,"xcar");
+       temp = lbot->val;
+       if (((typ = TYPE(temp)) == DTPR) || (typ == ATOM) || HUNKP(temp))
+           return(temp->d.car);
+       else if(typ == SDOT) {
+               result = inewint(temp->i);
+               return(result);
+       } else if(Schainp!=nil && typ==ATOM)
+               return(nil);
+       else
+               return(error("Bad arg to car",FALSE));
+
+}
+
+lispval
+Lxcdr()
+{      register int typ;
+       register lispval temp;
+
+       chkarg(1,"xcdr");
+       temp = lbot->val;
+       if(temp==nil) return (nil);
+
+       if (((typ = TYPE(temp)) == DTPR) || HUNKP(temp)) 
+           return(temp->d.cdr);
+       else if(typ==SDOT) {
+               if(temp->s.CDR==0) return(nil);
+               temp = temp->s.CDR;
+               if(TYPE(temp)==DTPR)
+                   errorh1(Vermisc,"Fell off the end of a bignum",nil,FALSE,5,lbot->val);
+               return(temp);
+       } else if(Schainp!=nil && typ==ATOM)
+               return(nil);
+       else
+               return(error("Bad arg to cdr", FALSE));
+}
+
+lispval
+cxxr(as,ds)
+register int as,ds;
+{
+
+       register lispval temp, temp2;
+       int i, typ;
+       lispval errorh();
+
+       chkarg(1,"c{ad}+r");
+       temp = lbot->val;
+
+       for( i=0 ; i<ds ; i++)
+       {
+           if( temp != nil)
+           {
+               typ = TYPE(temp);
+               if ((typ == DTPR) || HUNKP(temp))
+                   temp = temp->d.cdr;
+               else
+                   if(typ==SDOT)
+                   {
+                       if(temp->s.CDR==0)
+                           temp = nil;
+                       else
+                           temp = temp->s.CDR;
+                       if(TYPE(temp)==DTPR)
+                           errorh1(Vermisc,"Fell off the end of a bignum",nil,FALSE,5,lbot->val);
+                   }
+               else
+                   if(Schainp!=nil && typ==ATOM)
+                       return(nil);
+               else
+                   return(errorh1(Vermisc,"Bad arg to cdr",nil,FALSE,5,temp));
+           }
+       }
+
+       for( i=0 ; i<as ; i++)
+       {
+           if( temp != nil )
+           {
+               typ = TYPE(temp);
+               if ((typ == DTPR) || HUNKP(temp))
+                   temp = temp->d.car;
+               else if(typ == SDOT)
+                       temp2 = inewint(temp->i), temp = temp2;
+               else if(Schainp!=nil && typ==ATOM)
+                   return(nil);
+               else
+                   return(errorh1(Vermisc,"Bad arg to car",nil,FALSE,5,temp));
+           }
+       }
+
+       return(temp);
+}
+
+lispval
+Lcar()
+{      return(cxxr(1,0)); }
+
+lispval
+Lcdr()
+{      return(cxxr(0,1)); }
+
+lispval
+Lcadr()
+{      return(cxxr(1,1)); }
+
+lispval
+Lcaar()
+{      return(cxxr(2,0)); }
+
+lispval
+Lc02r()
+{      return(cxxr(0,2)); }    /* cddr */
+
+lispval
+Lc12r()
+{      return(cxxr(1,2)); }    /* caddr */
+
+lispval
+Lc03r()
+{      return(cxxr(0,3)); }    /* cdddr */
+
+lispval
+Lc13r()
+{      return(cxxr(1,3)); }    /* cadddr */
+
+lispval
+Lc04r()
+{      return(cxxr(0,4)); }    /* cddddr */
+
+lispval
+Lc14r()
+{      return(cxxr(1,4)); }    /* caddddr */
+
+/*
+ *  
+ *     (nthelem num list)
+ *
+ * Returns the num'th element of the list, by doing a caddddd...ddr
+ * where there are num-1 d's. If num<=0 or greater than the length of
+ * the list, we return nil.
+ *
+ */
+
+lispval
+Lnthelem()
+{
+       register lispval temp;
+       register int i;
+
+       chkarg(2,"nthelem");
+
+       if( TYPE(temp = lbot->val) != INT)
+       return (error ("First arg to nthelem must be a fixnum",FALSE));
+
+       i = temp->i;    /* pick up the first arg */
+
+       if( i <= 0) return(nil);
+
+       ++lbot;                 /* fix lbot for call to cxxr() 'cadddd..r' */
+       temp = cxxr(1,i-1);
+       --lbot;
+
+       return(temp);
+}
+
+lispval
+Lscons()
+{
+       register struct argent *argp = lbot;
+       register lispval retp, handy;
+
+       chkarg(2,"scons");
+       retp = newsdot();
+       handy = (argp) -> val;
+       if(TYPE(handy)!=INT)
+               error("First arg to scons must be an int.",FALSE);
+       retp->s.I = handy->i;
+       handy = (argp+1)->val;
+       if(handy==nil)
+               retp->s.CDR = (lispval) 0;
+       else {
+               if(TYPE(handy)!=SDOT)
+                   error("Currently you may only link sdots to sdots.",FALSE);
+               retp->s.CDR = handy;
+       }
+       return(retp);
+}
+
+lispval
+Lbigtol(){
+       register lispval handy,newp;
+
+       chkarg(1,"Bignum-to-list");
+       handy = lbot->val;
+       while(TYPE(handy)!=SDOT)
+               handy = errorh1(Vermisc,
+                               "Non bignum argument to Bignum-to-list",
+                               nil,TRUE,5755,handy);
+       protect(newp = newdot());
+       while(handy) {
+               newp->d.car = inewint((long)handy->s.I);
+               if(handy->s.CDR==(lispval) 0) break;
+               newp->d.cdr = newdot();
+               newp = newp->d.cdr;
+               handy = handy->s.CDR;
+       }
+       handy = (--np)->val;
+       return(handy);
+}
+
+lispval
+Lcons()
+{
+       register lispval retp;
+       register struct argent *argp;
+
+       chkarg(2,"cons");
+       retp = newdot();
+       retp->d.car = ((argp = lbot) -> val);
+       retp->d.cdr = argp[1].val;
+       return(retp);
+}
+#define CA 0
+#define CD 1
+
+lispval
+rpla(what)
+int what;
+{      register struct argent *argp;
+       register int typ; register lispval first, second;
+
+       chkarg(2,"rplac[ad]");
+       argp = np-1;
+       first = (argp-1)->val;
+       while(first==nil)
+               first = error("Attempt to rplac[ad] nil.",TRUE);
+       second = argp->val;
+       if (((typ = TYPE(first)) == DTPR) || (typ == ATOM) || HUNKP(first)) {
+               if (what == CA)
+                       first->d.car = second;
+               else 
+                       first->d.cdr = second;
+               return(first);
+       }
+       if (typ==SDOT) {
+               if(what == CA) {
+                       typ = TYPE(second);
+                       if(typ!=INT) error("Rplacca of a bignum will only replace INTS",FALSE);
+                       first->s.I = second->i;
+               } else {
+                       if(second==nil)
+                               first->s.CDR = (lispval) 0;
+                       else
+                               first->s.CDR = second;
+               }
+               return(first);
+       }
+       return(error("Bad arg to rpla",FALSE));
+}
+lispval
+Lrplca()
+{      return(rpla(CA));       }
+
+lispval
+Lrplcd()
+{      return(rpla(CD));       }
+
+
+lispval
+Leq()
+{
+       register struct argent *mynp = lbot + AD;
+
+       chkarg(2,"eq");
+       if(mynp->val==(mynp+1)->val) return(tatom);
+       return(nil);
+}
+
+
+
+lispval
+Lnull()
+{      chkarg(1,"null");
+       return ((lbot->val == nil) ? tatom : nil);
+}
+
+
+
+/* Lreturn **************************************************************/
+/* Returns the first argument - which is nill if not specified.                */
+
+lispval
+Lreturn()
+{
+       if(lbot==np) protect (nil);
+       Inonlocalgo(C_RET,lbot->val,nil);
+       /* NOT REACHED */
+}
+
+
+lispval
+Linfile()
+{
+       FILE *port;
+       register lispval name;
+
+       chkarg(1,"infile");
+       name = lbot->val;
+loop:
+       name = verify(name,"infile: file name must be atom or string");
+       /* return nil if file couldnt be opened
+       if ((port = fopen((char *)name,"r")) == NULL) return(nil); */   
+
+       if ((port = fopen((char *)name,"r")) == NULL) {
+               name = errorh1(Vermisc,"Unable to open file for reading.",nil,TRUE,31,name);
+               goto loop;
+       }
+       ioname[PN(port)] = (lispval) inewstr((char *)name); /* remember name */
+       return(P(port));
+}
+
+/* outfile - open a file for writing.  
+ * 27feb81 [jkf] - modifed to accept two arguments, the second one being a
+ *   string or atom, which if it begins with an `a' tells outfile to open the
+ *   file in append mode
+ */
+lispval
+Loutfile()
+{
+       FILE *port; register lispval name;
+       char *mode ="w";    /* mode is w for create new file, a for append */
+       char *given;
+
+       if(lbot+1== np) protect(nil);
+       chkarg(2,"outfile");
+       name = lbot->val;
+       given = (char *)verify((lbot+1)->val,"Illegal file open mode.");
+       if(*given == 'a') mode = "a";
+loop:
+       name = verify(name,"Please supply atom or string name for port.");
+#ifdef os_vms
+       /*
+        *      If "w" mode, open it as a "txt" file for convenience in VMS
+        */
+       if (strcmp(mode,"w") == 0) {
+               int fd;
+
+               if ((fd = creat(name,0777,"txt")) < 0) {
+                       name = errorh1(Vermisc,"Unable to open file for writing.",nil,TRUE,31,name);
+                       goto loop;
+               }
+               port = fdopen(fd,mode);
+       } else
+#endif
+       if ((port = fopen((char *)name,mode)) == NULL) {
+               name = errorh1(Vermisc,"Unable to open file for writing.",nil,TRUE,31,name);
+               goto loop;
+       }
+       ioname[PN(port)] = (lispval) inewstr((char *)name);
+       return(P(port));
+}
+
+lispval
+Lterpr()
+{
+       register lispval handy;
+       FILE *port;
+
+       if(lbot==np) handy = nil;
+       else 
+       { 
+           chkarg(1,"terpr");
+           handy = lbot->val;
+       }
+
+       port = okport(handy,okport(Vpoport->a.clb,stdout));
+       putc('\n',port);
+       fflush(port);
+       return(nil);
+}
+
+lispval
+Lclose()
+{
+       lispval port;
+
+       chkarg(1,"close");
+       port = lbot->val;
+       if((TYPE(port))==PORT) {
+               fclose(port->p);
+               ioname[PN(port->p)] = nil;
+               return(tatom);
+       }
+       errorh1(Vermisc,"close:Non-port",nil,FALSE,987,port);
+       /* not reached */
+}
+
+lispval
+Ltruename()
+{
+    chkarg(1,"truename");
+    if(TYPE(lbot->val) != PORT)
+       errorh1(Vermisc,"truename: non port argument",nil,FALSE,0,lbot->val);
+
+    return(ioname[PN(lbot->val->p)]);
+}
+
+lispval
+Lnwritn()
+{
+       register FILE *port;
+       register value;
+       register lispval handy;
+
+       if(lbot==np) handy = nil;
+       else 
+       {
+           chkarg(1,"nwritn");
+           handy = lbot->val;
+       }
+
+       port = okport(handy,okport(Vpoport->a.clb,stdout));
+       value = port->_ptr - port->_base;
+       return(inewint(value));
+}
+
+lispval
+Ldrain()
+{
+       register FILE *port;
+       register int iodes;
+       register lispval handy;
+       struct sgttyb arg;
+
+       if(lbot==np) handy = nil;
+       else 
+       {
+           chkarg(1,"nwritn");
+           handy = lbot->val;
+       }
+       port = okport(handy, okport(Vpoport->a.clb,stdout));
+       if(port->_flag & _IOWRT) {
+               fflush(port);
+               return(nil);
+       }
+       if(! port->_flag & _IOREAD) return(nil);
+       port->_cnt = 0;
+       port->_ptr = port->_base;
+       iodes = fileno(port);
+       if(gtty(iodes,&arg) != -1) stty(iodes,&arg);
+       return(P(port));
+}
+
+lispval
+Llist()
+{
+       /* added for the benefit of mapping functions. */
+       register struct argent *ulim, *namptr;
+       register lispval temp, result;
+       Savestack(4);
+
+       ulim = np;
+       namptr = lbot + AD;
+       temp = result = (lispval) np;
+       protect(nil);
+       for(; namptr < ulim;) {
+               temp = temp->l = newdot();
+               temp->d.car = (namptr++)->val;
+       }
+       temp->l = nil;
+       Restorestack();
+       return(result->l);
+}
+
+lispval
+Lnumberp()
+{
+       chkarg(1,"numberp");
+       switch(TYPE(lbot->val)) {
+       case INT: case DOUB: case SDOT:
+               return(tatom);
+       }
+       return(nil);
+}
+
+lispval
+Latom()
+{
+       register struct argent *lb = lbot;
+       chkarg(1,"atom");
+       if(TYPE(lb->val)==DTPR || (HUNKP(lb->val)))
+               return(nil);
+       else
+               return(tatom);
+}
+
+lispval
+Ltype()
+{
+       chkarg(1,"type");
+       switch(TYPE(lbot->val)) {
+       case INT:
+               return(int_name);
+       case ATOM:
+               return(atom_name);
+       case SDOT:
+               return(sdot_name);
+       case DOUB:
+               return(doub_name);
+       case DTPR:
+               return(dtpr_name);
+       case STRNG:
+               return(str_name);
+       case ARRAY:
+               return(array_name);
+       case BCD:
+               return(funct_name);
+       case OTHER:
+               return(other_name);
+
+       case HUNK2:
+               return(hunk_name[0]);
+       case HUNK4:
+               return(hunk_name[1]);
+       case HUNK8:
+               return(hunk_name[2]);
+       case HUNK16:
+               return(hunk_name[3]);
+       case HUNK32:
+               return(hunk_name[4]);
+       case HUNK64:
+               return(hunk_name[5]);
+       case HUNK128:
+               return(hunk_name[6]);
+               
+       case VECTOR:
+               return(vect_name);
+       case VECTORI:
+               return(vecti_name);
+
+       case VALUE:
+               return(val_name);
+       case PORT:
+               return(port_name);
+       }
+       return(nil);
+}
+
+lispval
+Ldtpr()
+{
+       chkarg(1,"dtpr");
+       return(typred(DTPR, lbot->val));
+}
+
+lispval
+Lbcdp()
+{
+       chkarg(1,"bcdp");
+       return(typred(BCD, lbot->val));
+}
+
+lispval
+Lportp()
+{
+       chkarg(1,"portp");
+       return(typred(PORT, lbot->val));
+}
+
+lispval
+Larrayp()
+{
+       chkarg(1,"arrayp");
+       return(typred(ARRAY, lbot->val));
+}
+
+/*
+ *     (hunkp 'g_arg1)
+ * Returns t if g_arg1 is a hunk, otherwise returns nil.
+ */
+
+lispval
+Lhunkp()
+{
+       chkarg(1,"hunkp");
+       if (HUNKP(lbot->val))
+               return(tatom);          /* If a hunk, return t */
+       else
+               return(nil);            /* else nil */
+}
+
+lispval
+Lset()
+{
+       lispval varble;
+
+       chkarg(2,"set");
+       varble = lbot->val;
+       switch(TYPE(varble))
+               {
+       case ATOM:      return(varble->a.clb = lbot[1].val);
+
+       case VALUE:     return(varble->l = lbot[1].val);
+               }
+
+       error("IMPROPER USE OF SET",FALSE);
+       /* NOTREACHED */
+}
+
+lispval
+Lequal()
+{
+       register lispval first, second;
+       register type1, type2;
+       lispval Lsub(),Lzerop();
+       long *oldsp;
+       Keepxs();
+       chkarg(2,"equal");
+
+
+       if(lbot->val==lbot[1].val) return(tatom);
+
+       oldsp=sp(); stack((long)lbot->val);stack((long)lbot[1].val);
+       for(;oldsp > sp();) {
+
+           first = (lispval) unstack(); second = (lispval) unstack();
+    again:
+           if(first==second) continue;
+
+           type1=TYPE(first); type2=TYPE(second);
+           if(type1!=type2) {
+               if((type1==SDOT&&type2==INT)||(type1==INT&&type2==SDOT))
+                   goto dosub;
+               {Freexs(); return(nil);}
+           }
+           switch(type1) {
+           case DTPR:
+               stack((long)first->d.cdr); stack((long)second->d.cdr);
+               first = first->d.car; second = second->d.car;
+               goto again;
+           case DOUB:
+               if(first->r!=second->r)
+                   {Freexs(); return(nil);}
+               continue;
+           case INT:
+               if(first->i!=second->i)
+                   {Freexs(); return(nil);}
+               continue;
+           case VECTOR:
+               if(!vecequal(first,second)) {Freexs(); return(nil);}
+               continue;
+           case VECTORI:
+               if(!veciequal(first,second)) {Freexs(); return(nil);}
+               continue;
+    dosub:
+           case SDOT: {
+               lispval temp;
+               struct argent *OLDlbot = lbot;
+               lbot = np;
+               np++->val = first;
+               np++->val = second;
+               temp = Lsub();
+               np = lbot;
+               lbot = OLDlbot;
+               if(TYPE(temp)!=INT || temp->i!=0)
+                   {Freexs(); return(nil);}
+               }
+               continue;
+           case VALUE:
+               if(first->l!=second->l)
+                   {Freexs(); return(nil);}
+               continue;
+           case STRNG:
+               if(strcmp((char *)first,(char *)second)!=0)
+                   {Freexs(); return(nil);}
+               continue;
+
+           default:
+               {Freexs(); return(nil);}
+           }
+       }
+       {Freexs(); return(tatom);}
+}
+lispval
+oLequal()
+{
+       chkarg(2,"equal");
+
+       if( lbot[1].val == lbot->val ) return(tatom);
+       if(Iequal(lbot[1].val,lbot->val)) return(tatom); else return(nil);
+}
+
+Iequal(first,second) 
+register lispval first, second;
+{
+       register type1, type2;
+       lispval Lsub(),Lzerop();
+
+       if(first==second)
+               return(1);
+       type1=TYPE(first);
+       type2=TYPE(second);
+       if(type1!=type2) {
+               if((type1==SDOT&&type2==INT)||(type1==INT&&type2==SDOT))
+                       goto dosub;
+               return(0);
+       }
+       switch(type1) {
+       case DTPR:
+                return(
+                       Iequal(first->d.car,second->d.car) &&
+                       Iequal(first->d.cdr,second->d.cdr) );
+       case DOUB:
+               return(first->r==second->r);
+       case INT:
+               return( (first->i==second->i));
+dosub:
+       case SDOT:
+       {
+               lispval temp;
+               struct argent *OLDlbot = lbot;
+               lbot = np;
+               np++->val = first;
+               np++->val = second;
+               temp = Lsub();
+               np = lbot;
+               lbot = OLDlbot;
+               return(TYPE(temp)==INT&& temp->i==0);
+       }
+       case VALUE:
+               return( first->l==second->l );
+       case STRNG:
+               return(strcmp((char *)first,(char *)second)==0);
+       }
+       return(0);
+}
+lispval
+Zequal()
+{
+       register lispval first, second;
+       register type1, type2;
+       lispval Lsub(),Lzerop();
+       long *oldsp;
+       Keepxs();
+       chkarg(2,"equal");
+
+
+       if(lbot->val==lbot[1].val) return(tatom);
+
+       oldsp=sp(); stack((long)lbot->val);stack((long)lbot[1].val);
+
+       for(;oldsp > sp();) {
+
+           first = (lispval) unstack(); second = (lispval) unstack();
+    again:
+           if(first==second) continue;
+
+           type1=TYPE(first); type2=TYPE(second);
+           if(type1!=type2) {
+               if((type1==SDOT&&type2==INT)||(type1==INT&&type2==SDOT))
+                   goto dosub;
+               {Freexs(); return(nil);}
+           }
+           switch(type1) {
+           case DTPR:
+               stack((long)first->d.cdr); stack((long)second->d.cdr);
+               first = first->d.car; second = second->d.car;
+               goto again;
+           case DOUB:
+               if(first->r!=second->r)
+                   {Freexs(); return(nil);}
+               continue;
+           case INT:
+               if(first->i!=second->i)
+                   {Freexs(); return(nil);}
+               continue;
+    dosub:
+           case SDOT:
+           {
+               lispval temp;
+               struct argent *OLDlbot = lbot;
+               lbot = np;
+               np++->val = first;
+               np++->val = second;
+               temp = Lsub();
+               np = lbot;
+               lbot = OLDlbot;
+               if(TYPE(temp)!=INT || temp->i!=0)
+                   {Freexs(); return(nil);}
+           }
+               continue;
+           case VALUE:
+               if(first->l!=second->l)
+                   {Freexs(); return(nil);}
+               continue;
+           case STRNG:
+               if(strcmp((char *)first,(char *)second)!=0)
+                   {Freexs(); return(nil);}
+               continue;
+           }
+       }
+       {Freexs(); return(tatom);}
+}
+
+/*
+ * (print 'expression ['port]) prints the given expression to the given
+ * port or poport if no port is given.  The amount of structure
+ * printed is a function of global lisp variables plevel and
+ * plength.
+ */
+lispval
+Lprint()
+{
+       register lispval handy;
+       extern int plevel,plength;
+
+
+       handy = nil;                    /* port is optional, default nil */
+       switch(np-lbot) 
+       {
+           case 2: handy = lbot[1].val;
+           case 1: break;
+           default: argerr("print");
+       }
+
+       chkrtab(Vreadtable->a.clb);
+       if(TYPE(Vprinlevel->a.clb) == INT)
+       { 
+          plevel = Vprinlevel->a.clb->i;
+       }
+       else plevel = -1;
+       if(TYPE(Vprinlength->a.clb) == INT)
+       {
+           plength = Vprinlength->a.clb->i;
+       }
+       else plength = -1;
+       printr(lbot->val,okport(handy,okport(Vpoport->a.clb,poport)));
+       return(nil);
+}
+
+/* patom does not use plevel or plength 
+ *
+ * form is (patom 'value ['port])
+ */
+lispval
+Lpatom()
+{
+       register lispval temp;
+       register lispval handy;
+       register int typ;
+       FILE *port;
+
+       handy = nil;                    /* port is optional, default nil */
+       switch(np-lbot) 
+       {
+           case 2: handy = lbot[1].val;
+           case 1: break;
+           default: argerr("patom");
+       }
+
+       temp = Vreadtable->a.clb;
+       chkrtab(temp);
+       port = okport(handy, okport(Vpoport->a.clb,stdout));
+       if ((typ= TYPE((temp = (lbot)->val))) == ATOM)
+               fputs(temp->a.pname, port);
+       else if(typ == STRNG)
+               fputs((char *)temp,port);
+       else
+       {
+               if(TYPE(Vprinlevel->a.clb) == INT)
+               {
+                   plevel = Vprinlevel->a.clb->i;
+               }
+               else plevel = -1;
+               if(TYPE(Vprinlength->a.clb) == INT)
+               {
+                   plength = Vprinlength->a.clb->i;
+               }
+               else plength = -1;
+
+               printr(temp, port);
+       }
+       return(temp);
+}
+
+/*
+ * (pntlen thing) returns the length it takes to print out
+ * an atom or number.
+ */
+
+lispval
+Lpntlen()
+{
+       return(inewint((long)Ipntlen()));
+}
+Ipntlen()
+{
+       register lispval temp;
+       register char *handy;
+
+       temp = np[-1].val;
+loop:  switch(TYPE(temp)) {
+
+       case ATOM:
+               handy = temp->a.pname;
+               break;
+
+       case STRNG:
+               handy = (char *) temp;
+               break;
+
+       case INT:
+               sprintf(strbuf,"%d",temp->i);
+               handy =strbuf;
+               break;
+
+       case DOUB:
+               sprintf(strbuf,"%g",temp->r);
+               handy =strbuf;
+               break;
+
+       default:
+               temp = error("Non atom or number to pntlen\n",TRUE);
+               goto loop;
+       }
+
+       return( strlen(handy));
+}
+#undef okport
+FILE *
+okport(arg,proper) 
+lispval arg;
+FILE *proper;
+{
+       if(TYPE(arg)!=PORT)
+               return(proper);
+       else
+               return(arg->p);
+}