2 * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
3 * See the copyright notice in the ACK home directory, in the file "Copyright".
5 /* $Id: domacro.c,v 1.26 1994/06/24 10:18:07 ceriel Exp $ */
6 /* PREPROCESSOR: CONTROLLINE INTERPRETER */
16 #include "botch_free.h"
18 #include "parbufsize.h"
27 IMPORT char **inctable; /* list of include directories */
28 IMPORT char *getwdir();
29 PRIVATE char ifstack[IFDEPTH]; /* if-stack: the content of an entry is */
30 /* 1 if a corresponding ELSE has been */
34 int svnestlevel[30] = {-1};
36 extern int do_preprocess;
41 /* returns a pointer to the descriptor of the identifier that is
42 read from the input stream. A null-pointer is returned if
43 the input does not contain an identifier.
44 The substitution of macros is disabled.
52 return tok == IDENTIFIER ? tk.tk_str : (char *)0;
55 /* domacro() is the control line interpreter. The '#' has already
56 been read by the lexical analyzer by which domacro() is called.
57 The token appearing directly after the '#' is obtained by calling
58 the basic lexical analyzing function GetToken() and is interpreted
59 to perform the action belonging to that token.
60 An error message is produced when the token is not recognized,
61 i.e. it is not one of "define" .. "undef" , integer or newline.
66 struct token tk; /* the token itself */
67 register struct idf *id;
69 switch(GetToken(&tk)) { /* select control line action */
70 case IDENTIFIER: /* is it a macro keyword? */
71 id = findidf(tk.tk_str);
73 error("%s: unknown control", tk.tk_str);
79 switch (id->id_resmac) {
80 case K_DEFINE: /* "define" */
83 case K_ELIF: /* "elif" */
86 case K_ELSE: /* "else" */
89 case K_ENDIF: /* "endif" */
95 case K_IFDEF: /* "ifdef" */
98 case K_IFNDEF: /* "ifndef" */
101 case K_INCLUDE: /* "include" */
104 case K_LINE: /* "line" */
105 /* set LineNumber and FileName according to
108 if (GetToken(&tk) != INTEGER) {
109 error("#line without linenumber");
114 do_line((unsigned int)tk.tk_val);
116 case K_UNDEF: /* "undef" */
119 case K_PRAGMA: /* "pragma" */
125 /* invalid word seen after the '#' */
126 error("%s: unknown control", id->id_text);
130 case INTEGER: /* # <integer> [<filespecifier>]? */
131 do_line((unsigned int)tk.tk_val);
133 case EOF: /* only `#' on this line: do nothing, ignore */
135 default: /* invalid token following '#' */
136 error("illegal # line");
145 /* skip_block() skips the input from
146 1) a false #if, #ifdef, #ifndef or #elif until the
147 corresponding #elif (resulting in true), #else or
149 2) a #else corresponding to a true #if, #ifdef,
150 #ifndef or #elif until the corresponding #endif is
154 register int skiplevel = nestlevel; /* current nesting level */
160 LoadChar(ch); /* read first character after newline */
170 if (GetToken(&tk) != IDENTIFIER) {
175 /* an IDENTIFIER: look for #if, #ifdef and #ifndef
176 without interpreting them.
177 Interpret #else, #elif and #endif if they occur
180 id = findidf(tk.tk_str);
182 if (id) switch(id->id_resmac) {
193 if (ifstack[nestlevel])
194 warning("#elif after #else/#elif");
195 if (! to_endif && nestlevel == skiplevel) {
198 if (ifexpr()) { /* implicit skipline() */
206 if (ifstack[nestlevel])
207 warning("#else after #else/#elif");
210 ++(ifstack[nestlevel]);
211 if (nestlevel == skiplevel) {
218 assert(nestlevel >= 0);
220 if (nestlevel == skiplevel) {
234 /* ifexpr() returns whether the restricted constant
235 expression following #if or #elif evaluates to true. This
236 is done by calling the LLgen generated subparser for
237 constant expressions. The result of this expression will
238 be given in the extern long variable "ifval".
241 int errors = err_occurred;
246 PushLex(); /* NEW parser */
247 If_expr(); /* invoke constant expression parser */
248 PopLex(); /* OLD parser */
251 return (errors == err_occurred) && (ifval != (arith)0);
257 /* do_include() performs the inclusion of a file.
264 AccFileSpecifier = 1;
265 if (((tok = GetToken(&tk)) == FILESPECIFIER) || tok == STRING)
268 error("bad include syntax");
271 AccFileSpecifier = 0;
274 inctable[0] = WorkingDir;
276 if (!InsertFile(filenm, &inctable[tok==FILESPECIFIER],&result)){
277 if (do_preprocess) error("cannot find include file \"%s\"", filenm);
278 else warning("cannot find include file \"%s\"", filenm);
279 add_dependency(filenm);
282 add_dependency(result);
283 WorkingDir = getwdir(result);
284 svnestlevel[++nestcount] = nestlevel;
294 /* do_define() interprets a #define control line.
297 int nformals = -1; /* keep track of the number of formals */
298 char *formals[NPARAMS]; /* pointers to the names of the formals */
299 char parbuf[PARBUFSIZE]; /* names of formals */
300 char *repl_text; /* start of the replacement text */
301 int length; /* length of the replacement text */
305 /* read the #defined macro's name */
306 if (!(str = GetIdentifier())) {
307 error("#define: illegal macro name");
312 /* there is a formal parameter list if the identifier is
313 followed immediately by a '('.
317 if ((nformals = getparams(formals, parbuf)) == -1) {
321 return; /* an error occurred */
325 /* read the replacement text if there is any */
326 ch = skipspaces(ch,0); /* find first character of the text */
328 if (class(ch) == STNL) {
329 /* Treat `#define something' as `#define something ""'
336 repl_text = get_text((nformals > 0) ? formals : 0, &length);
338 macro_def(str2idf(str, 0), repl_text, nformals, length, NOFLAG);
345 if (nestlevel >= IFDEPTH)
346 fatal("too many nested #if/#ifdef/#ifndef");
348 ifstack[++nestlevel] = 0;
354 if (nestlevel <= svnestlevel[nestcount] || (ifstack[nestlevel])) {
355 error("#elif without corresponding #if");
358 else { /* restart at this level as if a #if is detected. */
369 if (nestlevel <= svnestlevel[nestcount] || (ifstack[nestlevel]))
370 error("#else without corresponding #if");
371 else { /* mark this level as else-d */
372 ++(ifstack[nestlevel]);
381 if (nestlevel <= svnestlevel[nestcount])
382 error("#endif without corresponding #if");
390 if (!ifexpr()) /* a false #if/#elif expression */
397 register struct idf *id;
400 /* how == 1 : ifdef; how == 0 : ifndef
403 str = GetIdentifier();
405 error("illegal #ifdef construction");
413 /* The next test is a shorthand for:
414 (how && !id->id_macro) || (!how && id->id_macro)
416 if (how ^ (id && id->id_macro != 0))
427 register struct idf *id;
428 register char *str = GetIdentifier();
430 /* Forget a macro definition. */
432 if (id = findidf(str)) {
433 if (id->id_macro) { /* forget the macro */
434 free_macro(id->id_macro);
435 id->id_macro = (struct macro *) 0;
436 } /* else: don't complain */
441 error("illegal #undef construction");
451 int t = GetToken(&tk);
455 LineNumber = l; /* the number of the next input line */
456 if (t == STRING) /* is there a filespecifier? */
457 FileName = tk.tk_str;
461 getparams(buf, parbuf)
465 /* getparams() reads the formal parameter list of a macro
467 The number of parameters is returned.
468 As a formal parameter list is expected when calling this
469 routine, -1 is returned if an error is detected, for
471 #define one(1), where 1 is not an identifier.
472 Note that the '(' has already been eaten.
473 The names of the formal parameters are stored into parbuf.
475 register char **pbuf = &buf[0];
477 register char *ptr = &parbuf[0];
478 register char **pbuf2;
482 if (c == ')') { /* no parameters: #define name() */
486 for (;;) { /* eat the formal parameter list */
487 if (class(c) != STIDF) { /* not an identifier */
488 error("#define: bad formal parameter");
491 *pbuf = ptr; /* name of the formal */
493 if (ptr >= &parbuf[PARBUFSIZE])
494 fatal("formal parameter buffer overflow");
495 do { /* eat the identifier name */
498 if (ptr >= &parbuf[PARBUFSIZE])
499 fatal("formal parameter buffer overflow");
501 *(ptr - 1) = '\0'; /* mark end of the name */
503 /* Check if this formal parameter is already used.
504 Usually, macros do not have many parameters, so ...
506 for (pbuf2 = pbuf - 1; pbuf2 >= &buf[0]; pbuf2--) {
507 if (!strcmp(*pbuf2, *pbuf)) {
508 warning("formal parameter \"%s\" already used",
515 if (c == ')') { /* end of the formal parameter list */
520 error("#define: bad formal parameter list");
530 macro_def(id, text, nformals, length, flags)
531 register struct idf *id;
534 /* macro_def() puts the contents and information of a macro
535 definition into a structure and stores it into the symbol
536 table entry belonging to the name of the macro.
537 A warning is given if the definition overwrites another.
539 register struct macro *newdef = id->id_macro;
541 if (newdef) { /* is there a redefinition? */
542 if (macroeq(newdef->mc_text, text))
544 warning("redefine \"%s\"", id->id_text);
548 register char *p = id->id_text;
549 #define setbit(bx) if (!*p) goto go_on; bits[*p++] |= (bx)
561 id->id_macro = newdef = new_macro();
563 newdef->mc_text = text; /* replacement text */
564 newdef->mc_nps = nformals; /* nr of formals */
565 newdef->mc_length = length; /* length of repl. text */
566 newdef->mc_flag = flags; /* special flags */
567 newdef->mc_count = 0;
574 /* find_name() returns the index of "nm" in the namelist
575 "index" if it can be found there. 0 is returned if it is
578 register char **ip = &index[0];
581 if (strcmp(nm, *ip++) == 0)
582 return ip - &index[0];
583 /* arrived here, nm is not in the name list. */
588 get_text(formals, length)
592 /* get_text() copies the replacement text of a macro
593 definition with zero, one or more parameters, thereby
594 substituting each formal parameter by a special character
595 (non-ascii: 0200 & (order-number in the formal parameter
596 list)) in order to substitute this character later by the
597 actual parameter. The replacement text is copied into
598 itself because the copied text will contain fewer or the
599 same amount of characters. The length of the replacement
603 finite automaton : we are only interested in
604 identifiers, because they might be replaced by some actual
605 parameter. Other tokens will not be seen as such.
608 register unsigned int text_size;
609 char *text = Malloc(text_size = ITEXTSIZE);
610 register unsigned int pos = 0;
614 while ((c != EOI) && (class(c) != STNL)) {
615 if (c == '\\') { /* check for "\\\n" */
618 /* More than one line is used for the
620 Replace "\\\n" by " ".
628 if (pos == text_size)
629 text = Realloc(text, text_size <<= 1);
636 /* text[pos++] = ' '; ??? Why ??? */
641 if (pos == text_size)
642 text = Realloc(text, text_size <<= 1);
645 if (formals && class(c) == STIDF) {
646 char id_buf[IDFSIZE + 1];
647 register char *idp = id_buf;
650 /* read identifier: it may be a formal parameter */
654 if (idp <= &id_buf[IDFSIZE])
658 if (n = find_name(id_buf, formals)) {
659 /* construct the formal parameter mark */
660 text[pos++] = FORMALP | (char) n;
661 if (pos == text_size)
666 int sz = idp - id_buf + 1;
670 while (pos + sz >= text_size) text_size <<= 1;
671 text = Realloc(text, text_size);
672 while (text[pos++] = *idp++) ;
678 if (pos == text_size)
679 text = Realloc(text, text_size <<= 1);
684 text = Realloc(text, pos);
689 #define BLANK(ch) ((ch == ' ') || (ch == '\t'))
691 /* macroeq() decides whether two macro replacement texts are
692 identical. This version compares the texts, which occur
693 as strings, without taking care of the leading and trailing
694 blanks (spaces and tabs).
698 register char *s, *t;
701 /* skip leading spaces */
702 while (BLANK(*s)) s++;
703 while (BLANK(*t)) t++;
704 /* first non-blank encountered in both strings */
705 /* The actual comparison loop: */
706 while (*s && *s == *t)
708 /* two cases are possible when arrived here: */
709 if (*s == '\0') { /* *s == '\0' */
710 while (BLANK(*t)) t++;
713 else { /* *s != *t */
714 while (BLANK(*s)) s++;
715 while (BLANK(*t)) t++;
716 return (*s == '\0') && (*t == '\0');