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.23 1998/02/09 09:48:26 ceriel Exp $ */
6 /* PREPROCESSOR: CONTROLLINE INTERPRETER */
15 #include "botch_free.h"
17 #include "parbufsize.h"
29 extern char options[];
30 extern char **inctable; /* list of include directories */
31 extern char *getwdir();
32 char ifstack[IFDEPTH]; /* if-stack: the content of an entry is */
33 /* 1 if a corresponding ELSE has been */
37 int svnestlevel[30] = {-1};
39 extern int do_preprocess;
42 GetIdentifier(skiponerr)
43 int skiponerr; /* skip the rest of the line on error */
45 /* Returns a pointer to the identifier that is read from the
46 input stream. When the input does not contain an
47 identifier, the rest of the line is skipped when skiponerr
48 is on, and a null-pointer is returned.
49 The substitution of macros is disabled.
50 Remember that on end-of-line EOF is returned.
52 int tmp = UnknownIdIsZero;
56 UnknownIdIsZero = ReplaceMacros = 0;
59 UnknownIdIsZero = tmp;
60 if (tok != IDENTIFIER) {
61 if (skiponerr && tok != EOF) SkipToNewLine();
67 /* domacro() is the control line interpreter. The '#' has already
68 been read by the lexical analyzer by which domacro() is called.
69 The token appearing directly after the '#' is obtained by calling
70 the basic lexical analyzing function GetToken() and is interpreted
71 to perform the action belonging to that token.
72 An error message is produced when the token is not recognized.
73 Pragma's are handled by do_pragma(). They are passed on to the
78 struct token tk; /* the token itself */
79 register struct idf *id;
83 toknum = GetToken(&tk);
85 switch(toknum) { /* select control line action */
86 case IDENTIFIER: /* is it a macro keyword? */
87 id = findidf(tk.tk_str);
89 error("%s: unknown control", tk.tk_str);
95 switch (id->id_resmac) {
96 case K_DEFINE: /* "define" */
99 case K_ELIF: /* "elif" */
102 case K_ELSE: /* "else" */
105 case K_ENDIF: /* "endif" */
108 case K_IF: /* "if" */
111 case K_IFDEF: /* "ifdef" */
114 case K_IFNDEF: /* "ifndef" */
117 case K_INCLUDE: /* "include" */
120 case K_LINE: /* "line" */
121 /* set LineNumber and FileName according to
124 if (GetToken(&tk) != INTEGER) {
125 error("bad #line syntax");
129 do_line((unsigned int)tk.tk_val);
131 case K_ERROR: /* "error" */
134 case K_PRAGMA: /* "pragma" */
137 case K_UNDEF: /* "undef" */
141 /* invalid word seen after the '#' */
142 error("%s: unknown control", id->id_text);
146 case INTEGER: /* # <integer> [<filespecifier>]? */
147 do_line((unsigned int)tk.tk_val);
149 case EOF: /* only `#' on this line: do nothing, ignore */
151 default: /* invalid token following '#' */
152 error("illegal # line");
160 /* skip_block() skips the input from
161 1) a false #if, #ifdef, #ifndef or #elif until the
162 corresponding #elif (resulting in true), #else or
164 2) a #else corresponding to a true #if, #ifdef,
165 #ifndef or #elif until the corresponding #endif is
169 register int skiplevel = nestlevel; /* current nesting level */
176 ch = GetChar(); /* read first character after newline */
177 while (class(ch) == STSKIP)
185 if (ch != '*') UnGetChar();
195 toknum = GetToken(&tk);
197 if (toknum != IDENTIFIER) {
198 if (toknum != INTEGER) {
199 error("illegal # line");
204 /* an IDENTIFIER: look for #if, #ifdef and #ifndef
205 without interpreting them.
206 Interpret #else, #elif and #endif if they occur
209 id = findidf(tk.tk_str);
210 if (id == (struct idf *)0) {
211 /* invalid word seen after the '#' */
212 warning("%s: unknown control", tk.tk_str);
215 if (id == (struct idf *)0) continue;
216 switch(id->id_resmac) {
233 if (ifstack[nestlevel])
234 error("#elif after #else");
235 if (!to_endif && nestlevel == skiplevel) {
243 else SkipToNewLine(); /* otherwise done in ifexpr() */
246 if (ifstack[nestlevel])
247 error("#else after #else");
248 ++(ifstack[nestlevel]);
249 if (!to_endif && nestlevel == skiplevel) {
250 if (SkipToNewLine()) {
252 strict("garbage following #else");
257 else SkipToNewLine();
260 assert(nestlevel > svnestlevel[nestcount]);
261 if (nestlevel == skiplevel) {
262 if (SkipToNewLine()) {
264 strict("garbage following #endif");
270 else SkipToNewLine();
280 /* ifexpr() returns whether the restricted constant
281 expression following #if or #elif evaluates to true. This
282 is done by calling the LLgen generated subparser for
283 constant expressions. The result of this expression will
284 be given in the extern long variable "ifval".
287 int errors = err_occurred;
292 DOT = 0; /* tricky */
293 If_expr(); /* invoke constant expression parser */
296 return (errors == err_occurred) && (ifval != (arith)0);
301 /* do_include() performs the inclusion of a file.
308 AccFileSpecifier = 1;
309 if (((tok = GetToken(&tk)) == FILESPECIFIER) || tok == STRING)
312 error("bad include syntax");
315 AccFileSpecifier = 0;
316 if (SkipToNewLine()) {
317 error("bad include syntax");
319 inctable[0] = WorkingDir;
321 if (!InsertFile(filenm, &inctable[tok==FILESPECIFIER],&result)){
322 if (do_preprocess) error("cannot open include file \"%s\"", filenm);
323 else warning("cannot open include file \"%s\"", filenm);
324 add_dependency(filenm);
327 add_dependency(result);
328 WorkingDir = getwdir(result);
329 svnestlevel[++nestcount] = nestlevel;
338 /* do_define() interprets a #define control line.
340 register char *str; /* the #defined identifier's descriptor */
341 int nformals = -1; /* keep track of the number of formals */
342 char *formals[NPARAMS]; /* pointers to the names of the formals */
343 char parbuf[PARBUFSIZE]; /* names of formals */
344 char *repl_text; /* start of the replacement text */
345 int length; /* length of the replacement text */
349 /* read the #defined macro's name */
350 if (!(str = GetIdentifier(1))) {
351 error("#define: illegal macro name");
354 /* there is a formal parameter list if the identifier is
355 followed immediately by a '('.
359 if ((nformals = getparams(formals, parbuf)) == -1) {
362 return; /* an error occurred */
366 /* read the replacement text if there is any */
367 ch = skipspaces(ch,0); /* find first character of the text */
369 /* UnGetChar() is not right when replacement starts with a '/' */
371 repl_text = get_text((nformals > 0) ? formals : 0, &length);
372 macro_def(str2idf(str, 0), repl_text, nformals, length, NOFLAG);
378 if (nestlevel >= IFDEPTH)
379 fatal("too many nested #if/#ifdef/#ifndef");
381 ifstack[++nestlevel] = 0;
386 if (nestlevel <= svnestlevel[nestcount]) {
387 error("#elif without corresponding #if");
390 else { /* restart at this level as if a #if is detected. */
391 if (ifstack[nestlevel]) {
392 error("#elif after #else");
403 if (SkipToNewLine()) {
405 strict("garbage following #else");
407 if (nestlevel <= svnestlevel[nestcount])
408 error("#else without corresponding #if");
409 else { /* mark this level as else-d */
410 if (ifstack[nestlevel]) {
411 error("#else after #else");
413 ++(ifstack[nestlevel]);
420 if (SkipToNewLine()) {
422 strict("garbage following #endif");
424 if (nestlevel <= svnestlevel[nestcount]) {
425 error("#endif without corresponding #if");
433 if (!ifexpr()) /* a false #if/#elif expression */
439 register struct idf *id;
442 /* how == 1 : ifdef; how == 0 : ifndef
445 if (!(str = GetIdentifier(1))) {
446 error("illegal #ifdef construction");
447 id = (struct idf *)0;
452 if (SkipToNewLine()) {
453 if (str && !options['o'])
454 strict("garbage following #%s <identifier>",
455 how ? "ifdef" : "ifndef");
458 /* The next test is a shorthand for:
459 (how && !id->id_macro) || (!how && id->id_macro)
461 if (how ^ (id && id->id_macro != 0))
465 /* argstr != NULL when the undef came from a -U option */
469 register struct idf *id;
470 register char *str = argstr;
472 /* Forget a macro definition. */
473 if (str || (str = GetIdentifier(1))) {
474 if ((id = findidf(str)) && id->id_macro) {
475 if (id->id_macro->mc_flag & NOUNDEF) {
476 error("it is not allowed to #undef %s", str);
478 free(id->id_macro->mc_text);
479 free_macro(id->id_macro);
480 id->id_macro = (struct macro *) 0;
482 } /* else: don't complain */
485 if (SkipToNewLine()) {
487 strict("garbage following #undef");
492 error("illegal #undef construction");
499 char *bp = get_text((char **) 0, &len);
501 error("user error: %s", bp);
507 getparams(buf, parbuf)
511 /* getparams() reads the formal parameter list of a macro
513 The number of parameters is returned.
514 As a formal parameter list is expected when calling this
515 routine, -1 is returned if an error is detected, for
517 #define one(1), where 1 is not an identifier.
518 Note that the '(' has already been eaten.
519 The names of the formal parameters are stored into parbuf.
521 register char **pbuf = &buf[0];
523 register char *ptr = &parbuf[0];
524 register char **pbuf2;
528 if (c == ')') { /* no parameters: #define name() */
532 for (;;) { /* eat the formal parameter list */
533 if (class(c) != STIDF && class(c) != STELL) {
534 error("#define: bad formal parameter");
537 *pbuf = ptr; /* name of the formal */
539 if (ptr >= &parbuf[PARBUFSIZE])
540 fatal("formal parameter buffer overflow");
541 do { /* eat the identifier name */
544 if (ptr >= &parbuf[PARBUFSIZE])
545 fatal("formal parameter buffer overflow");
547 *(ptr - 1) = '\0'; /* mark end of the name */
549 /* Check if this formal parameter is already used.
550 Usually, macros do not have many parameters, so ...
552 for (pbuf2 = pbuf - 1; pbuf2 >= &buf[0]; pbuf2--) {
553 if (!strcmp(*pbuf2, *pbuf)) {
554 warning("formal parameter \"%s\" already used",
561 if (c == ')') { /* end of the formal parameter list */
566 error("#define: bad formal parameter list");
575 macro_def(id, text, nformals, length, flags)
576 register struct idf *id;
579 register struct macro *newdef = id->id_macro;
581 /* macro_def() puts the contents and information of a macro
582 definition into a structure and stores it into the symbol
583 table entry belonging to the name of the macro.
584 An error is given if there was already a definition
586 if (newdef) { /* is there a redefinition? */
587 if (newdef->mc_flag & NOUNDEF) {
588 error("it is not allowed to redefine %s", id->id_text);
589 } else if (!macroeq(newdef->mc_text, text))
590 error("illegal redefine of \"%s\"", id->id_text);
595 register char *p = id->id_text;
596 #define setbit(bx) if (!*p) goto go_on; bits[*p++] |= (bx)
608 id->id_macro = newdef = new_macro();
610 newdef->mc_text = text; /* replacement text */
611 newdef->mc_nps = nformals; /* nr of formals */
612 newdef->mc_length = length; /* length of repl. text */
613 newdef->mc_flag = flags; /* special flags */
620 /* find_name() returns the index of "nm" in the namelist
621 "index" if it can be found there. 0 is returned if it is
624 register char **ip = &index[0];
627 if (strcmp(nm, *ip++) == 0)
628 return ip - &index[0];
629 /* arrived here, nm is not in the name list. */
633 #define BLANK(ch) ((ch == ' ') || (ch == '\t'))
636 get_text(formals, length)
640 /* get_text() copies the replacement text of a macro
641 definition with zero, one or more parameters, thereby
642 substituting each formal parameter by a special character
643 (non-ascii: 0200 & (order-number in the formal parameter
644 list)) in order to substitute this character later by the
645 actual parameter. The replacement text is copied into
646 itself because the copied text will contain fewer or the
647 same amount of characters. The length of the replacement
651 finite automaton : we are interested in
652 1- white space, sequences must be mapped onto 1 single
654 2- identifiers, since they might be replaced by some
656 3- strings and character constants, since replacing
657 variables within them is illegal, and white-space is
659 4- comment, same as for 1
660 Other tokens will not be seen as such.
664 register struct repl *repl = &repls;
669 repl->r_ptr = repl->r_text = Malloc((unsigned)(repl->r_size = ITEXTSIZE));
671 while ((c != EOI) && (class(c) != STNL)) {
678 if (c == '\'' || c == '"') {
679 register int delim = c;
687 if (c == '\\') add2repl(repl, GetChar());
689 } while (c != delim && c != EOI && class(c) != STNL);
691 strict("unclosed opening %c", delim);
696 } else if (c == '/') {
710 && (class(c) == STIDF || class(c) == STELL)) {
711 char id_buf[IDFSIZE + 1];
712 register char *idp = id_buf;
715 /* read identifier: it may be a formal parameter */
719 if (idp <= &id_buf[IDFSIZE])
728 /* construct the formal parameter mark or identifier */
729 if (n = find_name(id_buf, formals))
730 add2repl(repl, FORMALP | (char) n);
733 while (*idp) add2repl(repl, *idp++);
735 } else if (class(c) == STNUM) {
743 if (class(c) != STNUM) {
749 while(in_idf(c) || c == '.') {
751 if((c = GetChar()) == 'e' || c == 'E') {
754 if (c == '+' || c == '-') {
769 *length = repl->r_ptr - repl->r_text;
770 return Realloc(repl->r_text, (unsigned)(repl->r_ptr - repl->r_text +1));
773 /* macroeq() decides whether two macro replacement texts are
774 identical. This version compares the texts, which occur
775 as strings, without taking care of the leading and trailing
776 blanks (spaces and tabs).
779 register char *s, *t;
782 /* skip leading spaces */
783 while (BLANK(*s)) s++;
784 while (BLANK(*t)) t++;
785 /* first non-blank encountered in both strings */
786 /* The actual comparison loop: */
787 while (*s && *s == *t)
789 /* two cases are possible when arrived here: */
790 if (*s == '\0') { /* *s == '\0' */
791 while (BLANK(*t)) t++;
794 else { /* *s != *t */
795 while (BLANK(*s)) s++;
796 while (BLANK(*t)) t++;
797 return (*s == '\0') && (*t == '\0');
805 int t = GetToken(&tk);
807 if (t != EOF) SkipToNewLine();
808 LineNumber = l; /* the number of the next input line */
809 if (t == STRING) /* is there a filespecifier? */
810 FileName = tk.tk_str;