version using input module and detecting preprocessor loops
authorceriel <none@none>
Thu, 4 Dec 1986 16:29:44 +0000 (16:29 +0000)
committerceriel <none@none>
Thu, 4 Dec 1986 16:29:44 +0000 (16:29 +0000)
13 files changed:
lang/cem/cemcom/LLlex.c
lang/cem/cemcom/LLlex.h
lang/cem/cemcom/Makefile.erik
lang/cem/cemcom/Parameters
lang/cem/cemcom/domacro.c
lang/cem/cemcom/file_info.h [new file with mode: 0644]
lang/cem/cemcom/init.c
lang/cem/cemcom/input.c
lang/cem/cemcom/input.h
lang/cem/cemcom/macro.str
lang/cem/cemcom/main.c
lang/cem/cemcom/options.c
lang/cem/cemcom/replace.c

index 84d5b29..e8b245c 100644 (file)
@@ -21,9 +21,6 @@
 /* Data about the token yielded */
 struct token dot, ahead, aside;
 
-unsigned int LineNumber = 0;   /* current LineNumber   */
-char *FileName = 0;            /* current filename     */
-
 int ReplaceMacros = 1;         /* replacing macros                     */
 int EoiForNewline = 0;         /* return EOI upon encountering newline */
 int PreProcKeys = 0;           /* return preprocessor key              */
@@ -31,6 +28,7 @@ int AccFileSpecifier = 0;     /* return filespecifier <...>           */
 int AccDefined = 0;            /* accept "defined(...)"                */
 int UnknownIdIsZero = 0;       /* interpret unknown id as integer 0    */
 int SkipEscNewline = 0;                /* how to interpret backslash-newline   */
+int Unstacked = 0;             /* an unstack is done                   */
 
 #define MAX_LL_DEPTH   2
 
@@ -102,21 +100,28 @@ GetToken(ptok)
        char buf[(IDFSIZE > NUMSIZE ? IDFSIZE : NUMSIZE) + 1];
        register int ch, nch;
 
+       if (! LineNumber) goto firstline;
 again: /* rescan the input after an error or replacement       */
+#ifndef NOPP
+       if (Unstacked) EnableMacros();
+#endif
        LoadChar(ch);
 go_on: /* rescan, the following character has been read        */
        if ((ch & 0200) && ch != EOI) /* stop on non-ascii character */
                fatal("non-ascii '\\%03o' read", ch & 0377);
        switch (class(ch)) {    /* detect character class       */
        case STNL:              /* newline, vertical space or formfeed  */
+firstline:
                LineNumber++;                   /* also at vs and ff    */
                if (EoiForNewline)      /* called in control line       */
                        /*      a newline in a control line indicates the
                                end-of-information of the line.
                        */
                        return ptok->tk_symb = EOI;
-               while (LoadChar(ch), ch == '#') /* a control line follows */
+               while (LoadChar(ch), ch == '#') /* a control line follows */
                        domacro();
+                       if (!LineNumber) goto firstline;
+               }
                        /*      We have to loop here, because in
                                `domacro' the nl, vt or ff is read. The
                                character following it may again be a `#'.
@@ -253,6 +258,9 @@ go_on:      /* rescan, the following character has been read        */
                hash = STARTHASH();
                do      {                       /* read the identifier  */
                        if (++pos < idfsize) {
+#ifndef NOPP
+                               if (Unstacked) EnableMacros();
+#endif
                                *tg++ = ch;
                                hash = ENHASH(hash, ch, pos);
                        }
@@ -485,8 +493,10 @@ string_token(nm, stop_char, plen)
                }
                if (ch == '\\') {
                        LoadChar(ch);
-                       if (ch == '\n')
+                       if (ch == '\n') {
                                LineNumber++;
+                               continue;
+                       }
                        ch = quoted(ch);
                }
                str[pos++] = ch;
index 569a2e9..c01aaf4 100644 (file)
@@ -7,6 +7,7 @@
 */
 
 #include "nofloat.h"
+#include "file_info.h"
 
 /* the structure of a token:   */
 struct token   {
@@ -42,8 +43,6 @@ struct token  {
 #endif NOFLOAT
 
 extern struct token dot, ahead, aside;
-extern unsigned int LineNumber;        /* "LLlex.c"    */
-extern char *FileName;         /* "LLlex.c"    */
 
 extern int ReplaceMacros;      /* "LLlex.c"    */
 extern int EoiForNewline;      /* "LLlex.c"    */
@@ -52,6 +51,7 @@ extern int AccFileSpecifier;  /* "LLlex.c"    */
 extern int AccDefined;         /* "LLlex.c"    */
 extern int UnknownIdIsZero;    /* "LLlex.c"    */
 extern int SkipEscNewline;     /* "LLlex.c"    */
+extern int Unstacked;          /* "LLlex.c"    */
 
 extern int NoUnstack;          /* buffer.c     */
 
index c247c54..d7f9352 100644 (file)
@@ -17,21 +17,23 @@ EMELIB = $(EM)/modules/lib/libeme.a
 STRLIB = $(EM)/modules/lib/libstr.a
 PRTLIB = $(EM)/modules/lib/libprint.a
 EMMESLIB = $(EM)/modules/lib/libem_mes.a
+INPLIB = $(EM)/modules/lib/libinput.a
 #CH3LIB = $(EM)/modules/lib/libch3.a
 CH3LIB =
-LIBS = $(CH3LIB) $(EMMESLIB) $(EMKLIB) $(PRTLIB) $(STRLIB) $(SYSLIB)
-ELIBS = $(CH3LIB) $(EMMESLIB) $(EMELIB) $(PRTLIB) $(STRLIB) $(SYSLIB)
-LIB_INCLUDES = $(EM)/modules/h
-EM_INCLUDES = $(EM)/h
+LIBS = $(INPLIB) $(CH3LIB) $(EMMESLIB) $(EMKLIB) $(PRTLIB) $(STRLIB) $(SYSLIB)
+ELIBS = $(INPLIB) $(CH3LIB) $(EMMESLIB) $(EMELIB) $(PRTLIB) $(STRLIB) $(SYSLIB)
+LIB_INCLUDES = -I$(EM)/modules/h -I$(EM)/modules/pkg
+EM_INCLUDES = -I$(EM)/h
 SYSLLIB = $(EM)/modules/lib/llib-lsys.ln
 EMKLLIB = $(EM)/modules/lib/llib-lemk.ln
 EMELLIB = $(EM)/modules/lib/llib-leme.ln
 STRLLIB = $(EM)/modules/lib/llib-lstr.ln
 PRTLLIB = $(EM)/modules/lib/llib-lprint.ln
 EMMESLLIB = $(EM)/modules/lib/llib-lmes.ln
+INPLLIB = $(EM)/modules/lib/llib-linput.ln
 CH3LLIB = $(EM)/modules/lib/llib-lch3.ln
 LINTLIBS =
-#LINTLIBS = $(CH3LLIB) $(EMMESLLIB) $(EMKLLIB) $(PRTLLIB) $(STRLLIB) $(SYSLLIB)
+#LINTLIBS = $(CH3LLIB) $(INPLLIB) $(EMMESLLIB) $(EMKLLIB) $(PRTLLIB) $(STRLLIB) $(SYSLLIB)
 
 # Where to install the compiler and its driver
 CEMCOM = $(DESTINATION)/cemcom
@@ -48,7 +50,7 @@ GEN = $(EM)/bin/LLgen
 GENOPTIONS = -vv
 
 # Special #defines during compilation
-CDEFS =        $(MAP) -I$(EM_INCLUDES) -I$(LIB_INCLUDES)
+CDEFS =        $(MAP) $(EM_INCLUDES) $(LIB_INCLUDES)
 CFLAGS = $(CDEFS) $(COPTIONS) -O#      # we cannot pass the COPTIONS to lint!
 
 # Grammar files and their objects
@@ -77,7 +79,7 @@ GSRC =        char.c symbol2str.c next.c \
 GHSRC =        botch_free.h dataflow.h debug.h density.h errout.h \
        idepth.h idfsize.h ifdepth.h inputtype.h inumlength.h lapbuf.h \
        maxincl.h myalloc.h nobitfield.h nofloat.h nopp.h \
-       nparams.h numsize.h parbufsize.h pathlength.h predefine.h \
+       nparams.h numsize.h parbufsize.h pathlength.h \
        strsize.h target_sizes.h textsize.h use_tmp.h spec_arith.h static.h
 
 # Other generated files, for 'make clean' only
@@ -206,47 +208,47 @@ sim:      cfiles
        $(SIM) $(SIMFLAGS) `sources $(COBJ)` $(GSRC) $(LSRC)
 
 #AUTOAUTOAUTOAUTOAUTOAUTOAUTOAUTOAUTOAUTO
-LLlex.o: LLlex.h Lpars.h alloc.h arith.h assert.h class.h debug.h def.h idf.h idfsize.h input.h nofloat.h nopp.h numsize.h sizes.h spec_arith.h strsize.h
-LLmessage.o: LLlex.h Lpars.h alloc.h arith.h idf.h nofloat.h nopp.h spec_arith.h
-Lpars.o: Lpars.h
-alloc.o: alloc.h assert.h debug.h myalloc.h
-arith.o: Lpars.h alloc.h arith.h botch_free.h expr.h field.h idf.h label.h mes.h nobitfield.h nofloat.h nopp.h spec_arith.h storage.h type.h
-blocks.o: arith.h atw.h nofloat.h sizes.h spec_arith.h
+main.o: LLlex.h Lpars.h alloc.h arith.h debug.h declar.h file_info.h idf.h input.h inputtype.h level.h maxincl.h myalloc.h nobitfield.h nofloat.h nopp.h spec_arith.h specials.h target_sizes.h tokenname.h type.h use_tmp.h
+idf.o: LLlex.h Lpars.h align.h alloc.h arith.h assert.h botch_free.h debug.h declar.h decspecs.h def.h file_info.h idf.h idfsize.h label.h level.h nobitfield.h nofloat.h nopp.h sizes.h spec_arith.h specials.h stack.h storage.h struct.h type.h
+declarator.o: Lpars.h alloc.h arith.h botch_free.h declar.h expr.h idf.h label.h nobitfield.h nofloat.h nopp.h sizes.h spec_arith.h storage.h type.h
+decspecs.o: Lpars.h arith.h decspecs.h def.h level.h nobitfield.h nofloat.h spec_arith.h type.h
+struct.o: LLlex.h Lpars.h align.h arith.h assert.h botch_free.h debug.h def.h field.h file_info.h idf.h level.h nobitfield.h nofloat.h nopp.h sizes.h spec_arith.h stack.h storage.h struct.h type.h
+expr.o: LLlex.h Lpars.h alloc.h arith.h botch_free.h declar.h decspecs.h def.h expr.h file_info.h idf.h label.h level.h nobitfield.h nofloat.h nopp.h sizes.h spec_arith.h storage.h type.h
 ch7.o: Lpars.h arith.h assert.h debug.h def.h expr.h idf.h label.h nobitfield.h nofloat.h nopp.h spec_arith.h struct.h type.h
 ch7bin.o: Lpars.h arith.h botch_free.h expr.h idf.h label.h nobitfield.h nofloat.h nopp.h spec_arith.h storage.h struct.h type.h
-ch7mon.o: Lpars.h arith.h botch_free.h def.h expr.h idf.h label.h nobitfield.h nofloat.h nopp.h spec_arith.h storage.h type.h
-char.o: class.h
-code.o: LLlex.h Lpars.h alloc.h arith.h assert.h atw.h botch_free.h code.h dataflow.h debug.h declar.h decspecs.h def.h expr.h idf.h label.h level.h mes.h nobitfield.h nofloat.h nopp.h sizes.h spec_arith.h specials.h stack.h stmt.h storage.h type.h use_tmp.h
-conversion.o: Lpars.h arith.h nobitfield.h nofloat.h sizes.h spec_arith.h type.h
 cstoper.o: Lpars.h arith.h assert.h debug.h expr.h idf.h label.h nobitfield.h nofloat.h nopp.h sizes.h spec_arith.h target_sizes.h type.h
-dataflow.o: dataflow.h
-declar.o: LLlex.h Lpars.h arith.h debug.h declar.h decspecs.h def.h expr.h field.h idf.h label.h nobitfield.h nofloat.h nopp.h sizes.h spec_arith.h storage.h struct.h type.h
-declarator.o: Lpars.h alloc.h arith.h botch_free.h declar.h expr.h idf.h label.h nobitfield.h nofloat.h nopp.h sizes.h spec_arith.h storage.h type.h
-decspecs.o: Lpars.h arith.h decspecs.h def.h level.h nobitfield.h nofloat.h spec_arith.h type.h
-domacro.o: LLlex.h Lpars.h alloc.h arith.h assert.h botch_free.h class.h debug.h idf.h idfsize.h ifdepth.h input.h interface.h macro.h nofloat.h nopp.h nparams.h parbufsize.h spec_arith.h storage.h textsize.h
+arith.o: Lpars.h alloc.h arith.h botch_free.h expr.h field.h idf.h label.h mes.h nobitfield.h nofloat.h nopp.h spec_arith.h storage.h type.h
+alloc.o: alloc.h assert.h debug.h myalloc.h
+code.o: LLlex.h Lpars.h alloc.h arith.h assert.h atw.h botch_free.h code.h dataflow.h debug.h declar.h decspecs.h def.h expr.h file_info.h idf.h label.h level.h mes.h nobitfield.h nofloat.h nopp.h sizes.h spec_arith.h specials.h stack.h stmt.h storage.h type.h use_tmp.h
 dumpidf.o: Lpars.h arith.h debug.h def.h expr.h field.h idf.h label.h nobitfield.h nofloat.h nopp.h spec_arith.h stack.h static.h struct.h type.h
-error.o: LLlex.h arith.h debug.h errout.h expr.h label.h nofloat.h nopp.h spec_arith.h tokenname.h use_tmp.h
-eval.o: Lpars.h align.h arith.h assert.h atw.h code.h dataflow.h debug.h def.h expr.h idf.h label.h level.h mes.h nobitfield.h nofloat.h nopp.h sizes.h spec_arith.h stack.h type.h
-expr.o: LLlex.h Lpars.h alloc.h arith.h botch_free.h declar.h decspecs.h def.h expr.h idf.h label.h level.h nobitfield.h nofloat.h nopp.h sizes.h spec_arith.h storage.h type.h
-expression.o: LLlex.h Lpars.h arith.h expr.h idf.h label.h nobitfield.h nofloat.h nopp.h spec_arith.h type.h
+error.o: LLlex.h arith.h debug.h errout.h expr.h file_info.h label.h nofloat.h nopp.h spec_arith.h tokenname.h use_tmp.h
 field.o: Lpars.h arith.h assert.h code.h debug.h expr.h field.h idf.h label.h nobitfield.h nofloat.h nopp.h sizes.h spec_arith.h type.h
-idf.o: LLlex.h Lpars.h align.h alloc.h arith.h assert.h botch_free.h debug.h declar.h decspecs.h def.h idf.h idfsize.h label.h level.h nobitfield.h nofloat.h nopp.h sizes.h spec_arith.h specials.h stack.h storage.h struct.h type.h
-init.o: alloc.h class.h idf.h interface.h macro.h nopp.h predefine.h
-input.o: LLlex.h alloc.h arith.h assert.h debug.h idepth.h input.h inputtype.h interface.h nofloat.h nopp.h pathlength.h spec_arith.h static.h
-ival.o: Lpars.h align.h arith.h assert.h class.h debug.h def.h expr.h field.h idf.h label.h level.h nobitfield.h nofloat.h nopp.h sizes.h spec_arith.h struct.h type.h
-label.o: Lpars.h arith.h def.h idf.h label.h level.h nobitfield.h nofloat.h nopp.h spec_arith.h type.h
-main.o: LLlex.h Lpars.h alloc.h arith.h debug.h declar.h idf.h input.h inputtype.h level.h maxincl.h myalloc.h nobitfield.h nofloat.h nopp.h spec_arith.h specials.h target_sizes.h tokenname.h type.h use_tmp.h
+tokenname.o: LLlex.h Lpars.h arith.h file_info.h idf.h nofloat.h nopp.h spec_arith.h tokenname.h
+LLlex.o: LLlex.h Lpars.h alloc.h arith.h assert.h class.h debug.h def.h file_info.h idf.h idfsize.h input.h nofloat.h nopp.h numsize.h sizes.h spec_arith.h strsize.h
+LLmessage.o: LLlex.h Lpars.h alloc.h arith.h file_info.h idf.h nofloat.h nopp.h spec_arith.h
+input.o: file_info.h input.h inputtype.h nopp.h
+domacro.o: LLlex.h Lpars.h alloc.h arith.h assert.h botch_free.h class.h debug.h file_info.h idf.h idfsize.h ifdepth.h input.h interface.h macro.h nofloat.h nopp.h nparams.h parbufsize.h spec_arith.h storage.h textsize.h
+replace.o: LLlex.h alloc.h arith.h assert.h class.h debug.h file_info.h idf.h input.h interface.h macro.h nofloat.h nopp.h pathlength.h spec_arith.h static.h strsize.h
+init.o: alloc.h class.h idf.h interface.h macro.h nopp.h
 options.o: align.h arith.h class.h idf.h idfsize.h macro.h maxincl.h nobitfield.h nofloat.h nopp.h sizes.h spec_arith.h storage.h use_tmp.h
-program.o: LLlex.h Lpars.h alloc.h arith.h code.h declar.h decspecs.h def.h expr.h idf.h label.h nobitfield.h nofloat.h nopp.h spec_arith.h type.h
-replace.o: LLlex.h alloc.h arith.h assert.h class.h debug.h idf.h input.h interface.h macro.h nofloat.h nopp.h pathlength.h spec_arith.h static.h strsize.h
 scan.o: class.h idf.h input.h interface.h lapbuf.h macro.h nopp.h nparams.h
-skip.o: LLlex.h arith.h class.h input.h interface.h nofloat.h nopp.h spec_arith.h
+skip.o: LLlex.h arith.h class.h file_info.h input.h interface.h nofloat.h nopp.h spec_arith.h
 stack.o: Lpars.h alloc.h arith.h botch_free.h debug.h def.h idf.h level.h mes.h nobitfield.h nofloat.h nopp.h spec_arith.h stack.h storage.h struct.h type.h use_tmp.h
-statement.o: LLlex.h Lpars.h arith.h botch_free.h code.h debug.h def.h expr.h idf.h label.h nobitfield.h nofloat.h nopp.h spec_arith.h stack.h storage.h type.h
-storage.o: alloc.h assert.h botch_free.h debug.h storage.h
-struct.o: LLlex.h Lpars.h align.h arith.h assert.h botch_free.h debug.h def.h field.h idf.h level.h nobitfield.h nofloat.h nopp.h sizes.h spec_arith.h stack.h storage.h struct.h type.h
+type.o: Lpars.h align.h alloc.h arith.h def.h idf.h nobitfield.h nofloat.h nopp.h sizes.h spec_arith.h storage.h type.h
+ch7mon.o: Lpars.h arith.h botch_free.h def.h expr.h idf.h label.h nobitfield.h nofloat.h nopp.h spec_arith.h storage.h type.h
+label.o: Lpars.h arith.h def.h idf.h label.h level.h nobitfield.h nofloat.h nopp.h spec_arith.h type.h
+eval.o: Lpars.h align.h arith.h assert.h atw.h code.h dataflow.h debug.h def.h expr.h idf.h label.h level.h mes.h nobitfield.h nofloat.h nopp.h sizes.h spec_arith.h stack.h type.h
 switch.o: Lpars.h arith.h assert.h botch_free.h code.h debug.h density.h expr.h idf.h label.h nobitfield.h nofloat.h nopp.h spec_arith.h storage.h switch.h type.h
-symbol2str.o: Lpars.h
+storage.o: alloc.h assert.h botch_free.h debug.h storage.h
+ival.o: Lpars.h align.h arith.h assert.h class.h debug.h def.h expr.h field.h idf.h label.h level.h nobitfield.h nofloat.h nopp.h sizes.h spec_arith.h struct.h type.h
+conversion.o: Lpars.h arith.h nobitfield.h nofloat.h sizes.h spec_arith.h type.h
+blocks.o: arith.h atw.h label.h nofloat.h sizes.h spec_arith.h stack.h
+dataflow.o: dataflow.h
 tokenfile.o: Lpars.h
-tokenname.o: LLlex.h Lpars.h arith.h idf.h nofloat.h nopp.h spec_arith.h tokenname.h
-type.o: Lpars.h align.h alloc.h arith.h def.h idf.h nobitfield.h nofloat.h nopp.h sizes.h spec_arith.h storage.h type.h
+declar.o: LLlex.h Lpars.h arith.h debug.h declar.h decspecs.h def.h expr.h field.h file_info.h idf.h label.h nobitfield.h nofloat.h nopp.h sizes.h spec_arith.h storage.h struct.h type.h
+statement.o: LLlex.h Lpars.h arith.h botch_free.h code.h debug.h def.h expr.h file_info.h idf.h label.h nobitfield.h nofloat.h nopp.h spec_arith.h stack.h storage.h type.h
+expression.o: LLlex.h Lpars.h arith.h expr.h file_info.h idf.h label.h nobitfield.h nofloat.h nopp.h spec_arith.h type.h
+program.o: LLlex.h Lpars.h alloc.h arith.h code.h declar.h decspecs.h def.h expr.h file_info.h idf.h label.h nobitfield.h nofloat.h nopp.h spec_arith.h type.h
+Lpars.o: Lpars.h
+char.o: class.h
+symbol2str.o: Lpars.h
index 6de9278..5466fb2 100644 (file)
 #define        DENSITY 2       /* see switch.[ch] for an explanation           */
 
 
-!File: predefine.h
-#define        PREDEFINE       "vax,VAX,BSD4_1,bsd4_1"
-
-
 !File: lapbuf.h
 #define        LAPBUF  4096    /* size of macro actual parameter buffer        */
 
 
 
 !File: inputtype.h
-#undef READ_IN_ONE     1       /* read input file in one       */
+#undef INP_READ_IN_ONE 1       /* read input file in one       */
 
 
 !File: nopp.h
index b3d3215..fe2f9f1 100644 (file)
@@ -24,6 +24,7 @@
 #include       "storage.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.                         */
@@ -223,6 +224,7 @@ do_include()
        /*      do_include() performs the inclusion of a file.
        */
        char *filenm;
+       char *result;
        int tok;
        struct token tk;
 
@@ -235,8 +237,17 @@ do_include()
        }
        AccFileSpecifier = 0;
        SkipRestOfLine();
-       if (filenm && !InsertFile(filenm, &inctable[tok == FILESPECIFIER]))
-               lexerror("cannot find include file \"%s\"", filenm);
+       inctable[0] = WorkingDir;
+       if (filenm) {
+               if (!InsertFile(filenm, &inctable[tok==FILESPECIFIER],&result)){
+                       lexerror("cannot find include file \"%s\"", filenm);
+               }
+               else {
+                       WorkingDir = getwdir(result);
+                       FileName = result;
+                       LineNumber = 0;
+               }
+       }
 }
 
 PRIVATE
@@ -341,35 +352,31 @@ do_if()
 PRIVATE
 do_ifdef(how)
 {
-       struct idf *id;
+       register struct idf *id;
 
        /*      how == 1 : ifdef; how == 0 : ifndef
        */
        push_if();
-       if (id = GetIdentifier()) {
-               if (
-                       (how && !(id && id->id_macro))
-               ||
-                       (!how && id && id->id_macro)
-               ) /* this id is not defined     */
-                       skip_block();
-               else
-                       SkipRestOfLine();
-       }
-       else {
+       if (!(id = GetIdentifier()))
                lexerror("illegal #ifdef construction");
+
+       /* 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
                SkipRestOfLine();
-       }
 }
 
 PRIVATE
 do_undef()
 {
-       struct idf *id;
+       register struct idf *id;
 
        /* Forget a macro definition.   */
        if (id = GetIdentifier()) {
-               if (id && id->id_macro) { /* forget the macro */
+               if (id->id_macro) { /* forget the macro */
                        free_macro(id->id_macro);
                        id->id_macro = (struct macro *) 0;
                } /* else: don't complain */
@@ -406,14 +413,15 @@ getparams(buf, parbuf)
                Note that the '(' has already been eaten.
                The names of the formal parameters are stored into parbuf.
        */
-       register count = 0;
-       register c;
+       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()        */
-               buf[0] = (char *) 0;
+               *pbuf = (char *) 0;
                return 0;
        }
        for (;;) {              /* eat the formal parameter list        */
@@ -421,7 +429,7 @@ getparams(buf, parbuf)
                        lexerror("#define: bad formal parameter");
                        return -1;
                }
-               buf[count++] = ptr;     /* name of the formal   */
+               *pbuf = ptr;    /* name of the formal   */
                *ptr++ = c;
                if (ptr >= &parbuf[PARBUFSIZE])
                        fatal("formal parameter buffer overflow");
@@ -432,10 +440,22 @@ getparams(buf, parbuf)
                                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     */
-                       buf[count] = (char *) 0;
-                       return count;
+                       *pbuf = (char *) 0;
+                       return pbuf - buf;
                }
                if (c != ',') {
                        lexerror("#define: bad formal parameter list");
@@ -444,11 +464,12 @@ getparams(buf, parbuf)
                LoadChar(c);
                c = skipspaces(c);
        }
+       /*NOTREACHED*/
 }
 
 EXPORT
 macro_def(id, text, nformals, length, flags)
-       struct idf *id;
+       register struct idf *id;
        char *text;
 {
        register struct macro *newdef = id->id_macro;
@@ -456,15 +477,12 @@ macro_def(id, text, nformals, length, flags)
        /*      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
-               (unless predefined!)
+               A warning is given if the definition overwrites another.
        */
        if (newdef) {           /* is there a redefinition?     */
-               if ((newdef->mc_flag & PREDEF) == 0) {
-                       if (macroeq(newdef->mc_text, text))
-                               return;
-                       lexwarning("redefine \"%s\"", id->id_text);
-               } /* else: overwrite pre-definition     */
+               if (macroeq(newdef->mc_text, text))
+                       return;
+               lexwarning("redefine \"%s\"", id->id_text);
        }
        else
                id->id_macro = newdef = new_macro();
@@ -472,6 +490,7 @@ macro_def(id, text, nformals, length, flags)
        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
diff --git a/lang/cem/cemcom/file_info.h b/lang/cem/cemcom/file_info.h
new file mode 100644 (file)
index 0000000..1cb1db0
--- /dev/null
@@ -0,0 +1,14 @@
+/* $Header$ */
+/* 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 */
index 2c0b6a6..20c120e 100644 (file)
@@ -5,7 +5,6 @@
 
 #ifndef NOPP
 #include       <system.h>
-#include       "predefine.h"   /* UF */
 #include       "alloc.h"
 #include       "class.h"
 #include       "macro.h"
@@ -57,10 +56,7 @@ init_pp()
        }
 
        /*      Initialize __DATE__, __FILE__ and __LINE__ macro
-               definitions.  The compile-time specified predefined macros
-               are also predefined:  if this file is compiled with
-               -DPREDEFINE="vax,pdp", the macro definitions "vax" and
-               "pdp" are predefined macros.
+               definitions.
        */
        /* __DATE__     */
        clock = sys_time();
@@ -77,33 +73,5 @@ init_pp()
 
        /* defined(??) */
        macro_def(str2idf("defined"), "", 1, 1, FUNC);
-
-#ifdef PREDEFINE
-       {
-               /*      PREDEFINE is a compile-time defined string
-                       containing a number of identifiers to be
-                       predefined at the host machine (for example
-                       -DPREDEFINE="vax,unix,pmds").
-               */
-               register char *s = PREDEFINE;
-               register char *id;
-               char c;
-
-               for (;;)        {
-                       while (*s && class(*s++) != STIDF);
-                       if (*s) {
-                               /* gobble identifier */
-                               id = s - 1;
-                               while (in_idf(*s++));
-                               c = *--s;
-                               *s = '\0';
-                               macro_def(str2idf(id), "1", -1, 1, PREDEF);
-                               *s = c;
-                       }
-                       else
-                               break;
-               }
-       }
-#endif PREDEFINE
 }
 #endif NOPP
index fd6de23..c362503 100644 (file)
 /* $Header$ */
-/*     INPUT AND BUFFER HANDLING MODULE        */
 
-/*
-       [input.c input.h]
-       Input buffering module: this module contains the routines that
-       offers an input buffering mechanism to the user.
-
-       This module exports the following objects:
-       InsertFile() :  suspend input from current buffer and obtain the
-                       next input characters from the specified file
-       InsertText() :  suspend input from current buffer and take the
-                       specified text as stream of input characters
-       LoadChar() :    (defined in input.h) read next character from
-                       the input ; LoadChar() invokes loadbuf() on
-                       encounting a ASCII NUL character
-       NoUnstack :     if set to non-zero:
-                       loadbuf() reports "unexpected EOF" on encounting
-                       the end-of-file or end-of-stacked-text.
-       
-       Imported objects are:
-       IDEPTH, DEBUG, READ_IN_ONE, PATHLENGTH: compile-time parameters
-       Malloc(), Salloc(): memory allocation routines
-       fatal(), lexerror(): exception handling
-       FileName, LineNumber, WorkingDir: input trace for lexical analyser
-
-       READ_IN_ONE DEFINED: every input file is read into memory completely
-               and made an input buffer
-       READ_IN_ONE NOT DEFINED: the input from files is buffered in
-               a fixed length input buffer
-*/
-
-#include       <system.h>
-#include       "nopp.h"
-#include       "inputtype.h"
-#include       "interface.h"
-#include       "arith.h"
-#include       "LLlex.h"
-#include       "input.h"
-#include       "alloc.h"
-
-#ifndef NOPP
-#include       "idepth.h"
-#include       "debug.h"
-#include       "pathlength.h"
-#include       "assert.h"
-#include       "static.h"
-#endif NOPP
-
-EXPORT char *ipp = 0;          /* input pointer        */
-EXPORT int NoUnstack = 0;      /* if 1: report EOF     */
-
-#ifndef READ_IN_ONE
-PRIVATE File *FilDes = 0;      /* current input medium */
-#endif READ_IN_ONE
+#include "inputtype.h"
+#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>
+#include "nopp.h"
 
 #ifndef NOPP
-struct buffer_header   {
-       char *bh_name;  /* file name where the text comes from  */
-       unsigned int bh_lineno;
-                       /* current lineno in file               */
-       long bh_size;   /* = strlen (text), should be unsigned  */
-       char *bh_text;  /* pointer to buffer containing text    */
-       char *bh_ipp;   /* current read pointer (= stacked ipp) */
-       char *bh_wdir;  /* directory of current file            */
-       File *bh_fp;    /* needed for files if !READ_IN_ONE     */
-};
-
-PRIVATE struct buffer_header instack[IDEPTH];  /* stack of input media */
-PRIVATE struct buffer_header *head  = 0;       /* current input buffer */
-
-IMPORT char **WorkingDir;      /* name of current working directory    */
-#else NOPP
-long isize;
-char ibuf[BUFSIZ + 1];
-#endif NOPP
-
-#ifdef READ_IN_ONE
-/*     readfile() creates a buffer in which the text of the file
-       is situated.  A pointer to the start of this text is
-       returned.  *size is initialized with the buffer length.
-       Note that the file input buffer is prepared for the
-       preprocessor by inserting a '\n' in the beginning of the
-       text and appending a '\n' at the end of the text.  The
-       file text start at position 1 of the input buffer. This is
-       done to allow pushback.
-*/
-
-PRIVATE char *
-readfile(filename, size)
-       char *filename;
-       long *size;
-{
-       File *fp;               /* filedescriptor for `filename'        */
-       char *cbuf;             /* pointer to buffer to be returned     */
-       int tmp;
-       long sys_filesize();
-
-       if (sys_open(filename, OP_READ, &fp) == 0) /* can't open this file */
-               return (char *) 0;
-       if ((*size = sys_filesize(filename)) == -1L)
-               fatal("(readfile) cannot get size of file");
-       /* allocate enough space to store contents of the file          */
-       cbuf = Malloc(*size + 2);
-       if (sys_read(fp, cbuf + 1, (int) *size, &tmp) == 0 || tmp != *size)
-               fatal("(readfile) bad read");
-       (*size)++;              /* keep book of the size!       */
-       sys_close(fp);          /* filedes no longer needed     */
-       cbuf[0] = '\0';         /* allow pushback of first char */
-       cbuf[*size] = '\0';     /* invoke loadbuf() at end      */
-       return cbuf;
-}
-#endif READ_IN_ONE
-
-#ifndef NOPP
-#ifndef READ_IN_ONE
-/*     Input buffer supplying routines: pushbuf() and popbuf()
-*/
-PRIVATE char *bufstack[IDEPTH] = 0;
-PRIVATE bufstptr = 0;
-
-PRIVATE char *
-pushbuf()
-{
-       if (bufstptr >= IDEPTH)
-               fatal("ran out of input buffers");
-       if (bufstack[bufstptr] == 0) {
-               bufstack[bufstptr] = Malloc(BUFSIZ + 4);
-       }
-       return bufstack[bufstptr++];
-}
-
-PRIVATE
-popbuf()
-{
-       bufstptr--;
-       ASSERT(bufstptr >= 0);
-}
-#endif READ_IN_ONE
-#endif NOPP
-
-#ifndef NOPP
-/*     Input buffer administration: push_bh() and pop_bh()
-*/
-PRIVATE struct buffer_header *
-push_bh()
-{
-       if (head) {
-               if (head >= &instack[IDEPTH - 1])
-                       fatal("too many nested input texts");
-               head->bh_ipp = ipp;
-               head->bh_lineno = LineNumber;
-               head++;
-       }
-       else
-               head = &instack[0];
-
-       return head;
-}
-#endif NOPP
-
-#ifndef NOPP
-/*     pop_bh() uncovers the previous inputbuffer on the stack
-       of headers.  0 is returned if there are no more
-       inputbuffers on the stack, 1 is returned in the other case.
-*/
-PRIVATE int
-pop_bh()
-{
-       File *pfp = head->bh_fp;
-
-       if (NoUnstack) {
-               lexerror("unexpected EOF");
-       }
-
-       if (head <= &instack[0])        {       /* no more entries      */
-               head = (struct buffer_header *) 0;
-               return 0;
-       }
-
-       ipp = (--head)->bh_ipp; /* restore the previous input pointer   */
-
-       if (pfp != 0)   {               /* unstack a file       */
-#ifndef READ_IN_ONE
-               closefile(pfp);
-               popbuf();               /* free last buffer     */
-#endif READ_IN_ONE
-               LineNumber = head->bh_lineno;
-               FileName = head->bh_name;
-               *WorkingDir = head->bh_wdir;
-       }
-
-#ifndef READ_IN_ONE
-       FilDes = head->bh_fp;
-#endif READ_IN_ONE
-
-       return 1;
-}
-#endif NOPP
-
-#ifndef READ_IN_ONE
-/*     low level IO routines: openfile(), readblock() and closefile()
-*/
-
-PRIVATE File *
-openfile(filename)
-       char *filename;
-{
-       File *fp;
-
-       if (filename == 0)
-               return STDIN;
-       if (sys_open(filename, OP_READ, &fp) == 0)
-               return (File *)0;
-       return fp;
-}
-
-PRIVATE
-closefile(fp)
-       File *fp;
-{
-       if (fp != STDIN)
-               sys_close(fp);
-}
-
-PRIVATE int
-readblock(fp, buf)
-       File *fp;
-       char buf[];
-{
-       int n;
-
-       if (sys_read(fp, &buf[1], BUFSIZ, &n) == 0)
-               fatal("(readblock) bad read");
-       buf[0] = buf[n + 1] = '\0';
-       return n;
-}
-#endif READ_IN_ONE
-
-/*     Interface routines : InsertFile(), InsertText() and loadbuf()
-*/
-
-EXPORT int
-InsertFile(filnam, table)
-       char *filnam;
-       char *table[];
-{
-       char *mk_filename(), *newfn;
-       char *strcpy();
-       File *openfile();
-
-#ifdef READ_IN_ONE
-       char *readfile(), *text;
-       long size;
-#else READ_IN_ONE
-       File *fp = 0;
-#endif READ_IN_ONE
-
-#ifdef READ_IN_ONE
-       if (!filnam)
-               return 0;
-#endif READ_IN_ONE
-
-#ifndef NOPP
-       if (table == 0 || filnam[0] == '/') {   /* don't look in the table! */
-#endif NOPP
-#ifdef READ_IN_ONE
-               text = readfile(filnam, &size);
-#else READ_IN_ONE
-               fp = openfile(filnam);
-               if (filnam == 0)
-                       filnam = "standard input";
-#endif READ_IN_ONE
-#ifndef NOPP
-       }
-       else {
-               ASSERT(filnam != 0);
-               while (*table) {        /* look in the directory table  */
-                       newfn = mk_filename(*table++, filnam);
-#ifdef READ_IN_ONE
-                       if (text = readfile(newfn, &size))
-#else READ_IN_ONE
-                       if ((fp = openfile(newfn)) != 0)
-#endif READ_IN_ONE
-                       {
-                               /* free filnam ??? */
-                               filnam = Salloc(newfn, strlen(newfn) + 1);
-                               break;
-                       }
-               }
-       }
-#endif NOPP
-
-#ifdef READ_IN_ONE
-       if (text)
-#else READ_IN_ONE
-       if (fp != 0)
-#endif READ_IN_ONE
-#ifndef NOPP
-       {
-               struct buffer_header *push_bh();
-               register struct buffer_header *bh = push_bh();
-
-               setwdir(WorkingDir, filnam);
-               bh->bh_lineno = LineNumber = 0;
-               bh->bh_name = FileName = filnam;
-               bh->bh_wdir = *WorkingDir;
-#ifdef READ_IN_ONE
-               bh->bh_size = size;
-               bh->bh_fp = STDIN;              /* this is a file */
-               ipp = bh->bh_text = text;
-#else READ_IN_ONE
-               bh->bh_size = readblock(fp, ipp = bh->bh_text = pushbuf()) + 1;
-               FilDes = bh->bh_fp = fp;
-#endif READ_IN_ONE
-               bh->bh_text[0] = '\n';  /* wake up pp if '#' comes first */
-               return 1;
-       }
-#else NOPP
-       {
-               LineNumber = 0;
-               FileName = filnam;
-#ifdef READ_IN_ONE
-               isize = size;
-               ipp = text;
-#else READ_IN_ONE
-               isize = readblock(FilDes = fp, ipp = &ibuf[0]) + 1;
-#endif READ_IN_ONE
-               ibuf[0] = '\n';
-               return 1;
-       }
-#endif NOPP
-       return 0;
-}
-
-#ifndef NOPP
-EXPORT
-InsertText(text, length)
-       char *text;
-{
-       struct buffer_header *push_bh();
-       register struct buffer_header *bh = push_bh();
-
-       bh->bh_name = FileName;
-       bh->bh_lineno = LineNumber;
-       bh->bh_size = (long) length;
-       bh->bh_text = text;
-       bh->bh_wdir = *WorkingDir;
-       bh->bh_fp = 0;  /* this is not a file ! */
-       ipp = text + 1;
-#ifndef READ_IN_ONE
-       FilDes = 0;
-#endif READ_IN_ONE
-}
-#endif NOPP
-
-/*     loadbuf() is called if LoadChar meets a '\0' character
-       which may be the end-of-buffer mark of the current input
-       buffer.  The '\0' could be genuine although not likely.
-       Note: this routine is exported due to its occurence in the definition
-       of LoadChar [input.h], that is defined as a macro.
-*/
-EXPORT int
-loadbuf()
-{
-#ifndef NOPP
-       if (!head) /* stack exhausted, EOF on sourcefile        */
-               return EOI;
-#endif NOPP
-       
-#ifndef NOPP
-       if (ipp < &(head->bh_text[head->bh_size]))
-#else NOPP
-       if (ipp < &ibuf[isize])
-#endif NOPP
-               return '\0'; /* a genuine '\0' character has been seen  */
-
-#ifndef READ_IN_ONE
-#ifndef NOPP
-       if (    FilDes != 0
-       &&      (head->bh_size = readblock(FilDes, head->bh_text)) > 0
-       )
-               return ipp = &(head->bh_text[1]), *ipp++;
-#else NOPP
-       if (FilDes != 0 && (isize = readblock(FilDes, &ibuf[0])) > 0)
-               return ipp = &ibuf[1], *ipp++;
-#endif NOPP
-#endif READ_IN_ONE
-
-#ifdef NOPP
-       if (NoUnstack)
-               lexerror("unexpected EOF");
-#ifndef READ_IN_ONE
-       closefile(FilDes);
-#endif READ_IN_ONE
-#endif NOPP
-
-#ifndef NOPP
-       if (pop_bh())
-               return *ipp ? *ipp++ : loadbuf();
-#endif NOPP
-       ipp = &"\0\0"[1];
-       return EOI;
-}
-
-/*     Some miscellaneous routines : setwdir() and mk_filename()
-*/
-
-#ifndef NOPP
-/*     setwdir() updates *wdir according to the old working
-       directory (*wdir) and the filename fn, which may contain
-       some path name.  The algorithm used here is:
-       setwdir(DIR, FILE):
-               if (FILE == "/***")
-                       *DIR = "/"
-               else
-               if (contains(FILE, '/'))
-                       *DIR = directory(FILE)
-               else
-                       *DIR remains unchanged
-*/
-PRIVATE
-setwdir(wdir, fn)
-       char *fn, **wdir;
+char *
+getwdir(fn)
+       char *fn;
 {
        register char *p;
        char *strrindex();
@@ -433,32 +24,31 @@ setwdir(wdir, fn)
        }
 
        if (fn[0] == '\0' || (fn[0] == '/' && p == &fn[0])) /* absolute path */
-               *wdir = "/";
+               return "";
        else
        if (p) {
                *p = '\0';
-               *wdir = Salloc(fn, p - &fn[0] + 1);
+               fn = Salloc(fn, p - &fn[0] + 1);
                *p = '/';
+               return fn;
        }
+       else return ".";
 }
 #endif NOPP
 
-#ifndef NOPP
-/*     mk_filename() concatenates a dir and filename.
-*/
-GSTATIC char path[PATHLENGTH];
+int    NoUnstack;
 
-PRIVATE char *
-mk_filename(dir, file)
-       register char *dir, *file;
+AtEoIT()
 {
-       register char *dst = &path[0];
+#ifndef NOPP
+       if (NoUnstack) lexerror("unexpected EOF");
+       DoUnstack();
+#endif NOPP
+       return 0;
+}
 
-       if (!(dir[0] == '.' && dir[1] == '\0')) {
-               while (*dst++ = *dir++);
-               *(dst - 1) = '/';
-       }
-       while (*dst++ = *file++);
-       return &path[0];
+AtEoIF()
+{
+       if (NoUnstack) lexerror("unexpected EOF");
+       return 0;
 }
-#endif NOPP
index 1118562..aa22fff 100644 (file)
@@ -1,13 +1,3 @@
 /* $Header$ */
-/* INPUT PRIMITIVES */
 
-#define        LoadChar(dest)  ((dest = *ipp++) || (dest = loadbuf()))
-#define        PushBack()      (ipp--)
-                               
-/*     EOF may be defined as -1 in most programs but the character -1 may
-       be expanded to the int -1 which causes troubles at the indexing in
-       the class or boolean arrays.
-*/
-#define        EOI     (0200)
-                       
-extern char *ipp;
+#include <inp_pkg.spec>
index 34a62dd..ef32432 100644 (file)
@@ -9,7 +9,7 @@
 */
 #define NOFLAG         0               /* no special flags     */
 #define        FUNC            01              /* function attached    */
-#define        PREDEF          02              /* predefined macro     */
+#define NOREPLACE      02              /* don't replace        */
 
 #define        FORMALP 0200    /* mask for creating macro formal parameter     */
 
@@ -21,8 +21,9 @@
 struct macro   {
        struct macro *next;
        char *  mc_text;        /* the replacement text         */
-       int     mc_nps; /* number of formal parameters  */
+       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           */
 };
 
index b9fa691..28d67c2 100644 (file)
@@ -34,7 +34,7 @@ char *inctable[MAXINCL] = {           /* list for includes    */
        0
 };
 
-char **WorkingDir = &inctable[0];
+extern char *getwdir();
 #endif NOPP
 
 struct sp_id special_ids[] =   {
@@ -90,19 +90,17 @@ main(argc, argv)
 #endif NOPP
 
        /*      Note: source file "-" indicates that the source is supplied
-               as standard input.  This is only allowed if READ_IN_ONE is
+               as standard input.  This is only allowed if INP_READ_IN_ONE is
                not defined!
        */
-#ifdef READ_IN_ONE
+#ifdef INP_READ_IN_ONE
        while (argc > 1 && *argv[1] == '-')
-#else READ_IN_ONE
+#else INP_READ_IN_ONE
        while (argc > 1 && *argv[1] == '-' && argv[1][1] != '\0')
-#endif READ_IN_ONE
+#endif INP_READ_IN_ONE
        {
                char *par = &argv[1][1];
 
-               if (*par == '-')
-                       par++;
                do_option(par);
                argc--, argv++;
        }
@@ -139,6 +137,7 @@ compile(argc, argv)
 #ifdef USE_TMP
        char tmpf[256];
 #endif
+       char *result;
 
 #ifndef NOPP
        int pp_only = options['E'] || options['P'];
@@ -172,11 +171,15 @@ compile(argc, argv)
 
        if (destination && strcmp(destination, "-") == 0)
                destination = 0;
-       if (!InsertFile(source, (char **) 0)) /* read the source file   */
+       if (!InsertFile(source, (char **) 0, &result)) /* read the source file  */
                fatal("%s: no source file %s\n", prog_name, 
                        source ? source : "stdin");
        init();
-       /* FileName = source; /* needed ???     */
+       FileName = source;
+       LineNumber = 0;
+#ifndef NOPP
+       WorkingDir = getwdir(source);
+#endif NOPP
        PushLex();
 
 #ifndef NOPP
index d862e0f..38525c0 100644 (file)
@@ -34,7 +34,10 @@ do_option(text)
        switch(*text++) {
 
        default:
-               options[text[-1]] = 1;  /* flags, debug options etc.    */
+               fatal("illegal option: %c", *--text);
+
+       case '-':
+               options[*text] = 1;     /* flags, debug options etc.    */
                break;
 
        case 'C' :      /* E option + comment output            */
@@ -105,6 +108,7 @@ do_option(text)
                                new = tmp;
                        }
                }
+               else inctable[inc_pos] = 0;
 #else NOPP
                warning("-I option ignored");
 #endif NOPP
@@ -135,6 +139,10 @@ do_option(text)
 #endif NOPP
                break;
 
+       case 'R':
+               options['R'] = 1;
+               break;
+
 #ifdef USE_TMP
        case 'T' :
                if (*text)
index 21c98c0..169f0a1 100644 (file)
 char *strcpy(), *strcat();
 char *long2str();
 
+PRIVATE struct macro   *ReplaceList;   /* list of currently active macros */
+
 EXPORT int
 replace(idef)
-       struct idf *idef;
+       register struct idf *idef;
 {
        /*      replace() is called by the lexical analyzer to perform
                macro replacement.  "idef" is the description of the
@@ -34,14 +36,18 @@ replace(idef)
                replace() returns 1 if the replacement succeeded and 0 if
                some error has occurred.
        */
+       register struct macro *mac = idef->id_macro;
        register char c;
-       register char flags = idef->id_macro->mc_flag;
        char **actpars, **getactuals();
        char *reptext, *macro2buffer();
        int size;
 
-       if (idef->id_macro->mc_nps != -1) {     /* with parameter list  */
-               if (flags & FUNC) {
+       if (mac->mc_flag & NOREPLACE) {
+               lexwarning("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 ...
@@ -50,6 +56,12 @@ replace(idef)
                        if (! AccDefined)
                                return 0;
                }
+               if (++mac->mc_count > 100) {
+                       /* 100 must be some number in Parameters */
+                       lexwarning("macro %s is assumed recursive",
+                                   idef->id_text);
+                       return 0;
+               }
                LoadChar(c);
                c = skipspaces(c);
                if (c != '(') {         /* no replacement if no ()      */
@@ -59,23 +71,27 @@ replace(idef)
                        return 0;
                }
                actpars = getactuals(idef);     /* get act.param. list  */
-               if (flags & FUNC) {
+               if (mac->mc_flag & FUNC) {
                        struct idf *param = str2idf(*actpars);
 
                        if (param->id_macro) 
-                               reptext = "\0001";
+                               reptext = "1";
                        else
-                               reptext = "\0000";
-                       InsertText(reptext, 2);
+                               reptext = "0";
+                       InsertText(reptext, 1);
+                       mac->next = ReplaceList;
+                       ReplaceList = mac;
                        return 1;
                }
        }
-       if ((flags & PREDEF) && (UnknownIdIsZero == 0)) /* don't replace */
-               return 0;
-       if (flags & FUNC)       /* this macro leads to special action   */
+       if (mac->mc_flag & FUNC) /* this macro leads to special action  */
                macro_func(idef);
+       if (mac->mc_nps <= 0)
+               mac->mc_flag |= NOREPLACE;
        reptext = macro2buffer(idef, actpars, &size); /* create input buffer */
        InsertText(reptext, size);
+       mac->next = ReplaceList;
+       ReplaceList = mac;
        return 1;
 }
 
@@ -83,24 +99,26 @@ GSTATIC char FilNamBuf[PATHLENGTH];
 
 PRIVATE
 macro_func(idef)
-       struct idf *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__     */
                FilNamBuf[0] = '"';
                strcpy(&FilNamBuf[1], FileName);
                strcat(FilNamBuf, "\"");
-               idef->id_macro->mc_text = FilNamBuf;
-               idef->id_macro->mc_length = strlen(FilNamBuf);
+               mac->mc_text = FilNamBuf;
+               mac->mc_length = strlen(FilNamBuf);
                break;
        case 'L' :                      /* __LINE__     */
-               idef->id_macro->mc_text = long2str((long)LineNumber, 10);
-               idef->id_macro->mc_length = 1;
+               mac->mc_text = long2str((long)LineNumber, 10);
+               mac->mc_length = 1;
                break;
        default :
                crash("(macro_func)");
@@ -125,10 +143,9 @@ macro2buffer(idef, actpars, siztext)
        */
        register int size = 8;
        register char *text = Malloc(size);
-       register pos = 0;
+       register int pos = 0;
        register char *ptr = idef->id_macro->mc_text;
 
-       text[pos++] = '\0';                     /* allow pushback       */
        while (*ptr) {
                if (*ptr & FORMALP) {   /* non-asc formal param. mark   */
                        register int n = *ptr++ & 0177;
@@ -138,7 +155,7 @@ macro2buffer(idef, actpars, siztext)
                        /*      copy the text of the actual parameter
                                into the replacement text
                        */
-                       for (p = actpars[n - 1]; *p; p++) {
+                       for (p = actpars[n - 1]; p && *p; p++) {
                                text[pos++] = *p;
                                if (pos == size)
                                        text = Srealloc(text, size += RSTRSIZE);
@@ -154,4 +171,26 @@ macro2buffer(idef, actpars, siztext)
        *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;
+}
 #endif NOPP