BSD 3 development
authorCharles B. Haley <cbh@research.uucp>
Thu, 1 Nov 1979 04:30:39 +0000 (20:30 -0800)
committerCharles B. Haley <cbh@research.uucp>
Thu, 1 Nov 1979 04:30:39 +0000 (20:30 -0800)
Work on file usr/src/cmd/pi/yyget.c
Work on file usr/src/cmd/pi/yyid.c
Work on file usr/src/cmd/pi/yylex.c
Work on file usr/src/cmd/pi/yyoptions.c
Work on file usr/src/cmd/pi/yypanic.c
Work on file usr/src/cmd/pi/yyparse.c
Work on file usr/src/cmd/pi/yyprint.c

Co-Authored-By: Bill Joy <wnj@ucbvax.Berkeley.EDU>
Co-Authored-By: Ken Thompson <ken@research.uucp>
Synthesized-from: 3bsd

usr/src/cmd/pi/yyget.c [new file with mode: 0644]
usr/src/cmd/pi/yyid.c [new file with mode: 0644]
usr/src/cmd/pi/yylex.c [new file with mode: 0644]
usr/src/cmd/pi/yyoptions.c [new file with mode: 0644]
usr/src/cmd/pi/yypanic.c [new file with mode: 0644]
usr/src/cmd/pi/yyparse.c [new file with mode: 0644]
usr/src/cmd/pi/yyprint.c [new file with mode: 0644]

diff --git a/usr/src/cmd/pi/yyget.c b/usr/src/cmd/pi/yyget.c
new file mode 100644 (file)
index 0000000..13ca068
--- /dev/null
@@ -0,0 +1,342 @@
+/* Copyright (c) 1979 Regents of the University of California */
+#
+/*
+ * pi - Pascal interpreter code translator
+ *
+ * Charles Haley, Bill Joy UCB
+ * Version 1.1 February 1978
+ *
+ *
+ * pxp - Pascal execution profiler
+ *
+ * Bill Joy UCB
+ * Version 1.1 February 1978
+ */
+
+#include "whoami"
+#include "0.h"
+#include "yy.h"
+
+#ifdef PXP
+int    yytokcnt;
+#endif
+
+/*
+ * Readch returns the next
+ * character from the current
+ * input line or -1 on end-of-file.
+ * It also maintains yycol for use in
+ * printing error messages.
+ */
+readch()
+{
+       register i, c;
+
+       if (*bufp == '\n' && bufp >= charbuf) {
+#ifdef PXP
+               yytokcnt = 0;
+#endif
+               if (getline() < 0)
+                       return (-1);
+       }
+       c = *++bufp;
+       if (c == '\t')
+               yycol = ((yycol + 8) & ~7);
+       else
+               yycol++;
+       return (c);
+}
+\f
+/*
+ * Definitions of the structures used for the
+ * include facility.  The variable "ibp" points
+ * to the getc buffer of the current input file.
+ * There are "inclev + 1" current include files,
+ * and information in saved in the incs stack
+ * whenever a new level of include nesting occurs.
+ *
+ * Ibp in the incs structure saves the pointer
+ * to the previous levels input buffer;
+ * filename saves the previous file name;
+ * Printed saves whether the previous file name
+ * had been printed before this nesting occurred;
+ * and yyline is the line we were on on the previous file.
+ */
+
+#define        MAXINC  10
+
+struct inc {
+       FILE    *ibp;
+       char    *filename;
+       int     Printed;
+       int     yyline;
+       int     yyLinpt;
+} incs[MAXINC];
+
+extern char *printed;
+
+int    inclev  = -1;
+
+#ifdef PXP
+/*
+ * These initializations survive only if
+ * pxp is asked to pretty print one file.
+ * Otherwise they are destroyed by the initial
+ * call to getline.
+ */
+char   charbuf[CBSIZE] = " program x(output);\n";
+int    yycol = 8;
+char   *bufp = charbuf;
+
+#endif
+/*
+ * YyLinpt is the seek pointer to the beginning of the
+ * next line in the file.
+ */
+int    yyLinpt;
+\f
+/*
+ * Getline places the next line
+ * from the input stream in the
+ * line buffer, returning -1 at YEOF.
+ */
+getline()
+{
+       register char *cp;
+       register CHAR c;
+#ifdef PXP
+       static char ateof;
+#endif
+       register FILE *ib;
+       int i;
+
+       if (opt('l') && yyprtd == 0)
+               yyoutline();
+       yyprtd = 0;
+top:
+       yylinpt = yyLinpt;
+       yyline++;
+       yyseqid++;
+       cp = charbuf;
+       ib = ibp;
+       i = sizeof charbuf - 1;
+       for (;;) {
+               c = getc(ib);
+               if (c == EOF) {
+                       if (uninclud())
+                               goto top;
+#ifdef PXP
+                       if (ateof == 0 && bracket) {
+                               strcpy(charbuf, "begin end.\n");
+                               ateof = 1;
+                               goto out;
+                       }
+#endif
+                       bufp = "\n";
+                       yyline--;
+                       yyseqid--;
+                       yyprtd = 1;
+                       return (-1);
+               }
+               *cp++ = c;
+               if (c == '\n')
+                       break;
+               if (--i == 0) {
+                       line = yyline;
+                       error("Input line too long - QUIT");
+                       pexit(DIED);
+               }
+       }
+       *cp = 0;
+       yyLinpt = yylinpt + cp - charbuf;
+       if (includ())
+               goto top;
+#ifdef PXP
+       if (cp == &charbuf[1])
+               commnl();
+       else if (cp == &charbuf[2])
+               switch (charbuf[0]) {
+                       case ' ':
+                               commnlbl();
+                               break;
+                       case '\f':
+                               commform();
+               }
+#endif
+       if (opt('u'))
+               setuflg();
+out:
+       bufp = charbuf - 1;
+       yycol = 8;
+       return (1);
+}
+\f
+/*
+ * Check an input line to see if it is a "#include" pseudo-statement.
+ * We allow arbitrary blanks in the line and the file name
+ * may be delimited by either 's or "s.  A single semicolon
+ * may be placed after the name, but nothing else is allowed
+ */
+includ()
+{
+       register char *cp, *dp;
+       char ch;
+       register struct inc *ip;
+
+       cp = charbuf;
+       if (*cp++ != '#')
+               return (0);
+       cp = skipbl(cp);
+       for (dp = "include"; *dp; dp++)
+               if (*dp != *cp++)
+                       return (0);
+       line = yyline;
+       cp = skipbl(cp);
+       ch = *cp++;
+       if (ch != '\'' && ch != '"') {
+               /*
+                * This should be a yerror flagging the place
+                * but its not worth figuring out the column.
+                */
+               line = yyline;
+               error("Include syntax error - expected ' or \" not found - QUIT");
+               pexit(DIED);
+       }
+       for (dp = cp; *dp != ch; dp++)
+               if (*dp == 0) {
+                       line = yyline;
+                       error("Missing closing %c for include file name - QUIT", ch);
+                       pexit(DIED);
+               }
+       *dp++ = 0;
+/*
+ *     if (*dp == ';')
+ *             dp++;
+ *     dp = skipbl(dp);
+ *     if (*dp != '\n') {
+ *             line = yyline;
+ *             error("Garbage after filename in include");
+ *             pexit(DIED);
+ *     }
+ */
+       if (!dotted(cp, 'i')) {
+               line = yyline;
+               error("Include filename must end in .i");
+       }
+#ifdef PXP
+       commincl(cp, ch);
+       if (noinclude)
+               return (1);
+#endif
+       inclev++;
+       if (inclev > MAXINC) {
+               line = yyline;
+               error("Absurdly deep include nesting - QUIT");
+               pexit(DIED);
+       }
+       ip = &incs[inclev];
+       ip->filename = filename;
+       filename = savestr(cp);
+/*
+ *     left over from before stdio
+ *
+ *     cp = malloc(518);
+ *     if (cp == -1) {
+ *             error("Ran out of memory (include)");
+ *             pexit(DIED);
+ *     }
+ *
+ */
+       ip->ibp = ibp;
+       if ( ( ibp = fopen(filename, "r" ) ) == NULL ) {
+               perror(filename);
+               pexit(DIED);
+       }
+       if (inpflist(filename)) {
+#ifdef PI
+               opush('l');
+#endif
+#ifdef PXP
+               opush('z');
+#endif
+       }
+       ip->Printed = printed;
+       printed = 0;
+       ip->yyline = yyline;
+       yyline = 0;
+       ip->yyLinpt = yyLinpt;
+       yyLinpt = 0;
+/*
+ *     left over from before stdio
+ *
+ *     ip->ibp = ibp;
+ *     ibp = cp;
+ *
+ */
+       return (1);
+}
+
+skipbl(ocp)
+       char *ocp;
+{
+       register char *cp;
+
+       cp = ocp;
+       while (*cp == ' ' || *cp == '\t')
+               cp++;
+       return (cp);
+}
+
+\f
+/*
+ * At the end of an include,
+ * close the file, free the input buffer,
+ * and restore the environment before
+ * the "push", including the value of
+ * the z option for pxp and the l option for pi.
+ */
+uninclud()
+{
+       register struct inc *ip;
+
+       if (inclev < 0)
+               return (0);
+/*
+ *     left over from before stdio: becomes fclose ( ibp )
+ *
+ *     close(ibp[0]);
+ *     free(ibp);
+ *
+ */
+       fclose ( ibp );
+       ip = &incs[inclev];
+       ibp = ip->ibp;
+       yyline = ip->yyline;
+       if (inpflist(filename)) {
+#ifdef PI
+               opop('l');
+#endif
+#ifdef PXP
+               opop('z');
+#endif
+       }
+       filename = ip->filename;
+       yyLinpt = ip->yyLinpt;
+       /*
+        * If we printed out the nested name,
+        * then we should print all covered names again.
+        * If we didn't print out the nested name
+        * we print the uncovered name only if it
+        * has not been printed before (unstack).
+        */
+       if (printed) {
+               printed = 0;
+               while (ip >= incs) {
+                       ip->Printed = 0;
+                       ip--;
+               }
+       } else
+               printed = ip->Printed;
+       inclev--;
+       return (1);
+}
diff --git a/usr/src/cmd/pi/yyid.c b/usr/src/cmd/pi/yyid.c
new file mode 100644 (file)
index 0000000..e13047c
--- /dev/null
@@ -0,0 +1,258 @@
+/* Copyright (c) 1979 Regents of the University of California */
+#
+/*
+ * pi - Pascal interpreter code translator
+ *
+ * Charles Haley, Bill Joy UCB
+ * Version 1.1 February 1978
+ *
+ *
+ * pxp - Pascal execution profiler
+ *
+ * Bill Joy UCB
+ * Version 1.1 February 1978
+ */
+
+#include "whoami"
+#include "0.h"
+#include "yy.h"
+
+#ifdef PI
+extern int *yypv;
+/*
+ * Determine whether the identifier whose name
+ * is "cp" can possibly be a kind, which is a
+ * namelist class.  We look through the symbol
+ * table for the first instance of cp as a non-field,
+ * and at all instances of cp as a field.
+ * If any of these are ok, we return true, else false.
+ * It would be much better to handle with's correctly,
+ * even to just know whether we are in a with at all.
+ *
+ * Note that we don't disallow constants on the lhs of assignment.
+ */
+identis(cp, kind)
+       register char *cp;
+       int kind;
+{
+       register struct nl *p;
+       int i;
+
+       /*
+        * Cp is NIL when error recovery inserts it.
+        */
+       if (cp == NIL)
+               return (1);
+
+       /*
+        * Record kind we want for possible later use by yyrecover
+        */
+       yyidwant = kind;
+       yyidhave = NIL;
+       i = ( (int) cp ) & 077;
+       for (p = disptab[i]; p != NIL; p = p->nl_next)
+               if (p->symbol == cp) {
+                       if (yyidok(p, kind))
+                               goto gotit;
+                       if (p->class != FIELD && p->class != BADUSE)
+                               break;
+               }
+       if (p != NIL)
+               for (p = p->nl_next; p != NIL; p = p->nl_next)
+                       if (p->symbol == cp && p->class == FIELD && yyidok(p, kind))
+                               goto gotit;
+       return (0);
+gotit:
+       if (p->class == BADUSE && !Recovery) {
+               yybadref(p, OY.Yyeline);
+               yypv[0] = NIL;
+       }
+       return (1);
+}
+\f
+/*
+ * A bad reference to the identifier cp on line
+ * line and use implying the addition of kindmask
+ * to the mask of kind information.
+ */
+yybaduse(cp, line, kindmask)
+       register char *cp;
+       int line, kindmask;
+{
+       register struct nl *p, *oldp;
+       int i;
+
+       i = ( (int) cp ) & 077;
+       for (p = disptab[i]; p != NIL; p = p->nl_next)
+               if (p->symbol == cp)
+                       break;
+       oldp = p;
+       if (p == NIL || p->class != BADUSE)
+               p = enter(defnl(cp, BADUSE, 0, 0));
+       p->value[NL_KINDS] =| kindmask;
+       yybadref(p, line);
+       return (oldp);
+}
+
+    /*
+     * ud is initialized so that esavestr will allocate
+     * sizeof ( struct udinfo ) bytes for the 'real' struct udinfo
+     */
+struct udinfo ud = { ~0 , ~0 , 0};
+/*
+ * Record a reference to an undefined identifier,
+ * or one which is improperly used.
+ */
+yybadref(p, line)
+       register struct nl *p;
+       int line;
+{
+       register struct udinfo *udp;
+
+       if (p->chain != NIL && p->chain->ud_line == line)
+               return;
+       udp = esavestr(&ud);
+       udp->ud_line = line;
+       udp->ud_next = p->chain;
+       p->chain = udp;
+}
+
+#define        varkinds        ((1<<CONST)|(1<<VAR)|(1<<REF)|(1<<ARRAY)|(1<<PTR)|(1<<RECORD)|(1<<FIELD)|(1<<FUNC)|(1<<FVAR))
+/*
+ * Is the symbol in the p entry of the namelist
+ * even possibly a kind kind?  If not, update
+ * what we have based on this encounter.
+ */
+yyidok(p, kind)
+       register struct nl *p;
+       int kind;
+{
+
+       if (p->class == BADUSE) {
+               if (kind == VAR)
+                       return (p->value[0] & varkinds);
+               return (p->value[0] & (1 << kind));
+       }
+       if (yyidok1(p, kind))
+               return (1);
+       if (yyidhave != NIL)
+               yyidhave = IMPROPER;
+       else
+               yyidhave = p->class;
+       return (0);
+}
+
+yyidok1(p, kind)
+       register struct nl *p;
+       int kind;
+{
+       int i;
+
+       switch (kind) {
+               case FUNC:
+                       if (p->class == FVAR)
+                               return(1);
+               case CONST:
+               case TYPE:
+               case PROC:
+               case FIELD:
+                       return (p->class == kind);
+               case VAR:
+                       return (p->class == CONST || yyisvar(p, NIL));
+               case ARRAY:
+               case RECORD:
+                       return (yyisvar(p, kind));
+               case PTRFILE:
+                       return (yyisvar(p, PTR) || yyisvar(p, FILET));
+       }
+}
+
+yyisvar(p, class)
+       register struct nl *p;
+       int class;
+{
+
+       switch (p->class) {
+               case FIELD:
+               case VAR:
+               case REF:
+               case FVAR:
+               /*
+                * We would prefer to return
+                * parameterless functions only.
+                */
+               case FUNC:
+                       return (class == NIL || (p->type != NIL && p->type->class == class));
+       }
+       return (0);
+}
+#endif
+#ifdef PXP
+#ifndef DEBUG
+identis()
+{
+
+       return (1);
+}
+#endif
+#ifdef DEBUG
+extern char *classes[];
+
+char   kindchars[]     "UCTVAQRDPF";
+/*
+ * Fake routine "identis" for pxp when testing error recovery.
+ * Looks at letters in variable names to answer questions
+ * about attributes.  Mapping is
+ *     C       const_id
+ *     T       type_id
+ *     V       var_id          also if any of AQRDF
+ *     A       array_id
+ *     Q       ptr_id
+ *     R       record_id
+ *     D       field_id        D for "dot"
+ *     P       proc_id
+ *     F       func_id
+ */
+identis(cp, kind)
+       register char *cp;
+       int kind;
+{
+       register char *dp;
+       char kindch;
+
+       /*
+        * Don't do anything unless -T
+        */
+       if (!typetest)
+               return (1);
+
+       /*
+        * Inserted symbols are always correct
+        */
+       if (cp == NIL)
+               return (1);
+       /*
+        * Set up the names for error messages
+        */
+       yyidwant = classes[kind];
+       for (dp = kindchars; *dp; dp++)
+               if (any(cp, *dp)) {
+                       yyidhave = classes[dp - kindchars];
+                       break;
+               }
+
+       /*
+        * U in the name means undefined
+        */
+       if (any(cp, 'U'))
+               return (0);
+
+       kindch = kindchars[kind];
+       if (kindch == 'V')
+               for (dp = "AQRDF"; *dp; dp++)
+                       if (any(cp, *dp))
+                               return (1);
+       return (any(cp, kindch));
+}
+#endif
+#endif
diff --git a/usr/src/cmd/pi/yylex.c b/usr/src/cmd/pi/yylex.c
new file mode 100644 (file)
index 0000000..2f735c6
--- /dev/null
@@ -0,0 +1,349 @@
+/* Copyright (c) 1979 Regents of the University of California */
+#
+/*
+ * pi - Pascal interpreter code translator
+ *
+ * Charles Haley, Bill Joy UCB
+ * Version 1.2 November 1978
+ *
+ *
+ * pxp - Pascal execution profiler
+ *
+ * Bill Joy UCB
+ * Version 1.2 November 1978
+ */
+
+#include "whoami"
+#include "0.h"
+#include "yy.h"
+
+/*
+ * Scanner
+ */
+int    yylacnt;
+
+#define        YYLASIZ 10
+
+struct yytok Yla[YYLASIZ];
+
+unyylex(y)
+       struct yylex *y;
+{
+
+       if (yylacnt == YYLASIZ)
+               panic("unyylex");
+       copy(&Yla[yylacnt], y, sizeof Yla[0]);
+       yylacnt++;
+
+}
+
+yylex()
+{
+       register c;
+       register **ip;
+       register char *cp;
+       int f;
+       char delim;
+
+       if (yylacnt != 0) {
+               yylacnt--;
+               copy(&Y, &Yla[yylacnt], sizeof Y);
+               return (yychar);
+       }
+       if (c = yysavc)
+               yysavc = 0;
+       else
+               c = readch();
+#ifdef PXP
+       yytokcnt++;
+#endif
+
+next:
+       /*
+        * skip white space
+        */
+#ifdef PXP
+       yywhcnt = 0;
+#endif
+       while (c == ' ' || c == '\t') {
+#ifdef PXP
+               if (c == '\t')
+                       yywhcnt++;
+               yywhcnt++;
+#endif
+               c = readch();
+       }
+       yyecol = yycol;
+       yyeline = yyline;
+       yyefile = filename;
+       yyeseqid = yyseqid;
+       yyseekp = yylinpt;
+       cp = token;
+       yylval = yyline;
+       switch (c) {
+               case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': 
+               case 'h': case 'i': case 'j': case 'k': case 'l': case 'm': case 'n': 
+               case 'o': case 'p': case 'q': case 'r': case 's': case 't': case 'u': 
+               case 'v': case 'w': case 'x': case 'y': case 'z': 
+               case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G': 
+               case 'H': case 'I': case 'J': case 'K': case 'L': case 'M': case 'N': 
+               case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T': case 'U': 
+               case 'V': case 'W': case 'X': case 'Y': case 'Z': 
+                       do {
+                               *cp++ = c;
+                               c = readch();
+                       } while (alph(c) || digit(c));
+                       *cp = 0;
+                       if (opt('s'))
+                               for (cp = token; *cp; cp++)
+                                       if (*cp >= 'A' && *cp <= 'Z') {
+                                               *cp =| ' ';
+                                       }
+                       yysavc = c;
+                       ip = hash(0, 1);
+                       if (*ip < yykey || *ip >= lastkey) {
+                               yylval = *ip;
+                               return (YID);
+                       }
+                       yylval = yyline;
+                       /*
+                        * For keywords
+                        * the lexical token
+                        * is magically retrieved
+                        * from the keyword table.
+                        */
+                       return ((*ip)[1]);
+               case '0': case '1': case '2': case '3': case '4':
+               case '5': case '6': case '7': case '8': case '9':
+                       f = 0;
+                       do {
+                               *cp++ = c;
+                               c = readch();
+                       } while (digit(c));
+                       if (c == 'b' || c == 'B') {
+                               /*
+                                * nonstandard - octal constants
+                                */
+                               if (opt('s')) {
+                                       standard();
+                                       yerror("Octal constants are non-standard");
+                               }
+                               *cp = 0;
+                               yylval = copystr(token);
+                               return (YBINT);
+                       }
+                       if (c == '.') {
+                               c = readch();
+                               if (c == '.') {
+                                       *cp = 0;
+                                       yysavc = YDOTDOT;
+                                       yylval = copystr(token);
+                                       return (YINT);
+                               }
+infpnumb:
+                               f++;
+                               *cp++ = '.';
+                               if (!digit(c)) {
+                                       yyset();
+                                       recovered();
+                                       yerror("Digits required after decimal point");
+                                       *cp++ = '0';
+                               } else
+                                       while (digit(c)) {
+                                               *cp++ = c;
+                                               c = readch();
+                                       }
+                       }
+                       if (c == 'e' || c == 'E') {
+                               f++;
+                               *cp++ = c;
+                               if ((c = yysavc) == 0)
+                                       c = readch();
+                               if (c == '+' || c == '-') {
+                                       *cp++ = c;
+                                       c = readch();
+                               }
+                               if (!digit(c)) {
+                                       yyset();
+                                       yerror("Digits required in exponent");
+                                       *cp++ = '0';
+                               } else
+                                       while (digit(c)) {
+                                               *cp++ = c;
+                                               c = readch();
+                                       }
+                       }
+                       *cp = 0;
+                       yysavc = c;
+                       yylval = copystr(token);
+                       if (f)
+                               return (YNUMB);
+                       return (YINT);
+               case '"':
+               case '`':
+                       if (!any(bufp + 1, c))
+                               goto illch;
+                       if (!dquote) {
+                               recovered();
+                               dquote++;
+                               yerror("Character/string delimiter is '");
+                       }
+               case '\'':
+               case '#':
+                       delim = c;
+                       do {
+                               do {
+                                       c = readch();
+                                       if (c == '\n') {
+                                               yerror("Unmatched %c for string", delim);
+                                               if (cp == token)
+                                                       *cp++ = ' ', cp++;
+                                               break;
+                                       }
+                                       *cp++ = c;
+                               } while (c != delim);
+                               c = readch();
+                       } while (c == delim);
+                       *--cp = 0;
+                       if (cp == token) {
+                               yerror("Null string not allowed");
+                               *cp++ = ' ';
+                               *cp++ = 0;
+                       }
+                       yysavc = c;
+                       yylval = copystr(token);
+                       return (YSTRING);
+               case '.':
+                       c = readch();
+                       if (c == '.')
+                               return (YDOTDOT);
+                       if (digit(c)) {
+                               recovered();
+                               yerror("Digits required before decimal point");
+                               *cp++ = '0';
+                               goto infpnumb;
+                       }
+                       yysavc = c;
+                       return ('.');
+               case '{':
+                       /*
+                        * { ... } comment
+                        */
+#ifdef PXP
+                       getcm(c);
+#endif
+#ifdef PI
+                       c = options();
+                       while (c != '}') {
+                               if (c <= 0)
+                                       goto nonterm;
+                               if (c == '{') {
+                                       warning();
+                                       yyset();
+                                       yerror("{ in a { ... } comment");
+                               }
+                               c = readch();
+                       }
+#endif
+                       c = readch();
+                       goto next;
+               case '(':
+                       if ((c = readch()) == '*') {
+                               /*
+                                * (* ... *) comment
+                                */
+#ifdef PXP
+                               getcm(c);
+                               c = readch();
+                               goto next;
+#endif
+#ifdef PI
+                               c = options();
+                               for (;;) {
+                                       if (c < 0) {
+nonterm:
+                                               yerror("Comment does not terminate - QUIT");
+                                               pexit(ERRS);
+                                       }
+                                       if (c == '(' && (c = readch()) == '*') {
+                                               warning();
+                                               yyset();
+                                               yerror("(* in a (* ... *) comment");
+                                       }
+                                       if (c == '*') {
+                                               if ((c = readch()) != ')')
+                                                       continue;
+                                               c = readch();
+                                               goto next;
+                                       }
+                                       c = readch();
+                               }
+#endif
+                       }
+                       yysavc = c;
+                       c = '(';
+               case ';':
+               case ',':
+               case ':':
+               case '=':
+               case '*':
+               case '+':
+               case '/':
+               case '-':
+               case '|':
+               case '&':
+               case ')':
+               case '[':
+               case ']':
+               case '<':
+               case '>':
+               case '~':
+               case '^':
+                       return (c);
+               default:
+                       switch (c) {
+                               case YDOTDOT:
+                                       return (c);
+                               case '\n':
+                                       c = readch();
+#ifdef PXP
+                                       yytokcnt++;
+#endif
+                                       goto next;
+                               case '\f':
+                                       c = readch();
+                                       goto next;
+                       }
+                       if (c <= 0)
+                               return (YEOF);
+illch:
+                       do
+                               yysavc = readch();
+                       while (yysavc == c);
+                       yylval = c;
+                       return (YILLCH);
+       }
+}
+
+yyset()
+{
+
+       yyecol = yycol;
+       yyeline = yyline;
+       yyefile = filename;
+       yyseekp = yylinpt;
+}
+
+/*
+ * Setuflg trims the current
+ * input line to at most 72 chars
+ * for the u option.
+ */
+setuflg()
+{
+
+       if (charbuf[71] != '\n') {
+               charbuf[72] = '\n';
+               charbuf[73] = 0;
+       }
+}
diff --git a/usr/src/cmd/pi/yyoptions.c b/usr/src/cmd/pi/yyoptions.c
new file mode 100644 (file)
index 0000000..ac75f4d
--- /dev/null
@@ -0,0 +1,66 @@
+/* Copyright (c) 1979 Regents of the University of California */
+#
+/*
+ * pi - Pascal interpreter code translator
+ *
+ * Charles Haley, Bill Joy UCB
+ * Version 1.1 February 1978
+ */
+
+#include "whoami"
+#include "0.h"
+#include "yy.h"
+
+/*
+ * Options processes the option
+ * strings which can appear in
+ * comments and returns the next character.
+ */
+options()
+{
+       register c, ch;
+       register char *optp;
+       int ok;
+
+       c = readch();
+       if (c != '$')
+               return (c);
+       do {
+               ch = c = readch();
+               switch (c) {
+                       case 'b':
+                               optp = &opts['b'-'a'];
+                               goto optdig;
+                       case 'x':
+                               optp = &opts['x'-'a'];
+                               goto optdig;
+                       optdig:
+                               c = readch();
+                               if (!digit(c))
+                                       return (c);
+                               *optp = c - '0';
+                               c = readch();
+                               break;
+                       default:
+                               if (c < 'a' || c > 'z')
+                                       return (c);
+                               optp = &opts[c-'a'];
+                               c = readch();
+                               if (c == '+') {
+                                       *optp = 1;
+                                       c = readch();
+                               } else if (c == '-') {
+                                       *optp = 0;
+                                       c = readch();
+                               } else
+                                       return (c);
+                               break;
+                       }
+#ifdef PI0
+               send(ROSET, ch, *optp);
+#endif
+       } while (c == ',');
+       if (opts['u'-'a'])
+               setuflg();
+       return (c);
+}
diff --git a/usr/src/cmd/pi/yypanic.c b/usr/src/cmd/pi/yypanic.c
new file mode 100644 (file)
index 0000000..abdd91d
--- /dev/null
@@ -0,0 +1,160 @@
+/* Copyright (c) 1979 Regents of the University of California */
+#
+/*
+ * pi - Pascal interpreter code translator
+ *
+ * Charles Haley, Bill Joy UCB
+ * Version 1.1 February 1978
+ *
+ *
+ * pxp - Pascal execution profiler
+ *
+ * Bill Joy UCB
+ * Version 1.1 February 1978
+ */
+
+#include "whoami"
+#include "0.h"
+#include "yy.h"
+
+struct yytok oldpos;
+/*
+ * The routine yyPerror coordinates the panic when
+ * the correction routines fail. Three types of panics
+ * are possible - those in a declaration part, those
+ * in a statement part, and those in an expression.
+ *
+ * Declaration part panics consider insertion of "begin",
+ * expression part panics will stop on more symbols.
+ * The panics are otherwise the same.
+ *
+ * ERROR MESSAGE SUPPRESSION STRATEGY: August 11, 1977
+ *
+ * If the parser has not made at least 2 moves since the last point of
+ * error then we want to suppress the supplied error message.
+ * Otherwise we print it.
+ * We then skip input up to the next solid symbol.
+ */
+yyPerror(cp, kind)
+       char *cp;
+       register int kind;
+{
+       register int ishifts, brlev;
+
+       copy(&oldpos, &Y, sizeof oldpos);
+       brlev = 0;
+       if (yychar < 0)
+               yychar = yylex();
+       for (ishifts = yyshifts; ; yychar = yylex(), yyshifts++)
+               switch (yychar) {
+                       case YILLCH:
+                               yerror("Illegal character");
+                               if (ishifts == yyshifts)
+                                       yyOshifts = 0;
+                               continue;
+                       case YEOF:
+                               goto quiet;
+                       case ';':
+                               if (kind == PPROG)
+                                       continue;
+                               if (kind == PDECL)
+                                       yychar = yylex();
+                               goto resume;
+                       case YEND:
+                               if (kind == PPROG)
+                                       continue;
+                       case YPROCEDURE:
+                       case YFUNCTION:
+                               goto resume;
+                       case YLABEL:
+                       case YTYPE:
+                       case YCONST:
+                       case YVAR:
+                               if (kind == PSTAT) {
+                                       yerror("Declaration found when statement expected");
+                                       goto quiet;
+                               }
+                       case YBEGIN:
+                               goto resume;
+                       case YFOR:
+                       case YREPEAT:
+                       case YWHILE:
+                       case YGOTO:
+                       case YIF:
+                               if (kind != PDECL)
+                                       goto resume;
+                               yerror("Expected keyword begin after declarations, before statements");
+                               unyylex(&Y);
+                               yychar = YBEGIN;
+                               yylval = nullsem(YBEGIN);
+                               goto quiet;
+                       case YTHEN:
+                       case YELSE:
+                       case YDO:
+                               if (kind == PSTAT) {
+                                       yychar = yylex();
+                                       goto resume;
+                               }
+                               if (kind == PEXPR)
+                                       goto resume;
+                               continue;
+                       case ')':
+                       case ']':
+                               if (kind != PEXPR)
+                                       continue;
+                               if (brlev == 0)
+                                       goto resume;
+                               if (brlev > 0)
+                                       brlev--;
+                               continue;
+                       case '(':
+                       case '[':
+                               brlev++;
+                               continue;
+                       case ',':
+                               if (brlev != 0)
+                                       continue;
+                       case YOF:
+                       case YTO:
+                       case YDOWNTO:
+                               if (kind == PEXPR)
+                                       goto resume;
+                               continue;
+#ifdef PI
+                       /*
+                        * A rough approximation for now
+                        * Should be much more lenient on suppressing
+                        * warnings.
+                        */
+                       case YID:
+                               syneflg++;
+                               continue;
+#endif
+               }
+resume:
+       if (yyOshifts >= 2) {
+               if (yychar != -1)
+                       unyylex(&Y);
+               copy(&Y, &oldpos, sizeof Y);
+               yerror(cp);
+               yychar = yylex();
+       }
+quiet:
+       if (yyshifts - ishifts > 2 && opt('r')) {
+               setpfx('r');
+               yerror("Parsing resumes");
+       }
+       /*
+        * If we paniced in the statement part,
+        * and didn't stop at a ';', then we insert
+        * a ';' to prevent the recovery from immediately
+        * inserting one and complaining about it.
+        */
+       if (kind == PSTAT && yychar != ';') {
+               unyylex(&Y);
+               yyshifts--;
+               yytshifts--;
+               yychar = ';';
+               yylval = nullsem(';');
+       }
+}
diff --git a/usr/src/cmd/pi/yyparse.c b/usr/src/cmd/pi/yyparse.c
new file mode 100644 (file)
index 0000000..e791c5d
--- /dev/null
@@ -0,0 +1,213 @@
+/* Copyright (c) 1979 Regents of the University of California */
+#
+/*
+ * pi - Pascal interpreter code translator
+ *
+ * Charles Haley, Bill Joy UCB
+ * Version 1.1 February 1978
+ *
+ *
+ * pxp - Pascal execution profiler
+ *
+ * Bill Joy UCB
+ * Version 1.1 February 1978
+ */
+
+#include "whoami"
+#include "0.h"
+#include "yy.h"
+
+/*
+ * Parser for 'yacc' output.
+ * Specifially Modified for Berkeley Pascal
+ */
+
+int    yystate;        /* Current parser state */
+int    *yypv;
+unsigned yytshifts 1;  /* Number of "true" shifts */
+
+/*
+ * Parse Tables
+ */
+int    yygo[];
+int    yypgo[];
+int    yyr1[];
+int    yyr2[];
+int    yyact[];
+int    yypact[];
+
+/*
+ * Parse and parallel semantic stack
+ */
+int    yyv[MAXDEPTH];
+int    yys[MAXDEPTH];
+
+/*
+ * This routine parses the input stream, and
+ * returns if it accepts, or if an unrecoverable syntax
+ * error is encountered.
+ */
+yyparse()
+{
+       register int *ps, n, *p;
+       int paniced, *panicps, idfail;
+
+       yystate = 0;
+       yychar = yylex();
+       OY.Yychar = -1;
+       yyshifts = 3;
+       paniced = 0;
+       ps = &yys[0]-1;
+       yypv = &yyv[0]-1;
+#ifdef PXP
+       yypw = &yyw[0]-1;
+#endif
+
+stack:
+       /*
+        * Push new state and value.
+        */
+       if (yypv >= &yyv[MAXDEPTH-1]) {
+               yerror("Parse stack overflow");
+               pexit(DIED);
+       }
+       *++ps = yystate;
+       *++yypv = yyval;
+#ifdef PXP
+       yypw++;
+#endif
+newstate:
+       /*
+        * Locate parsing actions for the
+        * new parser state.
+        */
+       p = &yyact[ yypact[yystate+1] ]; 
+actn:
+       /*
+        * Search the parse actions table
+        * for something useful to do.
+        * While n is non-positive, it is the negation
+        * of the token we are testing for.
+        */
+#ifdef PI
+       if ((n = *p++) <= 0) {
+               if (yychar < 0)
+                       yychar = yylex();
+               do
+                       if ((n =+ yychar) != 0)
+                               p++;
+               while ((n = *p++) <= 0);
+       }
+#else
+       while ((n = *p++) <= 0)
+               if ((n =+ yychar) != 0)
+                       p++;
+#endif
+       switch (n >> 12) {
+
+               /*
+                * Shift.
+                */
+               case 2:
+#ifdef PXP
+                       yypw[1].Wseqid = yyseqid;
+                       yypw[1].Wcol = yycol;
+#endif
+                       OYcopy();
+                       yystate = n & 07777;
+                       yyval = yylval;
+#ifdef PI
+                       yychar = -1;
+#else
+                       yychar = yylex();
+#endif
+                       yyshifts++;
+                       yytshifts++;
+                       goto stack;
+
+               /*
+                * Reduce.
+                */
+               case 3:
+                       n =& 07777;
+                       N = yyr2[n];
+                       if (N == 1 && OY.Yychar == YID && !yyEactr(n, yypv[0])) {
+                               idfail = 1;
+                               goto errin;
+                       }
+                       OY.Yychar = -1;
+                       ps =- N;
+                       yypv =- N;
+#ifdef PXP
+                       yypw =- N;
+#endif
+                       yyval = yypv[1];
+                       yyactr(n);
+                       /*
+                        * Use goto table to find next state.
+                        */
+                       p = &yygo[yypgo[yyr1[n]]];
+                       while (*p != *ps && *p >= 0)
+                               p =+ 2;
+                       yystate = p[1];
+                       goto stack;
+
+               /*
+                * Accept.
+                */
+               case 4:
+                       return;
+
+               /*
+                * Error.
+                */
+               case 1:
+                       idfail = 0;
+errin:
+                       if ((paniced || yyshifts != 0) && yyrecover(ps, idfail)) {
+                               paniced = 0;
+                               ps = Ps;
+                               yystate = *ps;
+                               goto newstate;
+                       }
+                       /*
+                        * Find a state where 'error' is a
+                        * legal shift action.
+                        */
+                       if (paniced && yyshifts <= 0 && ps >= panicps) {
+                               yypv =- (ps - panicps) + 1;
+#ifdef PXP
+                               yypw =- (ps - panicps) + 1;
+#endif
+                               ps = panicps - 1;
+                       }
+                       while (ps >= yys) {
+                               for (p = &yyact[ yypact[*ps+1] ] ; *p <= 0; p=+ 2)
+                                       if (*p == -256) {
+                                               panicps = ps;
+                                               yystate= p[1] & 07777;
+                                               yyOshifts = yyshifts;
+                                               yyshifts = 0;
+                                               paniced = 1;
+                                               goto stack;
+                                       }
+                               --ps;
+                               --yypv;
+#ifdef PXP
+                               --yypw;
+#endif
+#ifdef PI
+                               if (OY.Yychar != YID)
+                                       syneflg++;
+#endif
+                               OY.Yychar = -1;
+                       }
+                       if (yychar == YEOF)
+                               yyunexeof();
+                       if (yystate == 1)
+                               yyexeof();
+                       yerror("Unrecoverable syntax error - QUIT");
+                       return;
+       }
+       panic("yyparse");
+}
diff --git a/usr/src/cmd/pi/yyprint.c b/usr/src/cmd/pi/yyprint.c
new file mode 100644 (file)
index 0000000..5e19821
--- /dev/null
@@ -0,0 +1,108 @@
+/* Copyright (c) 1979 Regents of the University of California */
+#
+/*
+ * pi - Pascal interpreter code translator
+ *
+ * Charles Haley, Bill Joy UCB
+ * Version 1.1 February 1978
+ *
+ *
+ * pxp - Pascal execution profiler
+ *
+ * Bill Joy UCB
+ * Version 1.1 February 1978
+ */
+
+#include "whoami"
+#include "0.h"
+#include "yy.h"
+
+char   *tokname();
+
+STATIC bool bounce;
+
+/*
+ * Printing representation of a
+ * "character" - a lexical token
+ * not in a yytok structure.
+ * 'which' indicates which char * you want
+ * should always be called as "charname(...,0),charname(...,1)"
+ */
+char *
+charname(ch , which )
+       int ch;
+       int which;
+{
+       struct yytok Ych;
+
+       Ych.Yychar = ch;
+       Ych.Yylval = nullsem(ch);
+       return (tokname(&Ych , which ));
+}
+
+/*
+ * Printing representation of a token
+ * 'which' as above.
+ */
+char *
+tokname(tp , which )
+       register struct yytok *tp;
+       int                   which;
+{
+       register char *cp;
+       register struct kwtab *kp;
+       char    *cp2;
+
+       cp2 = "";
+       switch (tp->Yychar) {
+               case YCASELAB:
+                       cp = "case-label";
+                       break;
+               case YEOF:
+                       cp = "end-of-file";
+                       break;
+               case YILLCH:
+                       cp = "illegal character";
+                       break;
+               case 256:
+                       /* error token */
+                       cp = "error";
+                       break;
+               case YID:
+                       cp = "identifier";
+                       break;
+               case YNUMB:
+                       cp = "real number";
+                       break;
+               case YINT:
+               case YBINT:
+                       cp = "number";
+                       break;
+               case YSTRING:
+                       cp = tp->Yylval;
+                       cp = cp == NIL || cp[1] == 0 ? "character" : "string";
+                       break;
+               case YDOTDOT:
+                       cp = "'..'";
+                       break;
+               default:
+                       if (tp->Yychar < 256) {
+                               cp = "'x'\0'x'\0'x'\0'x'";
+                               /*
+                                * for four times reentrant code!
+                                * used to be:
+                                * if (bounce = ((bounce + 1) & 1))
+                                *      cp += 4;
+                                */
+                               bounce = ( bounce + 1 ) % 4;
+                               cp += (4 * bounce);     /* 'x'\0 is 4 chars */
+                               cp[1] = tp->Yychar;
+                               break;
+                       }
+                       for (kp = yykey; kp->kw_str != NIL && kp->kw_val != tp->Yychar; kp++)
+                               continue;
+                       cp = "keyword ";
+                       cp2 = kp->kw_str;
+       }
+       return ( which ? cp2 : cp );
+}