version using input module and detecting preprocessor loops

This commit is contained in:
ceriel 1986-12-04 16:29:44 +00:00
parent 91aad0b28e
commit 53d6dfcb6b
13 changed files with 239 additions and 599 deletions

View 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;

View 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 */

View 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
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
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
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
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
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
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
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
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
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
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
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

View file

@ -42,10 +42,6 @@
#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 */
@ -115,7 +111,7 @@
!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

View 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

View file

@ -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 */

View 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

View file

@ -1,427 +1,18 @@
/* $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"
#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
#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
#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];
if (!(dir[0] == '.' && dir[1] == '\0')) {
while (*dst++ = *dir++);
*(dst - 1) = '/';
}
while (*dst++ = *file++);
return &path[0];
}
#ifndef NOPP
if (NoUnstack) lexerror("unexpected EOF");
DoUnstack();
#endif NOPP
return 0;
}
AtEoIF()
{
if (NoUnstack) lexerror("unexpected EOF");
return 0;
}

View 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>

View 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 */
};

View 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

View 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)

View file

@ -21,9 +21,11 @@
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