BSD 1 development
authorBill Joy <wnj@ucbvax.Berkeley.EDU>
Tue, 6 Dec 1977 19:08:59 +0000 (11:08 -0800)
committerBill Joy <wnj@ucbvax.Berkeley.EDU>
Tue, 6 Dec 1977 19:08:59 +0000 (11:08 -0800)
Work on file pxp/subr.c
Work on file pxp/nl.c

Synthesized-from: 1bsd

pxp/nl.c [new file with mode: 0644]
pxp/subr.c [new file with mode: 0644]

diff --git a/pxp/nl.c b/pxp/nl.c
new file mode 100644 (file)
index 0000000..32dfe61
--- /dev/null
+++ b/pxp/nl.c
@@ -0,0 +1,577 @@
+#
+/*
+ * pi - Pascal interpreter code translator
+ *
+ * Charles Haley, Bill Joy UCB
+ * Version 1.0 August 1977
+ */
+
+#include "whoami"
+#include "0.h"
+#include "opcode.h"
+
+#ifdef PI
+/*
+ * Array of information about pre-defined, block 0 symbols.
+ */
+int    *biltins[] {
+
+       /*
+        * Types
+        */
+       "boolean",
+       "char",
+       "integer",
+       "real",
+       "_nil",         /* dummy name */
+       0,
+
+       /*
+        * Ranges
+        */
+       TINT,           0177777, 0177600, 0, 0177,
+       TINT,           0177777, 0100000, 0, 077777,
+       TINT,           0100000, 0, 077777, 0177777,
+       TCHAR,          0, 0, 0, 127,
+       TBOOL,          0, 0, 0, 1,
+       TDOUBLE,        0, 0, 0, 0,             /* fake for reals */
+       0,
+
+       /*
+        * Built-in composite types
+        */
+       "Boolean",
+       "intset",
+       "alfa",
+       "text",
+       "input", 
+       "output", 
+
+       /*
+        * Built-in constants
+        */
+       "true",         TBOOL,  1, 0,
+       "false",        TBOOL,  0, 0,
+       "minint",       T4INT,  0100000, 0,
+       "maxint",       T4INT,  077777, 0177777,
+       "minchar",      T1CHAR, 0, 0,
+       "maxchar",      T1CHAR, 0177, 0,
+       "bell",         T1CHAR, 07, 0,
+       "tab",          T1CHAR, 011, 0,
+       0,
+
+       /*
+        * Built-in functions
+        */
+       "abs",          O_ABS2,
+       "arctan",       O_ATAN,
+       "card",         O_CARD|NSTAND,
+       "chr",          O_CHR2,
+       "clock",        O_CLCK|NSTAND,
+       "cos",          O_COS,
+       "eof",          O_EOF,
+       "eoln",         O_EOLN,
+       "eos",          0,
+       "exp",          O_EXP,
+       "expo",         O_EXPO|NSTAND,
+       "ln",           O_LN,
+       "odd",          O_ODD2,
+       "ord",          O_ORD2,
+       "pred",         O_PRED2,
+       "round",        O_ROUND,
+       "sin",          O_SIN,
+       "sqr",          O_SQR2,
+       "sqrt",         O_SQRT,
+       "succ",         O_SUCC2,
+       "trunc",        O_TRUNC,
+       "undefined",    O_UNDEF|NSTAND,
+       /*
+        * UNIX extensions
+        */
+       "argc",         O_ARGC|NSTAND,
+       "random",       O_RANDOM|NSTAND,
+       "seed",         O_SEED|NSTAND,
+       "wallclock",    O_WCLCK|NSTAND,
+       "sysclock",     O_SCLCK|NSTAND,
+       0,
+
+       /*
+        * Built-in procedures
+        */
+       "date",         O_DATE|NSTAND,
+       "flush",        O_FLUSH|NSTAND,
+       "get",          O_GET,
+       "getseg",       0,
+       "halt",         O_HALT|NSTAND,
+       "linelimit",    O_LLIMIT|NSTAND,
+       "message",      O_MESSAGE|NSTAND,
+       "new",          O_NEW,
+       "pack",         O_PACK,
+       "page",         O_PAGE,
+       "put",          O_PUT,
+       "putseg",       0,
+       "read",         O_READ4,
+       "readln",       O_READLN,
+       "remove",       O_REMOVE|NSTAND,
+       "reset",        O_RESET,
+       "rewrite",      O_REWRITE,
+       "time",         O_TIME|NSTAND,
+       "unpack",       O_UNPACK,
+       "write",        O_WRIT2,
+       "writeln",      O_WRITLN,
+       /*
+        * UNIX extensions
+        */
+       "argv",         O_ARGV|NSTAND,
+       "null",         O_NULL|NSTAND,
+       "stlimit",      O_STLIM|NSTAND,
+       0,
+};
+\f
+/*
+ * NAMELIST SEGMENT DEFINITIONS
+ */
+struct nls {
+       struct nl *nls_low;
+       struct nl *nls_high;
+} ntab[MAXNL], *nlact;
+
+struct nl nl[INL];
+struct nl *nlp nl;
+struct nls *nlact ntab;
+/*
+ * Initnl initializes the first namelist segment and then
+ * uses the array biltins to initialize the name list for
+ * block 0.
+ */
+initnl()
+{
+       register int *q;
+       register struct nl *p;
+       register int i;
+
+       ntab[0].nls_low = nl;
+       ntab[0].nls_high = &nl[INL];
+       defnl(0, 0, 0, 0);
+       /*
+        * Fundamental types
+        */
+       for (q = biltins; *q != 0; q++)
+               hdefnl(*q, TYPE, nlp, 0);
+       q++;
+
+       /*
+        * Ranges
+        */
+       while (*q) {
+               p = defnl(0, RANGE, nl+*q, 0);
+               nl[*q++].type = p;
+               for (i = 0; i < 4; i++)
+                       p->value[i] = *q++;
+       }
+       q++;
+
+       /*
+        * Pre-defined composite types
+        */
+       hdefnl(*q++, TYPE, nl+T1BOOL, 0);
+       enter(defnl((intset = *q++), TYPE, nlp+1, 0));
+       defnl(0, SET, nlp+1, 0);
+       defnl(0, RANGE, nl+TINT, 0)->value[3] = 127;
+     p=        defnl(0, RANGE, nl+TINT, 0);
+       p->value[1] = 1;
+       p->value[3] = 10;
+       defnl(0, ARRAY, nl+T1CHAR, 1)->chain = p;
+       hdefnl(*q++, TYPE, nlp-1, 0);   /* "alfa" */
+       hdefnl(*q++, TYPE, nlp+1, 0);   /* "text" */
+     p=        defnl(0, FILE, nl+T1CHAR, 0);
+       p->nl_flags =| NFILES;
+       input = hdefnl(*q++, VAR, p, -2);       /* "input" */
+       output = hdefnl(*q++, VAR, p, -4);      /* "output" */
+
+       /*
+        * Pre-defined constants
+        */
+       for (; *q; q =+ 4)
+               hdefnl(q[0], CONST, nl+q[1], q[2])->value[1] = q[3];
+
+       /*
+        * Built-in procedures and functions
+        */
+       for (q++; *q; q =+ 2)
+               hdefnl(q[0], FUNC, 0, q[1]);
+       for (q++; *q; q =+ 2)
+               hdefnl(q[0], PROC, 0, q[1]);
+
+}
+
+hdefnl(sym, cls, typ, val)
+{
+       register struct nl *p;
+
+       if (sym)
+               hash(sym, 0);
+       p = defnl(sym, cls, typ, val);
+       if (sym)
+               enter(p);
+       return (p);
+}
+
+/*
+ * Free up the name list segments
+ * at the end of a statement/proc/func
+ * All segments are freed down to the one in which
+ * p points.
+ */
+nlfree(p)
+       struct nl *p;
+{
+
+       nlp = p;
+       while (nlact->nls_low > nlp || nlact->nls_high < nlp) {
+               free(nlact->nls_low);
+               nlact->nls_low = NIL;
+               nlact->nls_high = NIL;
+               --nlact;
+               if (nlact < &ntab[0])
+                       panic("nlfree");
+       }
+}
+#endif
+\f
+char   VARIABLE[]      "variable";
+
+char   *classes[] {
+       "undefined",
+       "constant",
+       "type",
+       VARIABLE,
+       "array",
+       "pointer or file",
+       "record",
+       "field",
+       "procedure",
+       "function",
+       VARIABLE,
+       VARIABLE,
+       "pointer",
+       "file",
+       "set",
+       "subrange",
+       "label",
+       "withptr",
+       "scalar",
+       "string",
+       "program",
+       "improper",
+#ifdef DEBUG
+       "variant",
+#endif
+};
+
+char   snark[] "SNARK";
+
+#ifdef PI
+#ifdef DEBUG
+char   *ctext[]
+{
+       "BADUSE",
+       "CONST",
+       "TYPE",
+       "VAR",
+       "ARRAY",
+       "PTRFILE",
+       "RECORD",
+       "FIELD",
+       "PROC",
+       "FUNC",
+       "FVAR",
+       "REF",
+       "PTR",
+       "FILE",
+       "SET",
+       "RANGE",
+       "LABEL",
+       "WITHPTR",
+       "SCAL",
+       "STR",
+       "PROG",
+       "IMPROPER",
+       "VARNT"
+};
+
+char   *stars  "\t***";
+
+/*
+ * Dump the namelist from the
+ * current nlp down to 'to'.
+ * All the namelist is dumped if
+ * to is NIL.
+ */
+dumpnl(to, rout)
+       struct nl *to;
+{
+       register struct nl *p;
+       register int j;
+       struct nls *nlsp;
+       int i, v, head;
+
+       if (opt('y') == 0)
+               return;
+       if (to != NIL)
+               printf("\n\"%s\" Block=%d\n", rout, cbn);
+       nlsp = nlact;
+       head = NIL;
+       for (p = nlp; p != to;) {
+               if (p == nlsp->nls_low) {
+                       if (nlsp == &ntab[0])
+                               break;
+                       nlsp--;
+                       p = nlsp->nls_high;
+               }
+               p--;
+               if (head == NIL) {
+                       printf("\tName\tClass  Bn+Flags\tType\tVal\tChn\n");
+                       head++;
+               }
+               printf("%3d:", nloff(p));
+               if (p->symbol)
+                       printf("\t%.7s", p->symbol);
+               else
+                       printf(stars);
+               if (p->class)
+                       printf("\t%s", ctext[p->class]);
+               else
+                       printf(stars);
+               if (p->nl_flags) {
+                       putchar('\t');
+                       if (p->nl_flags & 037)
+                               printf("%d ", p->nl_flags & 037);
+                       if (p->nl_flags & NMOD)
+                               putchar('M');
+                       if (p->nl_flags & NUSED)
+                               putchar('U');
+                       if (p->nl_flags & NFILES)
+                               putchar('F');
+               } else
+                       printf(stars);
+               if (p->type)
+                       printf("\t[%d]", nloff(p->type));
+               else
+                       printf(stars);
+               v = p->value[0];
+               switch (p->class) {
+                       case TYPE:
+                               break;
+                       case VARNT:
+                               goto con;
+                       case CONST:
+                               switch (nloff(p->type)) {
+                                       default:
+                                               printf("\t%d", v);
+                                               break;
+                                       case TDOUBLE:
+                                               printf("\t%f", p->real);
+                                               break;
+                                       case TINT:
+con:
+                                               printf("\t%ld", p->range[0]);
+                                               break;
+                                       case TSTR:
+                                               printf("\t'%s'", v);
+                                               break;
+                                       }
+                               break;
+                       case VAR:
+                       case REF:
+                       case WITHPTR:
+                               printf("\t%d,%d", cbn, v);
+                               break;
+                       case SCAL:
+                       case RANGE:
+                               printf("\t%ld..%ld", p->range[0], p->range[1]);
+                               break;
+                       case RECORD:
+                               printf("\t%d(%d)", v, p->value[NL_FLDSZ]);
+                               break;
+                       case FIELD:
+                               printf("\t%d", v);
+                               break;
+                       case STR:
+                               printf("\t\"%s\"", p->value[1]);
+                               goto casedef;
+                       case FVAR:
+                       case FUNC:
+                       case PROC:
+                       case PROG:
+                               if (cbn == 0) {
+                                       printf("\t<%o>", p->value[0] & 0377);
+                                       if (p->value[0] & NSTAND)
+                                               printf("\tNSTAND");
+                                       break;
+                               }
+                               v = p->value[1];
+                       default:
+casedef:
+                               if (v)
+                                       printf("\t<%d>", v);
+                               else
+                                       printf(stars);
+               }
+               if (p->chain)
+                       printf("\t[%d]", nloff(p->chain));
+               switch (p->class) {
+                       case RECORD:
+                               if (p->value[NL_VARNT])
+                                       printf("\tVARNT=[%d]", nloff(p->value[NL_VARNT]));
+                               if (p->value[NL_TAG])
+                                       printf(" TAG=[%d]", nloff(p->value[NL_TAG]));
+                               break;
+                       case VARNT:
+                               printf("\tVTOREC=[%d]", nloff(p->value[NL_VTOREC]));
+                               break;
+               }
+               putchar('\n');
+       }
+       if (head == 0)
+               printf("\tNo entries\n");
+}
+#endif
+
+\f
+/*
+ * Define a new name list entry
+ * with initial symbol, class, type
+ * and value[0] as given.  A new name
+ * list segment is allocated to hold
+ * the next name list slot if necessary.
+ */
+defnl(sym, cls, typ, val)
+       char *sym;
+       int cls;
+       struct nl *typ;
+       int val;
+{
+       register struct nl *p;
+       register int *q, i;
+       char *cp;
+
+       p = nlp;
+
+       /*
+        * Zero out this entry
+        */
+       q = p;
+       i = (sizeof *p)/2;
+       do
+               *q++ = 0;
+       while (--i);
+
+       /*
+        * Insert the values
+        */
+       p->symbol = sym;
+       p->class = cls;
+       p->type = typ;
+       p->nl_block = cbn;
+       p->value[0] = val;
+
+       /*
+        * Insure that the next namelist
+        * entry actually exists. This is
+        * really not needed here, it would
+        * suffice to do it at entry if we
+        * need the slot.  It is done this
+        * way because, historically, nlp
+        * always pointed at the next namelist
+        * slot.
+        */
+       nlp++;
+       if (nlp >= nlact->nls_high) {
+               i = NLINC;
+               cp = alloc(NLINC * sizeof *nlp);
+               if (cp == -1) {
+                       i = NLINC / 2;
+                       cp = alloc((NLINC / 2) * sizeof *nlp);
+               }
+               if (cp == -1) {
+                       error("Ran out of memory (defnl)");
+                       pexit(DIED);
+               }
+               nlact++;
+               if (nlact >= &ntab[MAXNL]) {
+                       error("Ran out of name list tables");
+                       pexit(DIED);
+               }
+               nlp = cp;
+               nlact->nls_low = nlp;
+               nlact->nls_high = nlact->nls_low + i;
+       }
+       return (p);
+}
+
+/*
+ * Make a duplicate of the argument
+ * namelist entry for, e.g., type
+ * declarations of the form 'type a = b'
+ * and array indicies.
+ */
+nlcopy(p)
+       struct nl *p;
+{
+       register int *p1, *p2, i;
+
+       p1 = p;
+       p = p2 = defnl(0, 0, 0, 0);
+       i = (sizeof *p)/2;
+       do
+               *p2++ = *p1++;
+       while (--i);
+       return (p);
+}
+
+/*
+ * Compute a namelist offset
+ */
+nloff(p)
+       struct nl *p;
+{
+
+       return (p - nl);
+}
+\f
+/*
+ * Enter a symbol into the block
+ * symbol table.  Symbols are hashed
+ * 64 ways based on low 6 bits of the
+ * character pointer into the string
+ * table.
+ */
+enter(np)
+       struct nl *np;
+{
+       register struct nl *rp, *hp;
+       register struct nl *p;
+       int i;
+
+       rp = np;
+       if (rp == NIL)
+               return (NIL);
+       if (cbn > 0)
+               if (rp->symbol == input->symbol || rp->symbol == output->symbol)
+                       error("Pre-defined files input and output must not be redefined");
+       i = rp->symbol;
+       i =& 077;
+       hp = disptab[i];
+       if (rp->class != BADUSE && rp->class != FIELD)
+       for (p = hp; p != NIL && (p->nl_block & 037) == cbn; p = p->nl_next)
+               if (p->symbol == rp->symbol && p->class != BADUSE && p->class != FIELD) {
+                       error("%s is already defined in this block", rp->symbol);
+                       break;
+
+               }
+       rp->nl_next = hp;
+       disptab[i] = rp;
+       return (rp);
+}
+#endif
diff --git a/pxp/subr.c b/pxp/subr.c
new file mode 100644 (file)
index 0000000..189604f
--- /dev/null
@@ -0,0 +1,209 @@
+#include "whoami"
+/*
+ * pi - Pascal interpreter code translator
+ *
+ * Charles Haley, Bill Joy UCB
+ * Version 1.0 August 1977
+ *
+ *
+ * pxp - Pascal execution profiler
+ *
+ * Bill Joy UCB
+ * Version 1.0 August 1977
+ */
+
+#include "0.h"
+
+/*
+ * Does the string fp end in '.' and the character c ?
+ */
+dotted(fp, c)
+       register char *fp;
+       char c;
+{
+       register int i;
+
+       i = strlen(fp);
+       return (i > 1 && fp[i - 2] == '.' && fp[i - 1] == c);
+}
+
+/*
+ * Toggle the option c.
+ */
+togopt(c)
+       char c;
+{
+       register char *tp;
+
+       tp = &opts[c-'a'];
+       *tp = 1 - *tp;
+}
+
+/*
+ * Set the time vector "tvec" to the
+ * modification time stamp of the current file.
+ */
+gettime()
+{
+       int stbuf[18];
+
+       stat(filename, stbuf);
+       tvec[0] = stbuf[16];
+       tvec[1] = stbuf[17];
+}
+
+/*
+ * Convert a "ctime" into a Pascal styple time line
+ */
+myctime(tv)
+       int *tv;
+{
+       register char *cp, *dp;
+       char *cpp;
+       register i;
+       static char mycbuf[26];
+
+       cpp = ctime(tv);
+       dp = mycbuf;
+       cp = cpp;
+       cpp[16] = 0;
+       while (*dp++ = *cp++);
+       dp--;
+       cp = cpp+19;
+       cpp[24] = 0;
+       while (*dp++ = *cp++);
+       return (mycbuf);
+}
+
+/*
+ * Is "fp" in the command line list of names ?
+ */
+inpflist(fp)
+       char *fp;
+{
+       register i, *pfp;
+
+       pfp = pflist;
+       for (i = pflstc; i > 0; i--)
+               if (strcmp(fp, *pfp++) == 0)
+                       return (1);
+       return (0);
+}
+
+extern int errno;
+extern char *sys_errlist[];
+
+/*
+ * Boom!
+ */
+Perror(file, error)
+       char *file, *error;
+{
+
+       errno = 0;
+       sys_errlist[0] = error;
+       perror(file);
+}
+
+calloc(num, size)
+       int num, size;
+{
+       register int p1, *p2, nbyte;
+
+       nbyte = (num*size+1) & ~01;
+       if ((p1 = alloc(nbyte)) == -1 || p1==0)
+               return (-1);
+       p2 = p1;
+       nbyte =>> 1;            /* 2 bytes/word */
+       do {
+               *p2++ = 0;
+       } while (--nbyte);
+       return (p1);
+}
+
+/*
+ * Compare strings:  s1>s2: >0  s1==s2: 0  s1<s2: <0
+ */
+strcmp(s1, s2)
+       register char *s1, *s2;
+{
+
+       while (*s1 == *s2++)
+               if (*s1++=='\0')
+                       return (0);
+       return (*s1 - *--s2);
+}
+
+/*
+ * Copy string s2 to s1.
+ * S1 must be large enough.
+ * Return s1.
+ */
+strcpy(s1, s2)
+       register char *s1, *s2;
+{
+       register os1;
+
+       os1 = s1;
+       while (*s1++ = *s2++)
+               continue;
+       return (os1);
+}
+
+/*
+ * Strlen is currently a freebie of perror
+ * Take the length of a string.
+ * Note that this does not include the trailing null!
+strlen(cp)
+       register char *cp;
+{
+       register int i;
+
+       for (i = 0; *cp != 0; cp++)
+               i++;
+       return (i);
+}
+ */
+copy(to, from, bytes)
+       register char *to, *from;
+       register int bytes;
+{
+
+       if (bytes != 0)
+               do
+                       *to++ = *from++;
+               while (--bytes);
+}
+
+/*
+ * Is ch one of the characters in the string cp ?
+ */
+any(cp, ch)
+       register char *cp;
+       char ch;
+{
+
+       while (*cp)
+               if (*cp++ == ch)
+                       return (1);
+       return (0);
+}
+
+opush(c)
+       register CHAR c;
+{
+
+       c =- 'a';
+       optstk[c] =<< 1;
+       optstk[c] =| opts[c];
+       opts[c] = 1;
+}
+
+opop(c)
+       register CHAR c;
+{
+
+       c =- 'a';
+       opts[c] = optstk[c] & 1;
+       optstk[c] =>> 1;
+}