Initial revision
authorceriel <none@none>
Tue, 6 Jan 1987 15:16:53 +0000 (15:16 +0000)
committerceriel <none@none>
Tue, 6 Jan 1987 15:16:53 +0000 (15:16 +0000)
34 files changed:
util/cpp/LLlex.c [new file with mode: 0644]
util/cpp/LLlex.h [new file with mode: 0644]
util/cpp/LLmessage.c [new file with mode: 0644]
util/cpp/Makefile [new file with mode: 0644]
util/cpp/Parameters [new file with mode: 0644]
util/cpp/bits.h [new file with mode: 0644]
util/cpp/ch7bin.c [new file with mode: 0644]
util/cpp/ch7mon.c [new file with mode: 0644]
util/cpp/char.tab [new file with mode: 0644]
util/cpp/chtab.c [new file with mode: 0644]
util/cpp/class.h [new file with mode: 0644]
util/cpp/domacro.c [new file with mode: 0644]
util/cpp/error.c [new file with mode: 0644]
util/cpp/expr.c [new file with mode: 0644]
util/cpp/expression.g [new file with mode: 0644]
util/cpp/file_info.h [new file with mode: 0644]
util/cpp/idf.c [new file with mode: 0644]
util/cpp/idf.h [new file with mode: 0644]
util/cpp/init.c [new file with mode: 0644]
util/cpp/input.c [new file with mode: 0644]
util/cpp/input.h [new file with mode: 0644]
util/cpp/interface.h [new file with mode: 0644]
util/cpp/macro.h [new file with mode: 0644]
util/cpp/main.c [new file with mode: 0644]
util/cpp/make.hfiles [new file with mode: 0755]
util/cpp/make.tokcase [new file with mode: 0755]
util/cpp/make.tokfile [new file with mode: 0755]
util/cpp/next.c [new file with mode: 0644]
util/cpp/options.c [new file with mode: 0644]
util/cpp/preprocess.c [new file with mode: 0644]
util/cpp/replace.c [new file with mode: 0644]
util/cpp/scan.c [new file with mode: 0644]
util/cpp/skip.c [new file with mode: 0644]
util/cpp/tokenname.c [new file with mode: 0644]

diff --git a/util/cpp/LLlex.c b/util/cpp/LLlex.c
new file mode 100644 (file)
index 0000000..744fd72
--- /dev/null
@@ -0,0 +1,372 @@
+/* $Header$ */
+/*                 L E X I C A L   A N A L Y Z E R                     */
+
+#include       "idfsize.h"
+#include       "numsize.h"
+#include       "strsize.h"
+
+#include       <alloc.h>
+#include       "input.h"
+#include       "idf.h"
+#include       "LLlex.h"
+#include       "Lpars.h"
+#include       "class.h"
+#include       "bits.h"
+
+/* Data about the token yielded */
+struct token dot;
+
+int ReplaceMacros = 1;         /* replacing macros                     */
+int AccFileSpecifier = 0;      /* return filespecifier <...>           */
+int AccDefined = 0;            /* accept "defined(...)"                */
+int UnknownIdIsZero = 0;       /* interpret unknown id as integer 0    */
+
+char *string_token();
+
+PushLex()
+{
+       DOT = 0;
+}
+
+PopLex()
+{}
+
+int
+LLlex()
+{
+       return (DOT != EOF) ? GetToken(&dot) : EOF;
+}
+
+#define BUFSIZ 1024
+
+int
+GetToken(ptok)
+       register struct token *ptok;
+{
+       char buf[BUFSIZ];
+       register int c, nch;
+
+again: /* rescan the input after an error or replacement       */
+       LoadChar(c);
+go_on:
+       if ((c & 0200) && c != EOI)
+               fatal("non-ascii '\\%03o' read", c & 0377);
+       switch (class(c)) {     /* detect character class       */
+       case STNL:
+               LineNumber++;
+               return ptok->tk_symb = EOF;
+       case STSKIP:
+               goto again;
+       case STGARB:            /* garbage character                    */
+               if (c == '\\') {
+                       /* a '\\' is allowed in #if/#elif expression    */
+                       LoadChar(c);
+                       if (class(c) == STNL) { /* vt , ff ?    */
+                               ++LineNumber;
+                               goto again;
+                       }
+                       PushBack();
+                       c = '\\';
+               }
+               if (040 < c && c < 0177)
+                       error("garbage char %c", c);
+               else
+                       error("garbage char \\%03o", c);
+               goto again;
+       case STSIMP:    /* a simple character, no part of compound token*/
+               if (c == '/') { /* probably the start of comment        */
+                       LoadChar(c);
+                       if (c == '*') { /* start of comment     */
+                               skipcomment();
+                               goto again;
+                       }
+                       else {
+                               PushBack();
+                               c = '/';        /* restore c    */
+                       }
+               }
+               return ptok->tk_symb = c;
+       case STCOMP:    /* maybe the start of a compound token          */
+               LoadChar(nch);                  /* character lookahead  */
+               switch (c) {
+               case '!':
+                       if (nch == '=')
+                               return ptok->tk_symb = NOTEQUAL;
+                       PushBack();
+                       return ptok->tk_symb = c;
+               case '&':
+                       if (nch == '&')
+                               return ptok->tk_symb = AND;
+                       PushBack();
+                       return ptok->tk_symb = c;
+               case '<':
+                       if (AccFileSpecifier) {
+                               PushBack();     /* pushback nch */
+                               ptok->tk_str =
+                                       string_token("file specifier", '>');
+                               return ptok->tk_symb = FILESPECIFIER;
+                       }
+                       if (nch == '<')
+                               return ptok->tk_symb = LEFT;
+                       if (nch == '=')
+                               return ptok->tk_symb = LESSEQ;
+                       PushBack();
+                       return ptok->tk_symb = c;
+               case '=':
+                       if (nch == '=')
+                               return ptok->tk_symb = EQUAL;
+                       /*      The following piece of code tries to recognise
+                               old-fashioned assignment operators `=op'
+                       */
+                       error("illegal character");
+                       goto go_on;
+               case '>':
+                       if (nch == '=')
+                               return ptok->tk_symb = GREATEREQ;
+                       if (nch == '>')
+                               return ptok->tk_symb = RIGHT;
+                       PushBack();
+                       return ptok->tk_symb = c;
+               case '|':
+                       if (nch == '|')
+                               return ptok->tk_symb = OR;
+                       PushBack();
+                       return ptok->tk_symb = c;
+               }
+       case STIDF:
+       {
+               extern int idfsize;             /* ??? */
+               register char *tg = &buf[0];
+               register char *maxpos = &buf[idfsize];
+               register struct idf *idef;
+
+#define tstmac(bx)     if (!(bits[c] & bx)) goto nomac
+#define cpy            if (Unstacked) EnableMacros(); *tg++ = c
+#define load           LoadChar(c); if (!in_idf(c)) goto endidf
+
+#ifdef DOBITS
+               cpy; tstmac(bit0); load;
+               cpy; tstmac(bit1); load;
+               cpy; tstmac(bit2); load;
+               cpy; tstmac(bit3); load;
+               cpy; tstmac(bit4); load;
+               cpy; tstmac(bit5); load;
+               cpy; tstmac(bit6); load;
+               cpy; tstmac(bit7); load;
+#endif
+
+               for(;;) {
+                       if (tg < maxpos) {
+                               cpy;
+                       }
+                       load;
+               }
+       endidf:
+               PushBack();
+               *tg = '\0';     /* mark the end of the identifier */
+               if (ReplaceMacros) {
+                       idef = findidf(buf);
+                       if ((idef && idef->id_macro && replace(idef))) {
+                               goto again;
+                       }
+               }
+       nomac:
+               LoadChar(c);
+               while (in_idf(c)) {
+                       if (tg < maxpos) *tg++ = c;
+                       LoadChar(c);
+               }
+               PushBack();
+               *tg++ = '\0';   /* mark the end of the identifier       */
+               if (UnknownIdIsZero) {
+                       ptok->tk_val = 0;
+                       return ptok->tk_symb = INTEGER;
+               }
+               ptok->tk_str = Malloc(idfsize + 1);
+               strcpy(ptok->tk_str, buf);
+               return ptok->tk_symb = IDENTIFIER;
+       }
+       case STCHAR:                            /* character constant   */
+       {
+               register int val = 0, size = 0;
+
+               LoadChar(c);
+               if (c == '\'')
+                       error("character constant too short");
+               else
+               while (c != '\'') {
+                       if (c == '\n') {
+                               error("newline in character constant");
+                               LineNumber++;
+                               break;
+                       }
+                       if (c == '\\') {
+                               LoadChar(c);
+                               if (c == '\n') {
+                                       LoadChar(c);
+                                       LineNumber++;
+                                       continue;
+                               }
+                               c = quoted(c);
+                       }
+                       val = val*256 + c;
+                       size++;
+                       LoadChar(c);
+               }
+               if (size > sizeof(int))
+                       error("character constant too long");
+               ptok->tk_val = val;
+               return ptok->tk_symb = INTEGER;
+       }
+       case STNUM:
+       {
+               register char *np = &buf[1];
+               register int base = 10;
+               register int vch;
+               register int val = 0;
+
+               if (c == '0') {
+                       *np++ = c;
+                       LoadChar(c);
+                       if (c == 'x' || c == 'X') {
+                               base = 16;
+                               LoadChar(c);
+                       }
+                       else
+                               base = 8;
+               }
+               while (vch = val_in_base(c, base), vch >= 0) {
+                       val = val*base + vch;
+                       if (np < &buf[NUMSIZE])
+                               *np++ = c;
+                       LoadChar(c);
+               }
+               if (c == 'l' || c == 'L')
+                       LoadChar(c);
+               PushBack();
+               ptok->tk_val = val;
+               return ptok->tk_symb = INTEGER;
+       }
+       case STSTR:
+               ptok->tk_str = string_token("string", '"');
+               return ptok->tk_symb = STRING;
+       case STEOI:                     /* end of text on source file   */
+               return ptok->tk_symb = EOF;
+       default:
+               crash("Impossible character class");
+       }
+       /*NOTREACHED*/
+}
+
+skipcomment()
+{
+       register int c;
+
+       NoUnstack++;
+       LoadChar(c);
+       do {
+               while (c != '*') {
+                       if (class(c) == STNL)
+                               ++LineNumber;
+                       else
+                       if (c == EOI) {
+                               NoUnstack--;
+                               return;
+                       }
+                       LoadChar(c);
+               }
+               /* Last Character seen was '*' */
+               LoadChar(c);
+       } while (c != '/');
+       NoUnstack--;
+}
+
+char *
+string_token(nm, stop_char)
+       char *nm;
+{
+       register int c;
+       register int str_size;
+       register char *str = Malloc(str_size = ISTRSIZE);
+       register int pos = 0;
+       
+       LoadChar(c);
+       while (c != stop_char) {
+               if (c == '\n') {
+                       error("newline in %s", nm);
+                       LineNumber++;
+                       break;
+               }
+               if (c == EOI) {
+                       error("end-of-file inside %s", nm);
+                       break;
+               }
+               if (c == '\\') {
+                       LoadChar(c);
+                       if (c == '\n') {
+                               LineNumber++;
+                               LoadChar(c);
+                               continue;
+                       }
+                       c = quoted(c);
+               }
+               str[pos++] = c;
+               if (pos == str_size)
+                       str = Srealloc(str, str_size += RSTRSIZE);
+               LoadChar(c);
+       }
+       str[pos++] = '\0'; /* for filenames etc. */
+       return str;
+}
+
+int
+quoted(c)
+       register int c;
+{      
+       /*      quoted() replaces an escaped character sequence by the
+               character meant.
+       */
+       /* first char after backslash already in c */
+       if (!is_oct(c)) {               /* a quoted char */
+               switch (c) {
+               case 'n':
+                       c = '\n';
+                       break;
+               case 't':
+                       c = '\t';
+                       break;
+               case 'b':
+                       c = '\b';
+                       break;
+               case 'r':
+                       c = '\r';
+                       break;
+               case 'f':
+                       c = '\f';
+                       break;
+               }
+       }
+       else {                          /* a quoted octal */
+               register int oct = 0, cnt = 0;
+
+               do {
+                       oct = oct*8 + (c-'0');
+                       LoadChar(c);
+               } while (is_oct(c) && ++cnt < 3);
+               PushBack();
+               c = oct;
+       }
+       return c&0377;
+}
+
+/* provisional */
+int
+val_in_base(c, base)
+       register int c;
+{
+       return
+               is_dig(c) ? c - '0' :
+               base != 16 ? -1 :
+               is_hex(c) ? (c - 'a' + 10) & 017 :
+               -1;
+}
diff --git a/util/cpp/LLlex.h b/util/cpp/LLlex.h
new file mode 100644 (file)
index 0000000..f85444a
--- /dev/null
@@ -0,0 +1,37 @@
+/* D E F I N I T I O N S   F O R   T H E   L E X I C A L   A N A L Y Z E R */
+
+/*     A token from the input stream is represented by an integer,
+       called a "symbol", but it may have other information associated
+       to it.
+*/
+
+/* the structure of a token:   */
+struct token   {
+       int tok_symb;           /* the token itself */
+       union {
+               int tok_val;            /* numeric values */
+               char *tok_str;          /* string/filespecifier */
+       } tok_data;
+};
+
+#include "file_info.h"
+
+#define tk_symb        tok_symb
+#define tk_val tok_data.tok_val
+#define tk_str tok_data.tok_str
+
+extern struct token dot;
+
+extern int ReplaceMacros;      /* "LLlex.c"    */
+extern int AccFileSpecifier;   /* "LLlex.c"    */
+extern int AccDefined;         /* "LLlex.c"    */
+extern int UnknownIdIsZero;    /* "LLlex.c"    */
+
+extern int NoUnstack;          /* "input.c"    */
+extern int Unstacked;          /* "input.c"    */
+
+extern int err_occurred;       /* "error.c"    */
+
+#define        DOT     dot.tk_symb
+
+#define EOF    (-1)
diff --git a/util/cpp/LLmessage.c b/util/cpp/LLmessage.c
new file mode 100644 (file)
index 0000000..81b1133
--- /dev/null
@@ -0,0 +1,19 @@
+/*             PARSER ERROR ADMINISTRATION             */
+
+#include       "LLlex.h"
+#include       "Lpars.h"
+
+extern char *symbol2str();
+
+LLmessage(tk)  {
+       err_occurred = 1;
+       if (tk < 0)
+               error("garbage at end of line");
+       else if (tk)    {
+               error("%s missing", symbol2str(tk));
+               skipline();
+               DOT = EOF;
+       }
+       else
+               error("%s deleted", symbol2str(DOT));
+}
diff --git a/util/cpp/Makefile b/util/cpp/Makefile
new file mode 100644 (file)
index 0000000..d02b115
--- /dev/null
@@ -0,0 +1,164 @@
+# MAKEFILE FOR (STAND_ALONE) CEM PREPROCESSOR
+
+EMHOME=../..
+MODULES=$(EMHOME)/modules
+MODULESLIB=$(MODULES)/lib
+BIN=$(EMHOME)/lib
+
+# Some paths
+
+# Libraries
+SYSLIB = $(MODULESLIB)/libsystem.a
+STRLIB = $(MODULESLIB)/libstring.a
+PRTLIB = $(MODULESLIB)/libprint.a
+ALLOCLIB = $(MODULESLIB)/liballoc.a
+ASSERTLIB = $(MODULESLIB)/libassert.a
+MALLOC = $(MODULESLIB)/malloc.o
+LIBS = $(PRTLIB) $(STRLIB) $(ALLOCLIB) $(MALLOC) $(ASSERTLIB) $(SYSLIB)
+LIB_INCLUDES = -I$(MODULES)/h -I$(MODULES)/pkg
+
+# Where to install the preprocessor
+CEMPP = $(BIN)/cpp
+
+# What C compiler to use and how
+CC = cc
+COPTIONS =
+LFLAGS = -n
+
+# What parser generator to use and how
+GEN = $(EMHOME)/bin/LLgen
+GENOPTIONS =
+
+# Special #defines during compilation
+CDEFS =        $(LIB_INCLUDES)
+CFLAGS = $(CDEFS) $(COPTIONS) -O#      # we cannot pass the COPTIONS to lint!
+
+# Grammar files and their objects
+LSRC = tokenfile.g expression.g
+LCSRC = tokenfile.c expression.c Lpars.c
+LOBJ = tokenfile.o expression.o Lpars.o
+
+# Objects of hand-written C files
+CSRC = LLlex.c LLmessage.c ch7bin.c ch7mon.c domacro.c \
+       error.c idf.c init.c input.c main.c options.c \
+       preprocess.c replace.c scan.c skip.c tokenname.c next.c expr.c
+COBJ = LLlex.o LLmessage.o ch7bin.o ch7mon.o domacro.o \
+       error.o idf.o init.o input.o main.o options.o \
+       preprocess.o replace.o scan.o skip.o tokenname.o next.o expr.o
+
+PRFILES = Makefile Parameters \
+       make.hfiles make.tokcase make.tokfile LLlex.h bits.h file_info.h \
+       idf.h input.h interface.h macro.h \
+       class.h chtab.c char.tab expression.g $(CSRC)
+
+# Objects of other generated C files
+GOBJ = char.o symbol2str.o
+
+# generated source files
+GSRC = char.c symbol2str.c
+
+# .h files generated by `make hfiles'; PLEASE KEEP THIS UP-TO-DATE!
+GHSRC =        errout.h idfsize.h ifdepth.h lapbuf.h \
+       maxincl.h nparams.h numsize.h obufsize.h \
+       parbufsize.h pathlength.h strsize.h textsize.h \
+       botch_free.h debug.h inputtype.h dobits.h
+
+# Other generated files, for 'make clean' only
+GENERATED = tokenfile.g Lpars.h LLfiles LL.output lint.out \
+       Xref hfiles cfiles charoffset.h
+
+all:   cc
+
+cc:    hfiles LLfiles
+       make "EMHOME="$(EMHOME) cpp
+
+hfiles: Parameters
+       ./make.hfiles Parameters
+       @touch hfiles
+
+LLfiles: $(LSRC)
+       $(GEN) $(GENOPTIONS) $(LSRC)
+       @touch LLfiles
+
+tokenfile.g:   tokenname.c make.tokfile
+       <tokenname.c ./make.tokfile >tokenfile.g
+
+symbol2str.c:  tokenname.c make.tokcase
+       <tokenname.c ./make.tokcase >symbol2str.c
+
+char.c:        char.tab chtab
+       chtab -fchar.tab > char.c
+
+charoffset.h:  chtab char.tab
+       chtab -fchar.tab > /dev/null
+
+chtab: chtab.o
+       $(CC) -o chtab chtab.o
+
+# Objects needed for 'cpp'
+OBJ =  $(COBJ) $(LOBJ) $(GOBJ)
+SRC =  $(CSRC) $(LCSRC) $(GSRC)
+
+cpp:   $(OBJ) Makefile
+       $(CC) $(COPTIONS) $(LFLAGS) $(OBJ) $(LIBS) -o cpp 
+       size cpp
+
+cfiles: hfiles LLfiles $(GSRC)
+       @touch cfiles
+
+install: all
+       cp cpp $(CEMPP)
+
+cmp:   all
+       cmp cpp $(CEMPP)
+
+pr: 
+       @pr $(PRFILES)
+
+opr:
+       make pr | opr
+
+tags:  cfiles
+       ctags $(SRC)
+
+depend:        cfiles
+       sed '/^#AUTOAUTO/,$$d' Makefile >Makefile.new
+       echo '#AUTOAUTOAUTOAUTOAUTOAUTOAUTOAUTOAUTOAUTO' >>Makefile.new
+       $(EMHOME)/bin/mkdep $(SRC) | \
+               sed 's/\.c:/.o:/' >>Makefile.new
+       mv Makefile Makefile.old
+       mv Makefile.new Makefile
+       
+xref:
+       ctags -x `grep "\.[ch]" Files`|sed "s/).*/)/">Xref
+       
+lint:  cfiles
+       lint -bx $(CDEFS) $(SRC) >lint.out
+
+clean:
+       rm -f $(LCSRC) $(OBJ) $(GENERATED) $(GSRC) $(GHSRC) chtab.o chtab
+
+#AUTOAUTOAUTOAUTOAUTOAUTOAUTOAUTOAUTOAUTO
+LLlex.o: LLlex.h Lpars.h bits.h charoffset.h class.h dobits.h file_info.h idf.h idfsize.h input.h inputtype.h numsize.h strsize.h
+LLmessage.o: LLlex.h Lpars.h file_info.h
+ch7bin.o: Lpars.h
+ch7mon.o: Lpars.h
+domacro.o: LLlex.h Lpars.h bits.h botch_free.h charoffset.h class.h debug.h dobits.h file_info.h idf.h idfsize.h ifdepth.h input.h inputtype.h interface.h macro.h nparams.h parbufsize.h textsize.h
+error.o: LLlex.h errout.h file_info.h
+idf.o: idf.h
+init.o: charoffset.h class.h idf.h interface.h macro.h
+input.o: file_info.h input.h inputtype.h
+main.o: file_info.h idfsize.h
+options.o: charoffset.h class.h idf.h idfsize.h macro.h maxincl.h
+preprocess.o: LLlex.h bits.h charoffset.h class.h dobits.h file_info.h idf.h idfsize.h input.h inputtype.h maxincl.h obufsize.h
+replace.o: LLlex.h charoffset.h class.h debug.h file_info.h idf.h input.h inputtype.h interface.h macro.h pathlength.h textsize.h
+scan.o: charoffset.h class.h idf.h input.h inputtype.h interface.h lapbuf.h macro.h nparams.h
+skip.o: LLlex.h charoffset.h class.h file_info.h input.h inputtype.h
+tokenname.o: LLlex.h Lpars.h file_info.h idf.h
+next.o: debug.h
+expr.o: Lpars.h
+tokenfile.o: Lpars.h
+expression.o: LLlex.h Lpars.h file_info.h
+Lpars.o: Lpars.h
+char.o: charoffset.h class.h
+symbol2str.o: Lpars.h
diff --git a/util/cpp/Parameters b/util/cpp/Parameters
new file mode 100644 (file)
index 0000000..21bd8a6
--- /dev/null
@@ -0,0 +1,71 @@
+!File: pathlength.h
+#define PATHLENGTH     1024    /* max. length of path to file          */
+
+
+!File: errout.h
+#define        ERROUT          STDERR  /* file pointer for writing messages    */
+#define        MAXERR_LINE     5       /* maximum number of error messages given
+                                       on the same input line.         */
+
+
+!File: idfsize.h
+#define        IDFSIZE 64      /* maximum significant length of an identifier  */
+
+
+!File: numsize.h
+#define        NUMSIZE 256     /* maximum length of a numeric constant         */
+
+
+!File: nparams.h
+#define        NPARAMS 32      /* maximum number of parameters of macros       */
+
+
+!File: ifdepth.h
+#define        IFDEPTH 256     /* maximum number of nested if-constructions    */
+
+
+!File: maxincl.h
+#define        MAXINCL 16      /* maximum number of #include directories       */
+
+
+!File: lapbuf.h
+#define        LAPBUF  4096    /* size of macro actual parameter buffer        */
+
+
+!File: strsize.h
+#define ISTRSIZE       32      /* minimum number of bytes allocated for
+                                       storing a string                */
+#define RSTRSIZE       8       /* step size in enlarging the memory for
+                                       the storage of a string         */
+
+
+!File: botch_free.h
+#undef BOTCH_FREE      1       /* botch freed memory, as a check       */
+
+
+!File: debug.h
+#undef DEBUG           1       /* perform various self-tests           */
+
+
+!File: parbufsize.h
+#define PARBUFSIZE     1024
+
+
+!File: textsize.h
+#define ITEXTSIZE      32      /* 1st piece of memory for repl. text   */
+#define RTEXTSIZE      32      /* stepsize for enlarging repl.text     */
+
+
+!File: inputtype.h
+#undef INP_READ_IN_ONE 1       /* read input file in one.  */
+                               /* If defined, we cannot read from a pipe */
+
+
+!File: obufsize.h
+#define OBUFSIZE       8192    /* output buffer size */
+
+
+!File: dobits.h
+#define DOBITS         1       /* use trick to reduce symboltable accesses */
+
+
diff --git a/util/cpp/bits.h b/util/cpp/bits.h
new file mode 100644 (file)
index 0000000..9719521
--- /dev/null
@@ -0,0 +1,13 @@
+#include "dobits.h"
+#ifdef DOBITS
+#define bit0   0x01
+#define bit1   0x02
+#define bit2   0x04
+#define bit3   0x08
+#define bit4   0x10
+#define bit5   0x20
+#define bit6   0x40
+#define bit7   0x80
+
+extern char bits[];
+#endif
diff --git a/util/cpp/ch7bin.c b/util/cpp/ch7bin.c
new file mode 100644 (file)
index 0000000..120f8be
--- /dev/null
@@ -0,0 +1,74 @@
+/* EVALUATION OF BINARY OPERATORS */
+
+#include       "Lpars.h"
+
+ch7bin(pval, oper, val)
+       register int *pval, val;
+       int oper;
+{
+       switch (oper)   {
+       case '%':
+               if (val == 0)
+                       error("% by 0");
+               else
+                       *pval = *pval % val;
+               break;
+       case '/':
+               if (val == 0)
+                       error("/ by 0");
+               else
+                       *pval = *pval / val;
+               break;
+       case '*':
+               *pval = *pval * val;
+               break;
+       case '+':
+               *pval = *pval + val;
+               break;
+       case '-':
+               *pval = *pval - val;
+               break;
+       case LEFT:
+               *pval = *pval << val;
+               break;
+       case RIGHT:
+               *pval = *pval >> val;
+               break;
+       case '<':
+               *pval = (*pval < val);
+               break;
+       case '>':
+               *pval = (*pval > val);
+               break;
+       case LESSEQ:
+               *pval = (*pval <= val);
+               break;
+       case GREATEREQ:
+               *pval = (*pval >= val);
+               break;
+       case EQUAL:
+               *pval = (*pval == val);
+               break;
+       case NOTEQUAL:
+               *pval = (*pval != val);
+               break;
+       case '&':
+               *pval = *pval & val;
+               break;
+       case '^':
+               *pval = *pval ^ val;
+               break;
+       case '|':
+               *pval = *pval | val;
+               break;
+       case AND:
+               *pval = (*pval && val);
+               break;
+       case OR:
+               *pval = (*pval || val);
+               break;
+       case ',':
+               *pval = val;
+               break;
+       }
+}
diff --git a/util/cpp/ch7mon.c b/util/cpp/ch7mon.c
new file mode 100644 (file)
index 0000000..5856dba
--- /dev/null
@@ -0,0 +1,19 @@
+/* EVALUATION OF MONADIC OPERATORS */
+
+#include       "Lpars.h"
+
+ch7mon(oper, pval)
+       register int *pval;
+{
+       switch (oper)   {
+       case '~':
+               *pval = ~(*pval);
+               break;
+       case '-':
+               *pval = -(*pval);
+               break;
+       case '!':
+               *pval = !(*pval);
+               break;
+       }
+}
diff --git a/util/cpp/char.tab b/util/cpp/char.tab
new file mode 100644 (file)
index 0000000..d5e8d9a
--- /dev/null
@@ -0,0 +1,36 @@
+%
+%      CHARACTER CLASSES
+%
+% some general settings:
+%F     %s,
+%
+%      START OF TOKEN
+%
+%C
+STGARB:\000-\377
+STSKIP:\r \t
+STNL:\n\f\013
+STCOMP:!&<=>|
+STSIMP:-%()+*,/:?^~
+STCHAR:'
+STIDF:a-zA-Z_
+STNUM:0-9
+STSTR:"
+STEOI:\200
+%T/* character classes */
+%T#include "class.h"
+%Tchar tkclass[] = {
+%p
+%T};
+%
+%      other kinds of classes
+%
+%C
+_D_|_H_|_I_|_O_:0-7
+_D_|_H_|_I_:89
+_H_|_I_:a-fA-F
+_I_:g-zG-Z_
+%Tchar tk2class[] = {
+%F     %s,
+%p
+%T};
diff --git a/util/cpp/chtab.c b/util/cpp/chtab.c
new file mode 100644 (file)
index 0000000..8b369f3
--- /dev/null
@@ -0,0 +1,316 @@
+/*
+       chtab - character table generator 
+
+       Author: Erik Baalbergen (..tjalk!erikb)
+       Modified by Ceriel Jacobs
+*/
+
+#include <stdio.h> 
+
+static char *RcsId = "$Header$";
+
+#define MAXBUF 256
+#define TABSIZE 257
+#define COMCOM '-'
+#define FILECOM        '%'
+
+int InputForm = 'c';
+char OutputForm[MAXBUF] = "%s,\n";
+char *Table[TABSIZE];
+char *Name;
+char *ProgCall;
+int signedch = 0;
+char *OutputName;
+char *chroffsetfile = "charoffset.h";
+
+main(argc, argv)
+       char *argv[];
+{
+       char c = 0200;
+       int i = c;
+
+       if (i < 0) signedch = 1;
+
+       ProgCall = *argv++;
+       argc--;
+       while (argc-- > 0) {
+               if (**argv == COMCOM) {
+                       option(*argv++);
+               }
+               else {
+                       process(*argv++, InputForm);
+               }
+       }
+       MkCharIndex();
+}
+
+MkCharIndex()
+{
+       FILE *fp;
+
+       if ((fp = fopen(chroffsetfile, "w")) == NULL) {
+               fprintf(stderr, "%s: cannot write file %s\n", ProgCall, chroffsetfile);
+               exit(1);
+       }
+       if (signedch) {
+               fputs("#define CharOffset       128\n");
+       }
+       else    fputs("#define CharOffset       0\n");
+       fclose(fp);
+}
+
+char *
+Salloc(s)
+       char *s;
+{
+       char *malloc();
+       char *ns = malloc(strlen(s) + 1);
+
+       if (ns) {
+               strcpy(ns, s);
+       }
+       return ns;
+}
+
+option(str)
+       char *str;
+{
+       /*      note that *str indicates the source of the option:
+               either COMCOM (from command line) or FILECOM (from a file).
+       */
+       switch (*++str) {
+
+       case ' ':       /* command */
+       case '\t':
+       case '\0':
+               break;
+       case 'I':
+               InputForm = *++str;
+               break;
+       case 'f':
+               if (*++str == '\0') {
+                       fprintf(stderr, "%s: -f: name expected\n", ProgCall);
+                       exit(1);
+               }
+               DoFile(str);
+               break;
+       case 'F':
+               sprintf(OutputForm, "%s\n", ++str);
+               break;
+       case 'T':
+               printf("%s\n", ++str);
+               break;
+       case 'p':
+               PrintTable();
+               break;
+       case 'C':
+               ClearTable();
+               break;
+       case 'H':
+               if (*++str == '\0') {
+                       fprintf(stderr, "%s: -H: name expected\n", ProgCall);
+               }
+               else    chroffsetfile = ++str;
+               break;
+       default:
+               fprintf(stderr, "%s: bad option -%s\n", ProgCall, str);
+       }
+}
+
+ClearTable()
+{
+       register i;
+
+       for (i = 0; i < TABSIZE; i++) {
+               Table[i] = 0;
+       }
+}
+
+PrintTable()
+{
+       register i;
+
+       for (i = 0; i < TABSIZE; i++) {
+               if (Table[i]) {
+                       printf(OutputForm, Table[i]);
+               }
+               else {
+                       printf(OutputForm, "0");
+               }
+       }
+}
+
+process(str, format)
+       char *str;
+{
+       char *cstr = str;
+       char *Name = cstr;      /* overwrite original string!   */
+
+       /* strip of the entry name
+       */
+       while (*str && *str != ':') {
+               if (*str == '\\') {
+                       ++str;
+               }
+               *cstr++ = *str++;
+       }
+
+       if (*str != ':') {
+               fprintf(stderr, "%s: bad specification: \"%s\", ignored\n",
+                       ProgCall, Name);
+               return 0;
+       }
+       *cstr = '\0';
+       str++;
+
+       switch (format) {
+
+       case 'c':
+               return c_proc(str, Name);
+       default:
+               fprintf(stderr, "%s: bad input format\n", ProgCall);
+       }
+       return 0;
+}
+
+c_proc(str, Name)
+       char *str;
+       char *Name;
+{
+       int ch, ch2;
+       int quoted();
+       char *name = Salloc(Name);
+
+       while (*str)    {
+               if (*str == '\\')       {
+                       ch = quoted(&str);
+               }
+               else    {
+                       ch = *str++;
+               }
+               if (*str == '-')        {
+                       if (*++str == '\\')     {
+                               ch2 = quoted(&str);
+                       }
+                       else    {
+                               if (ch2 = *str++);
+                               else str--;
+                       }
+                       if (ch > ch2) {
+                               fprintf(stderr, "%s: bad range\n", ProgCall);
+                               return 0;
+                       }
+#define ind(X) (signedch?(X>=128?X-128:X+128):X)
+                       while (ch <= ch2) {
+                               Table[ind(ch)] = name;
+                               ch++;
+                       }
+               }
+               else    {
+                       if (ch >= 0 && ch <= 255)
+                               Table[ind(ch)] = name;
+               }
+       }
+       Table[256] = Table[0];
+       return 1;
+}
+
+int
+quoted(pstr)
+       char **pstr;
+{
+       register int ch;
+       register int i;
+       register char *str = *pstr;
+
+       if ((*++str >= '0') && (*str <= '9'))   {
+               ch = 0;
+               for (i = 0; i < 3; i++) {
+                       ch = 8 * ch + (*str - '0');
+                       if (*++str < '0' || *str > '9')
+                               break;
+               }
+       }
+       else    {
+               switch (*str++) {
+
+               case 'n':
+                       ch = '\n';
+                       break;
+               case 't':
+                       ch = '\t';
+                       break;
+               case 'b':
+                       ch = '\b';
+                       break;
+               case 'r':
+                       ch = '\r';
+                       break;
+               case 'f':
+                       ch = '\f';
+                       break;
+               default :
+                       ch = *str;
+               }
+       }
+       *pstr = str;
+       return ch & 0377;
+}
+
+int
+stoi(str)
+       char *str;
+{
+       register i = 0;
+
+       while (*str >= '0' && *str <= '9') {
+               i = i * 10 + *str++ - '0';
+       }
+       return i;
+}
+
+char *
+getline(s, n, fp)
+       char *s;
+       FILE *fp;
+{
+       register c = getc(fp);
+       char *str = s;
+
+       while (n--) {
+               if (c == EOF) {
+                       return NULL;
+               }
+               else
+               if (c == '\n') {
+                       *str++ = '\0';
+                       return s;
+               }
+               *str++ = c;
+               c = getc(fp);
+       }
+       s[n - 1] = '\0';
+       return s;
+}
+
+#define BUFSIZE 1024
+
+DoFile(name)
+       char *name;
+{
+       char text[BUFSIZE];
+       FILE *fp;
+
+       if ((fp = fopen(name, "r")) == NULL) {
+               fprintf(stderr, "%s: cannot read file %s\n", ProgCall, name);
+               exit(1);
+       }
+       while (getline(text, BUFSIZE, fp) != NULL) {
+               if (text[0] == FILECOM) {
+                       option(text);
+               }
+               else {
+                       process(text, InputForm);
+               }
+       }
+}
diff --git a/util/cpp/class.h b/util/cpp/class.h
new file mode 100644 (file)
index 0000000..3697fd5
--- /dev/null
@@ -0,0 +1,41 @@
+/* U S E   O F   C H A R A C T E R   C L A S S E S */
+
+/*     As a starter, chars are divided into classes, according to which
+       token they can be the start of.
+       At present such a class number is supposed to fit in 4 bits.
+*/
+
+#include "charoffset.h"
+
+#define        class(ch)       ((tkclass+CharOffset)[ch])
+
+/*     Being the start of a token is, fortunately, a mutual exclusive
+       property, so, as there are less than 16 classes they can be
+       packed in 4 bits.
+*/
+
+#define        STSKIP  0       /* spaces and so on: skipped characters         */
+#define        STNL    1       /* newline character(s): update linenumber etc. */
+#define        STGARB  2       /* garbage ascii character: not allowed         */
+#define        STSIMP  3       /* this character can occur as token            */
+#define        STCOMP  4       /* this one can start a compound token          */
+#define        STIDF   5       /* being the initial character of an identifier */
+#define        STCHAR  6       /* the starter of a character constant          */
+#define        STSTR   7       /* the starter of a string                      */
+#define        STNUM   8       /* the starter of a numeric constant            */
+#define        STEOI   9       /* End-Of-Information mark                      */
+
+/*     But occurring inside a token is not, so we need 1 bit for each
+       class.
+*/
+#define _I_    01
+#define _O_    02
+#define _D_    04
+#define _H_    010
+
+#define        in_idf(ch)      ((tk2class+CharOffset)[ch] & _I_)
+#define        is_oct(ch)      ((tk2class+CharOffset)[ch] & _O_)
+#define        is_dig(ch)      ((tk2class+CharOffset)[ch] & _D_)
+#define        is_hex(ch)      ((tk2class+CharOffset)[ch] & _H_)
+
+extern char tkclass[], tk2class[];
diff --git a/util/cpp/domacro.c b/util/cpp/domacro.c
new file mode 100644 (file)
index 0000000..2b90844
--- /dev/null
@@ -0,0 +1,693 @@
+/* $Header$ */
+/* PREPROCESSOR: CONTROLLINE INTERPRETER */
+
+#include       "interface.h"
+#include       <em_arith.h>
+#include       "LLlex.h"
+#include       "Lpars.h"
+#include       "debug.h"
+#include       "idf.h"
+#include       "input.h"
+
+#include       "ifdepth.h"     
+#include       "botch_free.h"  
+#include       "nparams.h"     
+#include       "parbufsize.h"  
+#include       "textsize.h"    
+#include       "idfsize.h"     
+#include       <assert.h>
+#include       <alloc.h>
+#include       "class.h"
+#include       "macro.h"
+#include       "bits.h"
+
+IMPORT char *inctable[];       /* list of include directories          */
+IMPORT char *getwdir();
+PRIVATE char ifstack[IFDEPTH]; /* if-stack: the content of an entry is */
+                               /* 1 if a corresponding ELSE has been   */
+                               /* encountered.                         */
+PRIVATE int nestlevel = -1;    /* initially no nesting level.          */
+
+PRIVATE char *
+GetIdentifier()
+{
+       /*      returns a pointer to the descriptor of the identifier that is
+               read from the input stream. A null-pointer is returned if
+               the input does not contain an identifier.
+               The substitution of macros is disabled.
+       */
+       int tok;
+       struct token tk;
+
+       ReplaceMacros = 0;
+       tok = GetToken(&tk);
+       ReplaceMacros = 1;
+       return tok == IDENTIFIER ? tk.tk_str : (char *)0;
+}
+
+/*     domacro() is the control line interpreter. The '#' has already
+       been read by the lexical analyzer by which domacro() is called.
+       The token appearing directly after the '#' is obtained by calling
+       the basic lexical analyzing function GetToken() and is interpreted
+       to perform the action belonging to that token.
+       An error message is produced when the token is not recognized,
+       i.e. it is not one of "define" .. "undef" , integer or newline.
+*/
+EXPORT
+domacro()
+{
+       struct token tk;        /* the token itself                     */
+       register struct idf *id;
+
+       switch(GetToken(&tk)) {         /* select control line action   */
+       case IDENTIFIER:                /* is it a macro keyword?       */
+               id = findidf(tk.tk_str);
+               if (!id) {
+                       error("%s: unknown control", tk.tk_str);
+                       PushBack();
+                       skipline();
+                       free(tk.tk_str);
+                       break;
+               }
+               free(tk.tk_str);
+               switch (id->id_resmac) {
+               case K_DEFINE:                          /* "define"     */
+                       do_define();
+                       break;
+               case K_ELIF:                            /* "elif"       */
+                       do_elif();
+                       break;
+               case K_ELSE:                            /* "else"       */
+                       do_else();
+                       break;
+               case K_ENDIF:                           /* "endif"      */
+                       do_endif();
+                       break;
+               case K_IF:                              /* "if"         */
+                       do_if();
+                       break;
+               case K_IFDEF:                           /* "ifdef"      */
+                       do_ifdef(1);
+                       break;
+               case K_IFNDEF:                          /* "ifndef"     */
+                       do_ifdef(0);
+                       break;
+               case K_INCLUDE:                         /* "include"    */
+                       do_include();
+                       break;
+               case K_LINE:                            /* "line"       */
+                       /*      set LineNumber and FileName according to
+                               the arguments.
+                       */
+                       if (GetToken(&tk) != INTEGER) {
+                               error("#line without linenumber");
+                               PushBack();
+                               skipline();
+                       }
+                       else
+                               do_line((unsigned int)tk.tk_val);
+                       break;
+               case K_UNDEF:                           /* "undef"      */
+                       do_undef();
+                       break;
+               default:
+                       /* invalid word seen after the '#'      */
+                       error("%s: unknown control", id->id_text);
+                       PushBack();
+                       skipline();
+               }
+               break;
+       case INTEGER:           /* # <integer> [<filespecifier>]?       */
+               do_line((unsigned int)tk.tk_val);
+               break;
+       case EOI:       /* only `#' on this line: do nothing, ignore    */
+               break;
+       default:        /* invalid token following '#'          */
+               error("illegal # line");
+               PushBack();
+               skipline();
+       }
+}
+
+PRIVATE
+skip_block()
+{
+       /*      skip_block() skips the input from
+               1)      a false #if, #ifdef, #ifndef or #elif until the
+                       corresponding #elif (resulting in true), #else or
+                       #endif is read.
+               2)      a #else corresponding to a true #if, #ifdef,
+                       #ifndef or #elif until the corresponding #endif is
+                       seen.
+       */
+       register int ch;
+       register int skiplevel = nestlevel; /* current nesting level    */
+       struct token tk;
+       struct idf *id;
+
+       NoUnstack++;
+       for (;;) {
+               LoadChar(ch);   /* read first character after newline   */
+               if (ch != '#') {
+                       if (ch == EOI) {
+                               NoUnstack--;
+                               return;
+                       }
+                       PushBack();
+                       skipline();
+                       continue;
+               }
+               if (GetToken(&tk) != IDENTIFIER) {
+                       PushBack();
+                       skipline();
+                       continue;
+               }
+               /*      an IDENTIFIER: look for #if, #ifdef and #ifndef
+                       without interpreting them.
+                       Interpret #else, #elif and #endif if they occur
+                       on the same level.
+               */
+               id = findidf(tk.tk_str);
+               free(tk.tk_str);
+               switch(id->id_resmac) {
+               case K_IF:
+               case K_IFDEF:
+               case K_IFNDEF:
+                       push_if();
+                       continue;
+               case K_ELIF:
+                       if (nestlevel == skiplevel) {
+                               nestlevel--;
+                               push_if();
+                               if (ifexpr()) {
+                                       NoUnstack--;
+                                       return;
+                               }
+                       }
+                       break;
+               case K_ELSE:
+                       ++(ifstack[nestlevel]);
+                       if (nestlevel == skiplevel) {
+                               PushBack();
+                               skipline();
+                               NoUnstack--;
+                               return;
+                       }
+                       break;
+               case K_ENDIF:
+                       assert(nestlevel >= 0);
+                       if (nestlevel == skiplevel) {
+                               PushBack();
+                               skipline();
+                               nestlevel--;
+                               NoUnstack--;
+                               return;
+                       }
+                       nestlevel--;
+                       break;
+               }
+       }
+}
+
+PRIVATE
+ifexpr()
+{
+       /*      ifexpr() returns whether the restricted constant
+               expression following #if or #elif evaluates to true.  This
+               is done by calling the LLgen generated subparser for
+               constant expressions.  The result of this expression will
+               be given in the extern long variable "ifval".
+       */
+       IMPORT arith ifval;
+       int errors = err_occurred;
+
+       ifval = (arith)0;
+       AccDefined = 1;
+       UnknownIdIsZero = 1;
+       PushLex();      /* NEW parser */
+       If_expr();      /* invoke constant expression parser    */
+       PopLex();       /* OLD parser */
+       AccDefined = 0;
+       UnknownIdIsZero = 0;
+       return (errors == err_occurred) && (ifval != (arith)0);
+}
+
+PRIVATE
+do_include()
+{
+       /*      do_include() performs the inclusion of a file.
+       */
+       char *filenm;
+       char *result;
+       int tok;
+       struct token tk;
+
+       AccFileSpecifier = 1;
+       if (((tok = GetToken(&tk)) == FILESPECIFIER) || tok == STRING)
+               filenm = tk.tk_str;
+       else {
+               error("bad include syntax");
+               filenm = (char *)0;
+       }
+       AccFileSpecifier = 0;
+       PushBack();
+       skipline();
+       inctable[0] = WorkingDir;
+       if (filenm) {
+               if (!InsertFile(filenm, &inctable[tok==FILESPECIFIER],&result)){
+                       error("cannot find include file \"%s\"", filenm);
+               }
+               else {
+                       WorkingDir = getwdir(result);
+                       FileName = result;
+                       LineNumber = 1;
+               }
+       }
+}
+
+PRIVATE
+do_define()
+{
+       /*      do_define() interprets a #define control line.
+       */
+       char *str;
+       int nformals = -1;      /* keep track of the number of formals  */
+       char *formals[NPARAMS]; /* pointers to the names of the formals */
+       char parbuf[PARBUFSIZE];                /* names of formals     */
+       char *repl_text;        /* start of the replacement text        */
+       int length;             /* length of the replacement text       */
+       register ch;
+       char *get_text();
+
+       /* read the #defined macro's name       */
+       if (!(str = GetIdentifier())) {
+               error("#define: illegal macro name");
+               PushBack();
+               skipline();
+               return;
+       }
+       /*      there is a formal parameter list if the identifier is
+               followed immediately by a '('. 
+       */
+       LoadChar(ch);
+       if (ch == '(') {
+               if ((nformals = getparams(formals, parbuf)) == -1) {
+                       PushBack();
+                       skipline();
+                       return; /* an error occurred    */
+               }
+               LoadChar(ch);
+       }
+       /* read the replacement text if there is any                    */
+       ch = skipspaces(ch);    /* find first character of the text     */
+       assert(ch != EOI);
+       if (class(ch) == STNL) {
+               /*      Treat `#define something' as `#define something ""'
+               */
+               repl_text = "";
+               length = 0;
+       }
+       else {
+               PushBack();
+               repl_text = get_text((nformals > 0) ? formals : 0, &length);
+       }
+       macro_def(str2idf(str, 0), repl_text, nformals, length, NOFLAG);
+       LineNumber++;
+}
+
+PRIVATE
+push_if()
+{
+       if (nestlevel >= IFDEPTH)
+               fatal("too many nested #if/#ifdef/#ifndef");
+       else
+               ifstack[++nestlevel] = 0;
+}
+
+PRIVATE
+do_elif()
+{
+       if (nestlevel < 0 || (ifstack[nestlevel])) {
+               error("#elif without corresponding #if");
+               PushBack();
+               skipline();
+       }
+       else { /* restart at this level as if a #if is detected.  */
+               nestlevel--;
+               push_if();
+               skip_block();
+       }
+}
+
+PRIVATE
+do_else()
+{
+       PushBack();
+       skipline();
+       if (nestlevel < 0 || (ifstack[nestlevel]))
+               error("#else without corresponding #if");
+       else {  /* mark this level as else-d            */
+               ++(ifstack[nestlevel]);
+               skip_block();
+       }
+}
+
+PRIVATE
+do_endif()
+{
+       PushBack();
+       skipline();
+       if (nestlevel-- < 0)
+               error("#endif without corresponding #if");
+}
+
+PRIVATE
+do_if()
+{
+       push_if();
+       if (!ifexpr())  /* a false #if/#elif expression */
+               skip_block();
+}
+
+PRIVATE
+do_ifdef(how)
+{
+       register struct idf *id;
+       char *str;
+
+       /*      how == 1 : ifdef; how == 0 : ifndef
+       */
+       push_if();
+       str = GetIdentifier();
+       if (!str) {
+               error("illegal #ifdef construction");
+               id = 0;
+       }
+       else    {
+               id = findidf(str);
+               free(str);
+       }
+
+       /* The next test is a shorthand for:
+               (how && !id->id_macro) || (!how && id->id_macro)
+       */
+       if (how ^ (id && id->id_macro != 0))
+               skip_block();
+       else {
+               PushBack();
+               skipline();
+       }
+}
+
+PRIVATE
+do_undef()
+{
+       register struct idf *id;
+       register char *str = GetIdentifier();
+
+       /* Forget a macro definition.   */
+       if (str) {
+               if (id = findidf(str)) {
+                       if (id->id_macro) { /* forget the macro */
+                               free_macro(id->id_macro);
+                               id->id_macro = (struct macro *) 0;
+                       } /* else: don't complain */
+               }
+               free(str);
+       }
+       else
+               error("illegal #undef construction");
+       PushBack();
+       skipline();
+}
+
+PRIVATE
+do_line(l)
+       unsigned int l;
+{
+       struct token tk;
+
+       LineNumber = l - 1;     /* the number of the next input line */
+       if (GetToken(&tk) == STRING)    /* is there a filespecifier? */
+               FileName = tk.tk_str;
+       PushBack();
+       skipline();
+}
+
+PRIVATE int
+getparams(buf, parbuf)
+       char *buf[];
+       char parbuf[];
+{
+       /*      getparams() reads the formal parameter list of a macro
+               definition.
+               The number of parameters is returned.
+               As a formal parameter list is expected when calling this
+               routine, -1 is returned if an error is detected, for
+               example:
+                       #define one(1), where 1 is not an identifier.
+               Note that the '(' has already been eaten.
+               The names of the formal parameters are stored into parbuf.
+       */
+       register char **pbuf = &buf[0];
+       register int c;
+       register char *ptr = &parbuf[0];
+       register char **pbuf2;
+
+       LoadChar(c);
+       c = skipspaces(c);
+       if (c == ')') {         /* no parameters: #define name()        */
+               *pbuf = (char *) 0;
+               return 0;
+       }
+       for (;;) {              /* eat the formal parameter list        */
+               if (class(c) != STIDF) {        /* not an identifier    */
+                       error("#define: bad formal parameter");
+                       return -1;
+               }
+               *pbuf = ptr;    /* name of the formal   */
+               *ptr++ = c;
+               if (ptr >= &parbuf[PARBUFSIZE])
+                       fatal("formal parameter buffer overflow");
+               do {                    /* eat the identifier name      */
+                       LoadChar(c);
+                       *ptr++ = c;
+                       if (ptr >= &parbuf[PARBUFSIZE])
+                               fatal("formal parameter buffer overflow");
+               } while (in_idf(c));
+               *(ptr - 1) = '\0';      /* mark end of the name         */
+
+               /*      Check if this formal parameter is already used.
+                       Usually, macros do not have many parameters, so ...
+               */
+               for (pbuf2 = pbuf - 1; pbuf2 >= &buf[0]; pbuf2--) {
+                       if (!strcmp(*pbuf2, *pbuf)) {
+                               warning("formal parameter \"%s\" already used",
+                                       *pbuf);
+                       }
+               }
+
+               pbuf++;
+               c = skipspaces(c);
+               if (c == ')') { /* end of the formal parameter list     */
+                       *pbuf = (char *) 0;
+                       return pbuf - buf;
+               }
+               if (c != ',') {
+                       error("#define: bad formal parameter list");
+                       return -1;
+               }
+               LoadChar(c);
+               c = skipspaces(c);
+       }
+       /*NOTREACHED*/
+}
+
+EXPORT
+macro_def(id, text, nformals, length, flags)
+       register struct idf *id;
+       char *text;
+{
+       /*      macro_def() puts the contents and information of a macro
+               definition into a structure and stores it into the symbol
+               table entry belonging to the name of the macro.
+               A warning is given if the definition overwrites another.
+       */
+       register struct macro *newdef = id->id_macro;
+       
+       if (newdef) {           /* is there a redefinition?     */
+               if (macroeq(newdef->mc_text, text))
+                       return;
+               warning("redefine \"%s\"", id->id_text);
+       }
+       else {
+#ifdef DOBITS
+               register char *p = id->id_text;
+#define setbit(bx)     if (!*p) goto go_on; bits[*p++] |= (bx)
+               setbit(bit0);
+               setbit(bit1);
+               setbit(bit2);
+               setbit(bit3);
+               setbit(bit4);
+               setbit(bit5);
+               setbit(bit6);
+               setbit(bit7);
+               
+       go_on:
+#endif
+               id->id_macro = newdef = new_macro();
+       }
+       newdef->mc_text = text;         /* replacement text     */
+       newdef->mc_nps  = nformals;     /* nr of formals        */
+       newdef->mc_length = length;     /* length of repl. text */
+       newdef->mc_flag = flags;        /* special flags        */
+       newdef->mc_count = 0;
+}
+
+PRIVATE int
+find_name(nm, index)
+       char *nm, *index[];
+{
+       /*      find_name() returns the index of "nm" in the namelist
+               "index" if it can be found there.  0 is returned if it is
+               not there.
+       */
+       register char **ip = &index[0];
+
+       while (*ip)
+               if (strcmp(nm, *ip++) == 0)
+                       return ip - &index[0];
+       /* arrived here, nm is not in the name list.    */
+       return 0;
+}
+
+PRIVATE char *
+get_text(formals, length)
+       char *formals[];
+       int *length;
+{
+       /*      get_text() copies the replacement text of a macro
+               definition with zero, one or more parameters, thereby
+               substituting each formal parameter by a special character
+               (non-ascii: 0200 & (order-number in the formal parameter
+               list)) in order to substitute this character later by the
+               actual parameter.  The replacement text is copied into
+               itself because the copied text will contain fewer or the
+               same amount of characters.  The length of the replacement
+               text is returned.
+
+               Implementation:
+               finite automaton : we are only interested in
+               identifiers, because they might be replaced by some actual
+               parameter.  Other tokens will not be seen as such.
+       */
+       register int c;
+       register int text_size;
+       char *text = Malloc(text_size = ITEXTSIZE);
+       register int pos = 0;
+
+       LoadChar(c);
+
+       while ((c != EOI) && (class(c) != STNL)) {
+               if (c == '\\') {        /* check for "\\\n"     */
+                       LoadChar(c);
+                       if (c == '\n') {
+                               /*      More than one line is used for the
+                                       replacement text.
+                                       Replace "\\\n" by " ".
+                               */
+                               text[pos++] = ' ';
+                               ++LineNumber;
+                               LoadChar(c);
+                       }
+                       else
+                               text[pos++] = '\\';
+                       if (pos == text_size)
+                               text = Srealloc(text, text_size += RTEXTSIZE);
+               }
+               else
+               if ( c == '/') {
+                       LoadChar(c);
+                       if (c == '*') {
+                               skipcomment();
+                               text[pos++] = ' ';
+                               LoadChar(c);
+                       }
+                       else
+                               text[pos++] = '/';
+                       if (pos == text_size)
+                               text = Srealloc(text, text_size += RTEXTSIZE);
+               }
+               else
+               if (formals && class(c) == STIDF) {
+                       char id_buf[IDFSIZE + 1];
+                       register id_size = 0;
+                       register n;
+
+                       /* read identifier: it may be a formal parameter */
+                       id_buf[id_size++] = c;
+                       do {
+                               LoadChar(c);
+                               if (id_size <= IDFSIZE)
+                                       id_buf[id_size++] = c;
+                       } while (in_idf(c));
+                       id_buf[--id_size] = '\0';
+                       if (n = find_name(id_buf, formals)) {
+                               /* construct the formal parameter mark  */
+                               text[pos++] = FORMALP | (char) n;
+                               if (pos == text_size)
+                                       text = Srealloc(text,
+                                               text_size += RTEXTSIZE);
+                       }
+                       else {
+                               register char *ptr = &id_buf[0];
+
+                               while (pos + id_size >= text_size)
+                                       text = Srealloc(text,
+                                               text_size += RTEXTSIZE);
+                               while (text[pos++] = *ptr++) ;
+                               pos--;
+                       }
+               }
+               else {
+                       text[pos++] = c;
+                       if (pos == text_size)
+                               text = Srealloc(text, text_size += RTEXTSIZE);
+                       LoadChar(c);
+               }
+       }
+       text[pos++] = '\0';
+       *length = pos - 1;
+       return text;
+}
+
+#define        BLANK(ch)       ((ch == ' ') || (ch == '\t'))
+
+/*     macroeq() decides whether two macro replacement texts are
+       identical.  This version compares the texts, which occur
+       as strings, without taking care of the leading and trailing
+       blanks (spaces and tabs).
+*/
+PRIVATE
+macroeq(s, t)
+       register char *s, *t;
+{
+       
+       /* skip leading spaces  */
+       while (BLANK(*s)) s++;
+       while (BLANK(*t)) t++;
+       /* first non-blank encountered in both strings  */
+       /* The actual comparison loop:                  */
+       while (*s && *s == *t)
+               s++, t++;
+       /* two cases are possible when arrived here:    */
+       if (*s == '\0') {       /* *s == '\0'           */
+               while (BLANK(*t)) t++;
+               return *t == '\0';
+       }
+       else    {               /* *s != *t             */
+               while (BLANK(*s)) s++;
+               while (BLANK(*t)) t++;
+               return (*s == '\0') && (*t == '\0');
+       }
+}
diff --git a/util/cpp/error.c b/util/cpp/error.c
new file mode 100644 (file)
index 0000000..f19ce53
--- /dev/null
@@ -0,0 +1,59 @@
+/*     E R R O R   A N D  D I A G N O S T I C   R O U T I N E S        */
+
+#include       <system.h>
+
+#include       "errout.h"
+#include       "LLlex.h"
+
+/*     This file contains the (non-portable) error-message and diagnostic
+       functions.  Beware, they are called with a variable number of
+       arguments!
+*/
+
+int err_occurred;
+
+err_hdr(s)
+       char *s;
+{
+       fprint(ERROUT, "\"%s\", line %d: %s", FileName, LineNumber, s);
+}
+
+/*VARARGS1*/
+error(fmt, args)
+       char *fmt;
+{
+       err_hdr("");
+       doprnt(ERROUT, fmt, &args);
+       fprint(ERROUT, "\n");
+}
+
+/*VARARGS1*/
+warning(fmt, args)
+       char *fmt;
+{
+       err_hdr("warning ");
+       doprnt(ERROUT, fmt, &args);
+       fprint(ERROUT, "\n");
+}
+
+/*VARARGS1*/
+crash(fmt, args)
+       char *fmt;
+       int args;
+{
+       err_hdr("crash ");
+       doprnt(ERROUT, fmt, &args);
+       fprint(ERROUT, "\n");
+       sys_stop(S_ABORT);
+}
+
+/*VARARGS1*/
+fatal(fmt, args)
+       char *fmt;
+       int args;
+{
+       err_hdr("fatal ");
+       doprnt(ERROUT, fmt, &args);
+       fprint(ERROUT, "\n");
+       sys_stop(S_EXIT);
+}
diff --git a/util/cpp/expr.c b/util/cpp/expr.c
new file mode 100644 (file)
index 0000000..45ce1a0
--- /dev/null
@@ -0,0 +1,53 @@
+/* OPERATOR HANDLING */
+
+#include       "Lpars.h"
+
+int
+rank_of(oper)
+       int oper;
+{
+       /*      The rank of the operator oper is returned.
+       */
+       switch (oper)   {
+       default:
+               return 0;
+       case '(':
+               return 1;
+       case '!':
+               return 2;
+       case '*':
+       case '/':
+       case '%':
+               return 3;
+       case '+':
+       case '-':
+               return 4;
+       case LEFT:
+       case RIGHT:
+               return 5;
+       case '<':
+       case '>':
+       case LESSEQ:
+       case GREATEREQ:
+               return 6;
+       case EQUAL:
+       case NOTEQUAL:
+               return 7;
+       case '&':
+               return 8;
+       case '^':
+               return 9;
+       case '|':
+               return 10;
+       case AND:
+               return 11;
+       case OR:
+               return 12;
+       case '?':
+       case ':':
+               return 13;
+       case ',':
+               return 15;
+       }
+       /*NOTREACHED*/
+}
diff --git a/util/cpp/expression.g b/util/cpp/expression.g
new file mode 100644 (file)
index 0000000..109b564
--- /dev/null
@@ -0,0 +1,124 @@
+/*     EXPRESSION SYNTAX PARSER        */
+
+%lexical       LLlex;
+%start         If_expr, if_expression;
+
+{
+#include       "LLlex.h"
+
+extern int ifval;
+}
+
+if_expression
+:
+       constant_expression(&ifval)
+;
+
+/* 7.1 */
+primary(int *pval;)
+:
+       constant(pval)
+|
+       '(' expression(pval) ')'
+;
+
+unary(int *pval;)
+       {int oper;}
+:
+       unop(&oper)
+       unary(pval)
+       { ch7mon(oper, pval); }
+|
+       primary(pval)
+;
+
+binary_expression(int maxrank; int *pval;)
+       {int oper; int val1;}
+:
+       unary(pval)
+       [%while (rank_of(DOT) <= maxrank)
+               binop(&oper)
+               binary_expression(rank_of(oper)-1, &val1)
+               {
+                       ch7bin(pval, oper, val1);
+               }
+       ]*
+;
+
+/* 7.13 */
+conditional_expression(int *pval;)
+       {int val1 = 0, val2 = 0;}
+:
+       /* allow all binary operators */
+       binary_expression(rank_of('?') - 1, pval)
+       [       '?'
+               expression(&val1)
+               ':'
+               assignment_expression(&val2)
+               { *pval = (*pval ? val1 : val2); }
+       ]?
+;
+
+/* 7.14 */
+assignment_expression(int *pval;)
+:
+       conditional_expression(pval)
+;
+
+/* 7.15 */
+expression(int *pval;)
+       {int val1;}
+:
+       assignment_expression(pval)
+       [       ','
+               assignment_expression(&val1)
+               {
+                       ch7bin(pval, ',', val1);
+               }
+       ]*
+;
+
+unop(int *oper;) :
+       [ '-' | '!' | '~' ]
+       {*oper = DOT;}
+;
+
+multop:
+       '*' | '/' | '%'
+;
+
+addop:
+       '+' | '-'
+;
+
+shiftop:
+       LEFT | RIGHT
+;
+
+relop:
+       '<' | '>' | LESSEQ | GREATEREQ
+;
+
+eqop:
+       EQUAL | NOTEQUAL
+;
+
+arithop:
+       multop | addop | shiftop
+|
+       '&' | '^' | '|'
+;
+
+binop(int *oper;) :
+       [ arithop | relop | eqop | AND | OR ]
+       {*oper = DOT;}
+;
+
+constant(int *pval;) :
+       INTEGER
+       {*pval = dot.tk_val;}
+;
+
+constant_expression (int *pval;) :
+       assignment_expression(pval)
+;
diff --git a/util/cpp/file_info.h b/util/cpp/file_info.h
new file mode 100644 (file)
index 0000000..8a3c8a8
--- /dev/null
@@ -0,0 +1,13 @@
+/* F I L E   I N F O R M A T I O N   S T R U C T U R E */
+
+struct file_info {
+       unsigned int    fil_lino;
+       char            *fil_name;
+       char            *fil_wdir;
+};
+
+#define LineNumber     finfo.fil_lino
+#define FileName       finfo.fil_name
+#define WorkingDir     finfo.fil_wdir
+
+extern struct file_info finfo; /* input.c */
diff --git a/util/cpp/idf.c b/util/cpp/idf.c
new file mode 100644 (file)
index 0000000..4bbd88a
--- /dev/null
@@ -0,0 +1,2 @@
+#include "idf.h"
+#include <idf_pkg.body>
diff --git a/util/cpp/idf.h b/util/cpp/idf.h
new file mode 100644 (file)
index 0000000..a017b9c
--- /dev/null
@@ -0,0 +1,11 @@
+struct id_usr {
+       struct macro *idu_macro;
+       int idu_resmac;
+};
+
+#define IDF_TYPE struct id_usr
+#define IDF_HSIZE 6
+#define id_macro id_user.idu_macro
+#define id_resmac id_user.idu_resmac
+
+#include <idf_pkg.spec>
diff --git a/util/cpp/init.c b/util/cpp/init.c
new file mode 100644 (file)
index 0000000..64ec4cb
--- /dev/null
@@ -0,0 +1,72 @@
+/* PREPROCESSOR: INITIALIZATION ROUTINES */
+
+#include       <system.h>
+#include       <alloc.h>
+#include       "class.h"
+#include       "macro.h"
+#include       "idf.h"
+#include       "interface.h"
+
+PRIVATE struct mkey    {
+       char *mk_reserved;
+       int mk_key;
+} mkey[] =     {
+       {"define",      K_DEFINE},
+       {"elif",        K_ELIF},
+       {"else",        K_ELSE},
+       {"endif",       K_ENDIF},
+       {"if",          K_IF},
+       {"ifdef",       K_IFDEF},
+       {"ifndef",      K_IFNDEF},
+       {"include",     K_INCLUDE},
+       {"line",        K_LINE},
+       {"undef",       K_UNDEF},
+       {0,             K_UNKNOWN}
+};
+
+char *strcpy();
+
+EXPORT
+init_pp()
+{
+       long clock, sys_time();
+       static char date[30];
+       char *ctime();
+
+       /*      Initialise the control line keywords (if, include, define, etc)
+               Although the lexical analyzer treats them as identifiers, the
+               control line handler can recognize them as keywords by the
+               id_resmac field of the identifier.
+       */
+       {
+               register struct mkey *mk = &mkey[0];
+
+               while (mk->mk_reserved) {
+                       struct idf *idf = str2idf(mk->mk_reserved, 0);
+                       
+                       if (idf->id_resmac)
+                               fatal("maximum identifier length insufficient");
+                       idf->id_resmac = mk->mk_key;
+                       mk++;
+               }
+       }
+
+       /*      Initialize __DATE__, __FILE__ and __LINE__ macro
+               definitions.
+       */
+       /* __DATE__     */
+       clock = sys_time();
+       strcpy(&date[1], ctime(&clock));
+       date[26] = '\0';                /* zap nl       */
+       date[0] = date[25] = '"';
+       macro_def(str2idf("__DATE__", 0), date, -1, 26, NOFLAG);
+
+       /* __LINE__     */
+       macro_def(str2idf("__LINE__", 0), "0", -1, 1, FUNC);
+
+       /* __FILE__     */
+       macro_def(str2idf("__FILE__", 0), "", -1, 1, FUNC);
+
+       /* defined(??) */
+       macro_def(str2idf("defined", 0), "", 1, 1, FUNC);
+}
diff --git a/util/cpp/input.c b/util/cpp/input.c
new file mode 100644 (file)
index 0000000..b26bfc0
--- /dev/null
@@ -0,0 +1,47 @@
+#include "file_info.h"
+#include "input.h"
+#define INP_TYPE       struct file_info
+#define INP_VAR                finfo
+struct file_info       finfo;
+#include <inp_pkg.body>
+
+char *
+getwdir(fn)
+       char *fn;
+{
+       register char *p;
+       char *strrindex();
+
+       p = strrindex(fn, '/');
+       while (p && *(p + 1) == '\0') { /* remove trailing /'s */
+               *p = '\0';
+               p = strrindex(fn, '/');
+       }
+
+       if (fn[0] == '\0' || (fn[0] == '/' && p == &fn[0])) /* absolute path */
+               return "";
+       else
+       if (p) {
+               *p = '\0';
+               fn = Salloc(fn, p - &fn[0] + 1);
+               *p = '/';
+               return fn;
+       }
+       else return ".";
+}
+
+int    NoUnstack;
+int    Unstacked;
+
+AtEoIT()
+{
+       if (NoUnstack) error("unexpected EOF");
+       DoUnstack();
+       return 0;
+}
+
+AtEoIF()
+{
+       if (NoUnstack) error("unexpected EOF");
+       return 0;
+}
diff --git a/util/cpp/input.h b/util/cpp/input.h
new file mode 100644 (file)
index 0000000..b1221d5
--- /dev/null
@@ -0,0 +1,2 @@
+#include "inputtype.h"
+#include <inp_pkg.spec>
diff --git a/util/cpp/interface.h b/util/cpp/interface.h
new file mode 100644 (file)
index 0000000..d4a8c65
--- /dev/null
@@ -0,0 +1,3 @@
+#define PRIVATE        
+#define IMPORT extern
+#define EXPORT
diff --git a/util/cpp/macro.h b/util/cpp/macro.h
new file mode 100644 (file)
index 0000000..b04953a
--- /dev/null
@@ -0,0 +1,52 @@
+/* PREPROCESSOR: DEFINITION OF MACRO DESCRIPTOR */
+
+/*     The flags of the mc_flag field of the macro structure. Note that
+       these flags can be set simultaneously.
+*/
+#define NOFLAG         0               /* no special flags     */
+#define        FUNC            01              /* function attached    */
+#define NOREPLACE      02              /* don't replace        */
+
+#define        FORMALP 0200    /* mask for creating macro formal parameter     */
+
+/*     The macro descriptor is very simple, except the fact that the
+       mc_text, which points to the replacement text, contains the
+       non-ascii characters \201, \202, etc, indicating the position of a
+       formal parameter in this text.
+*/
+struct macro   {
+       struct macro *next;
+       char *  mc_text;        /* the replacement text         */
+       int     mc_nps;         /* number of formal parameters  */
+       int     mc_length;      /* length of replacement text   */
+       int     mc_count;       /* # of "concurrent" invocations*/
+       char    mc_flag;        /* marking this macro           */
+};
+
+
+/* allocation definitions of struct macro */
+extern char *st_alloc();
+extern struct macro *h_macro;
+#ifdef DEBUG
+extern int cnt_macro;
+extern char *std_alloc();
+#define        new_macro() ((struct macro *) std_alloc((char **)&h_macro, sizeof(struct macro), 20, &cnt_macro))
+#else
+#define        new_macro() ((struct macro *) st_alloc((char **)&h_macro, sizeof(struct macro), 20))
+#endif
+#define        free_macro(p) st_free(p, &h_macro, sizeof(struct macro))
+
+
+/* `token' numbers of keywords of command-line processor
+*/
+#define        K_UNKNOWN       0
+#define        K_DEFINE        1
+#define        K_ELIF          2
+#define        K_ELSE          3
+#define        K_ENDIF         4
+#define        K_IF            5
+#define        K_IFDEF         6
+#define        K_IFNDEF        7
+#define        K_INCLUDE       8
+#define        K_LINE          9
+#define        K_UNDEF         10
diff --git a/util/cpp/main.c b/util/cpp/main.c
new file mode 100644 (file)
index 0000000..fc581c3
--- /dev/null
@@ -0,0 +1,65 @@
+/* MAIN PROGRAM */
+
+#include "file_info.h"
+#include "idfsize.h"
+
+extern struct tokenname tkidf[], tkkey[];
+extern char *symbol2str();
+extern char *inctable[];
+extern int err_occurred;
+int idfsize = IDFSIZE;
+
+int ifval;
+
+char *prog_name;
+
+main(argc, argv)
+       char *argv[];
+{
+       /* parse and interpret the command line options */
+       prog_name = argv[0];
+
+       init_idf();
+       init_pp();      /* initialise the preprocessor macros   */
+
+       /*      Note: source file "-" indicates that the source is supplied
+               as standard input.  This is only allowed if INP_READ_IN_ONE is
+               not defined!
+       */
+       while (argc > 1 && *argv[1] == '-' && argv[1][1] != '\0')       {
+               char *par = &argv[1][1];
+
+               if (*par == '-')
+                       par++;
+               do_option(par);
+               argc--, argv++;
+       }
+       compile(argc - 1, &argv[1]);
+       return err_occurred;
+}
+
+compile(argc, argv)
+       char *argv[];
+{
+       register char *source = 0;
+       char *dummy;
+
+       switch (argc) {
+       case 1:
+               source = argv[0];
+               FileName = source;
+               break;
+       case 0:
+               FileName = "";
+               break;
+       default:
+               fatal("use: %s [options] [source]", prog_name);
+               break;
+       }
+       WorkingDir = inctable[0];
+
+       if (!InsertFile(source, (char **) 0, &dummy)) /* read the source file   */
+               fatal("%s: no source file %s\n", prog_name, 
+                       source ? source : "stdin");
+       preprocess(source);
+}
diff --git a/util/cpp/make.hfiles b/util/cpp/make.hfiles
new file mode 100755 (executable)
index 0000000..2132dd6
--- /dev/null
@@ -0,0 +1,35 @@
+: Update Files from database
+
+PATH=/bin:/usr/bin
+
+case $# in
+1) ;;
+*)     echo use: $0 file >&2
+       exit 1
+esac
+
+(
+IFCOMMAND="if (<\$FN) 2>/dev/null;\
+       then    if cmp -s \$FN \$TMP;\
+               then    rm \$TMP;\
+               else    mv \$TMP \$FN;\
+                       echo update \$FN;\
+               fi;\
+       else    mv \$TMP \$FN;\
+               echo create \$FN;\
+       fi"
+echo 'TMP=.uf$$'
+echo 'FN=$TMP'
+echo 'cat >$TMP <<\!EOF!'
+sed -n '/^!File:/,${
+/^$/d
+/^!File:[       ]*\(.*\)$/s@@!EOF!\
+'"$IFCOMMAND"'\
+FN=\1\
+cat >$TMP <<\\!EOF!@
+p
+}' $1
+echo '!EOF!'
+echo $IFCOMMAND
+) |
+sh
diff --git a/util/cpp/make.tokcase b/util/cpp/make.tokcase
new file mode 100755 (executable)
index 0000000..ef32292
--- /dev/null
@@ -0,0 +1,34 @@
+cat <<'--EOT--'
+#include "Lpars.h"
+
+char *
+symbol2str(tok)
+       int tok;
+{
+       static char buf[2] = { '\0', '\0' };
+
+       if (040 <= tok && tok < 0177) {
+               buf[0] = tok;
+               buf[1] = '\0';
+               return buf;
+       }
+       switch (tok) {
+--EOT--
+sed '
+/{[A-Z]/!d
+s/.*{\(.*\),.*\(".*"\).*$/     case \1 :\
+               return \2;/
+'
+cat <<'--EOT--'
+       case '\n':
+       case '\f':
+       case '\v':
+       case '\r':
+       case '\t':
+               buf[0] = tok;
+               return buf;
+       default:
+               return "bad token";
+       }
+}
+--EOT--
diff --git a/util/cpp/make.tokfile b/util/cpp/make.tokfile
new file mode 100755 (executable)
index 0000000..494b7e3
--- /dev/null
@@ -0,0 +1,6 @@
+sed '
+/{[A-Z]/!d
+s/.*{//
+s/,.*//
+s/.*/%token    &;/
+'
diff --git a/util/cpp/next.c b/util/cpp/next.c
new file mode 100644 (file)
index 0000000..64ff5ff
--- /dev/null
@@ -0,0 +1,5 @@
+#include "debug.h"
+struct macro *h_macro = 0;
+#ifdef DEBUG
+int cnt_macro = 0;
+#endif
diff --git a/util/cpp/options.c b/util/cpp/options.c
new file mode 100644 (file)
index 0000000..c1ef969
--- /dev/null
@@ -0,0 +1,119 @@
+/* USER-OPTION HANDLING */
+
+#include       <alloc.h>
+#include       "idfsize.h"
+#include       "maxincl.h"
+#include       "class.h"
+#include       "macro.h"
+#include       "idf.h"
+
+char options[128];                     /* one for every char   */
+int inc_pos = 1;                       /* place where next -I goes */
+char *inctable[MAXINCL] = {            /* list for includes    */
+       ".",
+       "/usr/include",
+       0
+};
+
+extern int idfsize;
+int txt2int();
+
+do_option(text)
+       char *text;
+{
+       switch(*text++) {
+       case '-':
+               options[*text] = 1;
+               break;
+       default:
+               error("illegal option: %c", text[-1]);
+               break;
+       case 'C' :      /* comment output               */
+               options['C'] = 1;
+               break;
+       case 'D' :      /* -Dname :     predefine name          */
+       {
+               register char *cp = text, *name, *mactext;
+
+               if (class(*cp) != STIDF)        {
+                       error("identifier missing in -D%s", text);
+                       break;
+               }
+               name = cp;
+               while (*cp && in_idf(*cp))
+                       ++cp;
+               if (!*cp)                       /* -Dname */
+                       mactext = "1";
+               else
+               if (*cp == '=') {               /* -Dname=text  */
+                       *cp++ = '\0';           /* end of name  */
+                       mactext = cp;
+               }
+               else    {                       /* -Dname?? */
+                       error("malformed option -D%s", text);
+                       break;
+               }
+               macro_def(str2idf(name, 0), mactext, -1, strlen(mactext), NOFLAG);
+               break;
+       }
+       case 'I' :      /* -Ipath : insert "path" into include list     */
+               if (*text)      {
+                       register int i = inc_pos++;
+                       register char *new = text;
+                       
+                       while (new)     {
+                               register char *tmp = inctable[i];
+                               
+                               inctable[i++] = new;
+                               if (i == MAXINCL)
+                                       fatal("too many -I options");
+                               new = tmp;
+                       }
+               }
+               else    inctable[inc_pos] = 0;
+               break;
+       case 'M':       /* maximum identifier length */
+               idfsize = txt2int(&text);
+               if (*text)
+                       error("malformed -M option");
+               if (idfsize > IDFSIZE) {
+                       warning("maximum identifier length is %d", IDFSIZE);
+                       idfsize = IDFSIZE;
+               }
+               if (idfsize < 8) {
+                       warning("minimum identifier length is 8");
+                       idfsize = 8;
+               }
+               break;
+       case 'P' :      /* run preprocessor stand-alone, without #'s    */
+               options['P'] = 1;
+               break;
+       case 'U' :      /* -Uname :     undefine predefined     */
+               if (*text)      {
+                       register struct idf *idef = findidf(text);
+
+                       if (idef && idef->id_macro) {
+                               free_macro(idef->id_macro);
+                               idef->id_macro = (struct macro *) 0;
+                       }
+               }
+               break;
+       }
+}
+
+int
+txt2int(tp)
+       char **tp;
+{
+       /*      the integer pointed to by *tp is read, while increasing
+               *tp; the resulting value is yielded.
+       */
+       register int val = 0;
+       register int ch;
+       
+       while (ch = **tp, ch >= '0' && ch <= '9')       {
+               val = val * 10 + ch - '0';
+               (*tp)++;
+       }
+       return val;
+}
diff --git a/util/cpp/preprocess.c b/util/cpp/preprocess.c
new file mode 100644 (file)
index 0000000..935d178
--- /dev/null
@@ -0,0 +1,209 @@
+/* PREPROCESSOR DRIVER */
+
+#include <system.h>
+#include "input.h"
+#include "maxincl.h"
+#include "obufsize.h"
+#include "LLlex.h"
+#include "class.h"
+#include "idf.h"
+#include "idfsize.h"
+#include "bits.h"
+
+char _obuf[OBUFSIZE];
+
+#ifdef DOBITS
+char bits[128];
+#endif
+
+preprocess(fn)
+       char *fn;
+{
+       register int c;
+       register char *op = _obuf;
+       register char *ob = &_obuf[OBUFSIZE];
+       int lineno = 0;
+       extern char options[];
+
+#define flush(X)       (sys_write(STDOUT,_obuf,X), op = _obuf)
+#define echo(ch)       (op != ob || flush(OBUFSIZE), *op++ = (ch))
+#define newline()      echo('\n')
+
+       for (;;) {
+               LineNumber++;
+               lineno++;
+               LoadChar(c);
+               while (c == '#') {
+                       domacro();
+                       lineno++;
+                       newline();
+                       LoadChar(c);
+               }
+               if (! options['P'] &&
+                    (lineno != LineNumber || fn != FileName)) {
+                       char Xbuf[256];
+                       register char *p = Xbuf;
+
+                       fn = FileName;
+                       lineno = LineNumber;
+                       sprint(p, "#line %d \"%s\"\n", LineNumber,
+                                                       FileName);
+                       while (*p) echo(*p++);
+               }
+               for (;;) {
+                       if (c & 0200)  {
+                               if (c == EOI) {
+                                       flush(op-_obuf);
+                                       return;
+                               }
+                               fatal("non-ascii character read");
+                       }
+                       if (c == '/') {
+                               LoadChar(c);
+                               if (c == '*') {
+                                       NoUnstack++;
+                                       if (options['C']) {
+                                               echo('/');
+                                               echo('*');
+                                       }
+                                       for (;;) {
+                                               LoadChar(c);
+                                               if (class(c) == STNL) {
+                                                       ++LineNumber;
+                                                       ++lineno;
+                                                       echo(c);
+                                               }
+                                               else if (c == EOI) {
+                                                       flush(op - _obuf);
+                                                       return;
+                                               }
+                                               else if (c == '*') {
+                                                       if (options['C']) echo(c);
+                                                       LoadChar(c);
+                                                       if (c == '/') {
+                                                               if (options['C']) echo(c);
+                                                               break;
+                                                       }
+                                                       else {
+                                                               PushBack();
+                                                       }
+                                               }
+                                               else if (options['C']) echo(c);
+                                       }
+                                       NoUnstack--;
+                                       LoadChar(c);
+                                       continue;
+                               }
+                               echo('/');
+                               continue;
+                       }
+                       switch(class(c)) {
+                       case STNL:
+                               echo(c);
+                               break;
+                       case STSTR:
+                       case STCHAR: {
+                               register int stopc = c;
+       
+                               do {
+                                       echo(c);
+                                       LoadChar(c);
+                                       if (c == '\\') {
+                                               echo(c);
+                                               LoadChar(c);
+                                       }
+                                       if (c == '\n') {
+                                               ++LineNumber;
+                                               lineno++;
+                                       }
+                                       else if (c == EOI) {
+                                               flush(op-_obuf);
+                                               return;
+                                       }
+                               }
+                               while (c != stopc);
+                               echo(c);
+                               LoadChar(c);
+                               continue;
+                               }
+                       case STNUM:
+#define getdec(c)      do { echo(c); LoadChar(c);} while (is_dig(c))
+#define gethex(c)      do { echo(c); LoadChar(c);} while (is_hex(c))
+
+                               if (c != '0') {
+                                       getdec(c);
+                                       if (c == '.') getdec(c);
+                                       if (c == 'e') {
+                                               echo(c);
+                                               LoadChar(c);
+                                               if (c == '+' || c == '-') {
+                                                       echo(c);
+                                                       LoadChar(c);
+                                               }
+                                               if (is_dig(c)) getdec(c);
+                                       }
+                               }
+                               else {
+                                       echo(c);
+                                       LoadChar(c);
+                                       if (c == 'x' || c == 'X') gethex(c);
+                                       else if (is_dig(c)) getdec(c);
+                               }
+                               continue;
+                           case STIDF: {
+                               extern int idfsize;             /* ??? */
+                               char buf[IDFSIZE + 1];
+                               register char *tg = &buf[0];
+                               register char *maxpos = &buf[idfsize];
+                               register struct idf *idef;
+
+#define tstmac(bx)     if (!(bits[c] & bx)) goto nomac
+#define cpy            if (Unstacked) EnableMacros(); *tg++ = c
+#define load           LoadChar(c); if (!in_idf(c)) goto endidf
+
+#ifdef DOBITS
+                               cpy; tstmac(bit0); load;
+                               cpy; tstmac(bit1); load;
+                               cpy; tstmac(bit2); load;
+                               cpy; tstmac(bit3); load;
+                               cpy; tstmac(bit4); load;
+                               cpy; tstmac(bit5); load;
+                               cpy; tstmac(bit6); load;
+                               cpy; tstmac(bit7); load;
+#endif
+
+                               for(;;) {
+                                       if (tg < maxpos) {
+                                               cpy;
+                                       }
+                                       load;
+                               }
+                       endidf:
+                               PushBack();
+                               *tg = '\0';     /* mark the end of the identifier */
+                               idef = findidf(buf);
+                               if ((idef && idef->id_macro && replace(idef))) {
+                                       LoadChar(c);
+                                       continue;
+                               }
+                       nomac:
+                               *tg = 0;
+                               tg = buf;
+                               while (*tg) echo(*tg++);
+                               LoadChar(c);
+                               while (in_idf(c)) {
+                                       echo(c);
+                                       LoadChar(c);
+                               }
+                               continue;
+                               }
+                           default:
+                               echo(c);
+                               LoadChar(c);
+                               continue;
+                       }
+                       break;
+               }
+       }
+       /*NOTREACHED*/
+}
diff --git a/util/cpp/replace.c b/util/cpp/replace.c
new file mode 100644 (file)
index 0000000..e8e78d3
--- /dev/null
@@ -0,0 +1,196 @@
+/* PREPROCESSOR: MACRO-TEXT REPLACEMENT ROUTINES */
+
+#include       "debug.h"       /* UF */
+#include       "pathlength.h"  /* UF */
+#include       "textsize.h"    /* UF */
+
+#include       <alloc.h>
+#include       <em_arith.h>
+#include       <assert.h>
+#include       "idf.h"
+#include       "input.h"
+#include       "macro.h"
+#include       "LLlex.h"
+#include       "class.h"
+#include       "interface.h"
+
+char *strcpy(), *strcat();
+char *long2str();
+
+PRIVATE struct macro   *ReplaceList;   /* list of currently active macros */
+
+EXPORT int
+replace(idef)
+       register struct idf *idef;
+{
+       /*      replace() is called by the lexical analyzer to perform
+               macro replacement.  "idef" is the description of the
+               identifier which leads to the replacement.  If the
+               optional actual parameters of the macro are OK, the text
+               of the macro is prepared to serve as an input buffer,
+               which is pushed onto the input stack.
+               replace() returns 1 if the replacement succeeded and 0 if
+               some error has occurred.
+       */
+       register struct macro *mac = idef->id_macro;
+       register char c;
+       char **actpars, **getactuals();
+       char *reptext, *macro2buffer();
+       int size;
+
+       if (mac->mc_flag & NOREPLACE) {
+               warning("macro %s is recursive", idef->id_text);
+               return 0;
+       }
+       if (mac->mc_nps != -1) {        /* with parameter list  */
+               if (mac->mc_flag & FUNC) {
+                                       /* must be "defined".
+                                          Unfortunately, the next assertion
+                                          will not compile ...
+                       assert( ! strcmp("defined", idef->id_text));
+                                       */
+                       if (! AccDefined)
+                               return 0;
+               }
+               if (++mac->mc_count > 100) {
+                       /* 100 must be some number in Parameters */
+                       warning("macro %s is assumed recursive",
+                                   idef->id_text);
+                       return 0;
+               }
+               LoadChar(c);
+               c = skipspaces(c);
+               if (c != '(') {         /* no replacement if no ()      */
+                       error("macro %s needs arguments",
+                               idef->id_text);
+                       PushBack();
+                       return 0;
+               }
+               actpars = getactuals(idef);     /* get act.param. list  */
+               if (mac->mc_flag & FUNC) {
+                       struct idf *param = findidf(*actpars);
+
+                       if (param && param->id_macro) 
+                               reptext = "1";
+                       else
+                               reptext = "0";
+                       InsertText(reptext, 1);
+                       mac->next = ReplaceList;
+                       ReplaceList = mac;
+                       return 1;
+               }
+       }
+       if (mac->mc_flag & FUNC) /* this macro leads to special action  */
+               macro_func(idef);
+       if (mac->mc_nps <= 0) {
+               mac->mc_flag |= NOREPLACE;
+               reptext = mac->mc_text;
+               size = mac->mc_length;
+       }
+       else reptext = macro2buffer(idef, actpars, &size); /* create input buffer */
+       InsertText(reptext, size);
+       mac->next = ReplaceList;
+       ReplaceList = mac;
+       return 1;
+}
+
+char FilNamBuf[PATHLENGTH];
+
+PRIVATE
+macro_func(idef)
+       register struct idf *idef;
+{
+       /*      macro_func() performs the special actions needed with some
+               macros.  These macros are __FILE__ and __LINE__ which
+               replacement texts must be evaluated at the time they are
+               used.
+       */
+       register struct macro *mac = idef->id_macro;
+
+       switch (idef->id_text[2]) { /* This switch is very blunt... */
+       case 'F' :                      /* __FILE__     */
+               mac->mc_length = strlen(FileName) + 2;
+               mac->mc_text = FilNamBuf;
+               mac->mc_text[0] = '"';
+               strcpy(&(mac->mc_text[1]), FileName);
+               strcat(mac->mc_text, "\"");
+               break;
+       case 'L' :                      /* __LINE__     */
+       {
+               mac->mc_text = long2str((long) LineNumber, 10);
+               mac->mc_length = strlen(mac->mc_text);
+               break;
+       }
+       default :
+               crash("(macro_func)");
+       }
+}
+
+PRIVATE char *
+macro2buffer(idef, actpars, siztext)
+       struct idf *idef;
+       char **actpars;
+       int *siztext;
+{
+       /*      Macro2buffer() turns the macro replacement text, as it is
+               stored, into an input buffer, while each occurrence of the
+               non-ascii formal parameter mark is replaced by its
+               corresponding actual parameter specified in the actual
+               parameter list actpars.  A pointer to the beginning of the
+               constructed text is returned, while *siztext is filled
+               with its length.
+               If there are no parameters, this function behaves
+               the same as strcpy().
+       */
+       register int size = idef->id_macro->mc_length + ITEXTSIZE;
+       register char *text = Malloc(size);
+       register int pos = 0;
+       register char *ptr = idef->id_macro->mc_text;
+
+       while (*ptr) {
+               if (*ptr & FORMALP) {   /* non-asc formal param. mark   */
+                       register int n = *ptr++ & 0177;
+                       register char *p;
+
+                       assert(n != 0);
+                       /*      copy the text of the actual parameter
+                               into the replacement text
+                       */
+                       for (p = actpars[n - 1]; p && *p; p++) {
+                               text[pos++] = *p;
+                               if (pos == size)
+                                       text = Srealloc(text, size += RTEXTSIZE);
+                       }
+               }
+               else {
+                       text[pos++] = *ptr++;
+                       if (pos == size)
+                               text = Srealloc(text, size += RTEXTSIZE);
+               }
+       }
+       text[pos] = '\0';
+       *siztext = pos;
+       return text;
+}
+
+EXPORT
+DoUnstack()
+{
+       Unstacked++;
+}
+
+EXPORT
+EnableMacros()
+{
+       register struct macro *p = ReplaceList;
+
+       assert(Unstacked > 0);
+       while (Unstacked > 0) {
+               assert(p != 0);
+               p->mc_flag &= ~NOREPLACE;
+               p->mc_count = 0;
+               p = p->next;
+               Unstacked--;
+       }
+       ReplaceList = p;
+}
diff --git a/util/cpp/scan.c b/util/cpp/scan.c
new file mode 100644 (file)
index 0000000..8be12de
--- /dev/null
@@ -0,0 +1,224 @@
+/* PREPROCESSOR: SCANNER FOR THE ACTUAL PARAMETERS OF MACROS   */
+
+/*     This file contains the function getactuals() which scans an actual
+       parameter list and splits it up into a list of strings, each one
+       representing an actual parameter.
+*/
+
+#include       "lapbuf.h"      /* UF */
+#include       "nparams.h"     /* UF */
+
+#include       "input.h"
+#include       "class.h"
+#include       "idf.h"
+#include       "macro.h"
+#include       "interface.h"
+
+#define        EOS             '\0'
+#define        overflow()      (fatal("actual parameter buffer overflow"))
+
+PRIVATE char apbuf[LAPBUF]; /* temporary storage for actual parameters */
+PRIVATE char *actparams[NPARAMS]; /* pointers to the text of the actuals */
+PRIVATE char *aptr;    /* pointer to last inserted character in apbuf  */
+
+#define        copy(ch)        ((aptr < &apbuf[LAPBUF]) ? (*aptr++ = ch) : overflow())
+
+PRIVATE int nr_of_params;      /* number of actuals read until now     */
+
+PRIVATE char **
+getactuals(idef)
+       struct idf *idef;
+{
+       /*      getactuals() collects the actual parameters and turns them
+               into a list of strings, a pointer to which is returned.
+       */
+       register acnt = idef->id_macro->mc_nps;
+
+       nr_of_params = 0;
+       actparams[0] = aptr = &apbuf[0];
+       copyact('(', ')', 0);   /* read the actual parameters   */
+       copy(EOS);              /* mark the end of it all       */
+
+       if (!nr_of_params++)    {               /* 0 or 1 parameter     */
+               /* there could be a ( <spaces, comment, ...> )
+               */
+               register char *p = actparams[0];
+
+               while ((class(*p) == STSKIP) || (*p == '\n')) {
+                               ++p;
+               }
+
+               if (!*p) {      /* the case () : 0 parameters   */
+                       nr_of_params--;
+               }
+       }
+
+       if (nr_of_params != acnt)       {
+               /*      argument mismatch: too many or too few
+                       actual parameters.
+               */
+               error("argument mismatch, %s", idef->id_text);
+
+               while (++nr_of_params < acnt) {
+                       /*      too few paraeters: remaining actuals are ""
+                       */
+                       actparams[nr_of_params] = (char *) 0;
+               }
+       }
+
+       return actparams;
+}
+
+PRIVATE
+copyact(ch1, ch2, level)
+       char ch1, ch2;
+       int level;
+{
+       /*      copyact() is taken from Ceriel Jacobs' LLgen, with
+               permission.  Its task is to build a list of actuals
+               parameters, which list is surrounded by '(' and ')' and in
+               which the parameters are separated by ',' if there are
+               more than 1. The balancing of '(',')' and '[',']' and
+               '{','}' is taken care of by calling this function
+               recursively. At each level, copyact() reads the input,
+               upto the corresponding closing bracket.
+
+               Opening bracket is ch1, closing bracket is ch2. If
+               level != 0, copy opening and closing parameters too.
+       */
+       register int ch;                /* Current char */
+       register int match;             /* used to read strings */
+
+       if (level) {
+               copy(ch1);
+       }
+
+       for (;;)        {
+               LoadChar(ch);
+
+               if (ch == ch2)  {
+                       if (level) {
+                               copy(ch);
+                       }
+                       return;
+               }
+
+               switch(ch)      {
+
+               case ')':
+               case '}':
+               case ']':
+                       error("unbalanced parenthesis");
+                       break;
+
+               case '(':
+                       copyact('(', ')', level+1);
+                       break;
+
+               case '{':
+                       /*      example:
+                                       #define declare(v, t)   t v
+                                       declare(v, union{int i, j; float r;});
+                       */
+                       copyact('{', '}', level+1);
+                       break;
+
+               case '[':
+                       copyact('[', ']', level+1);
+                       break;
+
+               case '\n':
+                       LoadChar(ch);
+                       while (ch == '#')       {
+                               /*      This piece of code needs some
+                                       explanation: consider the call of
+                                       the macro defined as:
+                                               #define sum(b,c) (b + c)
+                                       in the following form:
+                                               sum(
+                                               #include my_phone_number
+                                               ,2)
+                                       in which case the include must be
+                                       interpreted as such.
+                               */
+                               domacro();      /* has read nl, vt or ff */
+                               LoadChar(ch);
+                               /* Loop, for another control line */
+                       }
+
+                       PushBack();
+                       copy('\n');
+                       break;
+
+               case '/':
+                       LoadChar(ch);
+
+                       if (ch == '*')  {       /* skip comment */
+                               skipcomment();
+                               continue;
+                       }
+
+                       PushBack();
+                       copy('/');
+                       break;
+
+               case ',':
+                       if (!level)     {
+                               /* next parameter encountered */
+                               copy(EOS);
+
+                               if (++nr_of_params >= NPARAMS) {
+                                       fatal("(getact) too many actuals");
+                               }
+
+                               actparams[nr_of_params] = aptr;
+                       }
+                       else    {
+                               copy(ch);
+                       }
+                       break;
+
+               case '\'':
+               case '"' :
+                       /*      watch out for brackets in strings, they do
+                               not count !
+                       */
+                       match = ch;
+                       copy(ch);
+                       LoadChar(ch);
+                       while (ch != EOI)       {
+                               if (ch == match) {
+                                       break;
+                               }
+
+                               if (ch == '\\') {
+                                       copy(ch);
+                                       LoadChar(ch);
+                               }
+                               else
+                               if (ch == '\n') {
+                                       error("newline in string");
+                                       copy(match);
+                                       break;
+                               }
+
+                               copy(ch);
+                               LoadChar(ch);
+                       }
+
+                       if (ch == match)        {
+                               copy(ch);
+                               break;
+                       }
+                       /* Fall through */
+
+               case EOI :
+                       error("unterminated macro call");
+                       return;
+
+               default:
+                       copy(ch);
+                       break;
+               }
+       }
+}
diff --git a/util/cpp/skip.c b/util/cpp/skip.c
new file mode 100644 (file)
index 0000000..636e79b
--- /dev/null
@@ -0,0 +1,64 @@
+/* $Header$ */
+/* PREPROCESSOR: INPUT SKIP FUNCTIONS */
+
+#include       "LLlex.h"
+#include       "class.h"
+#include       "input.h"
+
+int
+skipspaces(ch)
+       register int ch;
+{
+       /*      skipspaces() skips any white space and returns the first
+               non-space character.
+       */
+       for (;;) {
+               while (class(ch) == STSKIP)
+                       LoadChar(ch);
+               /* How about "\\\n"?????????    */
+               if (ch == '/') {
+                       LoadChar(ch);
+                       if (ch == '*') {
+                               skipcomment();
+                               LoadChar(ch);
+                       }
+                       else    {
+                               PushBack();
+                               return '/';
+                       }
+               }
+               else
+                       return ch;
+       }
+}
+
+skipline()
+{
+       /*      skipline() skips all characters until a newline character
+               is seen, not escaped by a '\\'.
+               Any comment is skipped.
+       */
+       register int c;
+
+       LoadChar(c);
+       while (class(c) != STNL && c != EOI) {
+               if (c == '\\') {
+                       LoadChar(c);
+                       if (class(c) == STNL)
+                               ++LineNumber;
+               }
+               if (c == '/') {
+                       LoadChar(c);
+                       if (c == '*')
+                               skipcomment();
+                       else
+                               continue;
+               }
+               LoadChar(c);
+       }
+       ++LineNumber;
+       if (c == EOI) {         /* garbage input...             */
+               error("unexpected EOF while skipping text");
+               PushBack();
+       }
+}
diff --git a/util/cpp/tokenname.c b/util/cpp/tokenname.c
new file mode 100644 (file)
index 0000000..82fc1f5
--- /dev/null
@@ -0,0 +1,51 @@
+/* $Header$ */
+/* TOKEN NAME DEFINITIONS */
+
+#include       "idf.h"
+#include       "LLlex.h"
+#include       "Lpars.h"
+
+struct tokenname       {       /*      Used for defining the name of a
+                                       token as identified by its symbol
+                               */
+       int tn_symbol;
+       char *tn_name;
+};
+
+/*     To centralize the declaration of %tokens, their presence in this
+       file is taken as their declaration. The Makefile will produce
+       a grammar file (tokenfile.g) from this file.
+       Moreover, rather than looking up a symbol in all these lists
+       to find its printable name, a fast version of symbol2str() is
+       generated from these tables.
+       Consequenty some of these tables are not referenced explicitly
+       in the C text any more.  To save space and to avoid lint confusion,
+       these have been made pseudo-invisible by #ifdefs.
+*/
+
+#ifdef ____
+struct tokenname tkspec[] =    {       /* the names of the special tokens */
+       {IDENTIFIER, "identifier"},
+       {STRING, "string"},
+       {FILESPECIFIER, "filespecifier"},
+       {INTEGER, "integer"},
+       {0, ""}
+};
+
+struct tokenname tkcomp[] =    {       /* names of the composite tokens */
+       {NOTEQUAL, "!="},
+       {AND, "&&"},
+       {LEFT, "<<"},
+       {LESSEQ, "<="},
+       {EQUAL, "=="},
+       {GREATEREQ, ">="},
+       {RIGHT, ">>"},
+       {OR, "||"},
+       {0, ""}
+};
+
+struct tokenname tkfunny[] =   {       /* internal keywords */
+       {ERRONEOUS, "erroneous"},
+       {0, ""}
+};
+#endif ____