/* 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 */
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
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 `#'.
hash = STARTHASH();
do { /* read the identifier */
if (++pos < idfsize) {
+#ifndef NOPP
+ if (Unstacked) EnableMacros();
+#endif
*tg++ = ch;
hash = ENHASH(hash, ch, pos);
}
}
if (ch == '\\') {
LoadChar(ch);
- if (ch == '\n')
+ if (ch == '\n') {
LineNumber++;
+ continue;
+ }
ch = quoted(ch);
}
str[pos++] = ch;
*/
#include "nofloat.h"
+#include "file_info.h"
/* the structure of a token: */
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" */
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 */
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
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
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
$(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
#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
#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. */
/* do_include() performs the inclusion of a file.
*/
char *filenm;
+ char *result;
int tok;
struct token tk;
}
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
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 */
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 */
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");
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");
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;
/* 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();
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
--- /dev/null
+/* $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 */
#ifndef NOPP
#include <system.h>
-#include "predefine.h" /* UF */
#include "alloc.h"
#include "class.h"
#include "macro.h"
}
/* 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();
/* 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
/* $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();
}
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
/* $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>
*/
#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 */
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 */
};
0
};
-char **WorkingDir = &inctable[0];
+extern char *getwdir();
#endif NOPP
struct sp_id special_ids[] = {
#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++;
}
#ifdef USE_TMP
char tmpf[256];
#endif
+ char *result;
#ifndef NOPP
int pp_only = options['E'] || options['P'];
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
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 */
new = tmp;
}
}
+ else inctable[inc_pos] = 0;
#else NOPP
warning("-I option ignored");
#endif NOPP
#endif NOPP
break;
+ case 'R':
+ options['R'] = 1;
+ break;
+
#ifdef USE_TMP
case 'T' :
if (*text)
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
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 ...
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 () */
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;
}
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)");
*/
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;
/* 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);
*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