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 3.34 1994/06/24 12:03:19 ceriel Exp $ */
6 /* PREPROCESSOR: CONTROLLINE INTERPRETER */
20 #include "botch_free.h"
22 #include "parbufsize.h"
34 extern char options[];
37 IMPORT char **inctable; /* list of include directories */
38 IMPORT char *getwdir();
39 PRIVATE char ifstack[IFDEPTH]; /* if-stack: the content of an entry is */
40 /* 1 if a corresponding ELSE has been */
55 PRIVATE int getparams();
56 PRIVATE char *get_text();
57 PRIVATE int macroeq();
58 PRIVATE SkipRestOfLine();
64 /* returns a pointer to the descriptor of the identifier that is
65 read from the input stream. A null-pointer is returned if
66 the input does not contain an identifier.
67 The substitution of macros is disabled.
75 return tok == IDENTIFIER ? tk.tk_idf : (struct idf *)0;
78 /* domacro() is the control line interpreter. The '#' has already
79 been read by the lexical analyzer by which domacro() is called.
80 The token appearing directly after the '#' is obtained by calling
81 the basic lexical analyzing function GetToken() and is interpreted
82 to perform the action belonging to that token.
83 An error message is produced when the token is not recognized,
84 i.e. it is not one of "define" .. "undef" , integer or newline.
89 struct token tk; /* the token itself */
93 switch(GetToken(&tk)) { /* select control line action */
94 case IDENTIFIER: /* is it a macro keyword? */
95 switch (tk.tk_idf->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 lexerror("#line without linenumber");
129 do_line((unsigned int)tk.tk_ival);
131 case K_UNDEF: /* "undef" */
134 case K_PRAGMA: /* "pragma" */
140 /* invalid word seen after the '#' */
141 lexerror("%s: unknown control", tk.tk_idf->id_text);
145 case INTEGER: /* # <integer> [<filespecifier>]? */
146 do_line((unsigned int)tk.tk_ival);
148 case EOI: /* only `#' on this line: do nothing, ignore */
150 default: /* invalid token following '#' */
151 lexerror("illegal # line");
159 int lint_skip_comment;
165 /* skip_block() skips the input from
166 1) a false #if, #ifdef, #ifndef or #elif until the
167 corresponding #elif (resulting in true), #else or
169 2) a #else corresponding to a true #if, #ifdef,
170 #ifndef or #elif until the corresponding #endif is
174 register int skiplevel = nestlevel; /* current nesting level */
182 LoadChar(ch); /* read first character after newline */
194 if (GetToken(&tk) != IDENTIFIER) {
198 /* an IDENTIFIER: look for #if, #ifdef and #ifndef
199 without interpreting them.
200 Interpret #else, #elif and #endif if they occur
203 switch(tk.tk_idf->id_resmac) {
214 if (ifstack[nestlevel])
215 lexwarning("#elif without corresponding #if");
216 if (! to_endif && nestlevel == skiplevel) {
227 else SkipRestOfLine();
230 if (ifstack[nestlevel])
231 lexwarning("#else without corresponding #if");
234 ++(ifstack[nestlevel]);
235 if (nestlevel == skiplevel) {
245 ASSERT(nestlevel > nestlow);
247 if (nestlevel == skiplevel) {
264 /* ifexpr() returns whether the restricted constant
265 expression following #if or #elif evaluates to true. This
266 is done by calling the LLgen generated subparser for
267 constant expressions. The result of this expression will
268 be given in the extern long variable "ifval".
271 int errors = err_occurred;
276 PushLex(); /* NEW parser */
277 If_expr(); /* invoke constant expression parser */
278 PopLex(); /* OLD parser */
281 return (errors == err_occurred) && (ifval != (arith)0);
287 /* do_include() performs the inclusion of a file.
294 AccFileSpecifier = 1;
295 if (((tok = GetToken(&tk)) == FILESPECIFIER) || tok == STRING)
298 lexerror("bad include syntax");
301 AccFileSpecifier = 0;
303 inctable[0] = WorkingDir;
305 if (!InsertFile(filenm, &inctable[tok==FILESPECIFIER],&result)){
306 fatal("cannot open include file \"%s\"", filenm);
309 add_dependency(result);
310 WorkingDir = getwdir(result);
318 C_ms_stb_cst(FileName, N_BINCL, 0, (arith) 0);
320 #endif /* DBSYMTAB */
328 /* do_define() interprets a #define control line.
330 struct idf *id; /* the #defined identifier's descriptor */
331 int nformals = -1; /* keep track of the number of formals */
332 char *formals[NPARAMS]; /* pointers to the names of the formals */
333 char parbuf[PARBUFSIZE]; /* names of formals */
334 char *repl_text; /* start of the replacement text */
335 int length; /* length of the replacement text */
338 /* read the #defined macro's name */
339 if (!(id = GetIdentifier())) {
340 lexerror("#define: illegal macro name");
344 /* there is a formal parameter list if the identifier is
345 followed immediately by a '('.
349 if ((nformals = getparams(formals, parbuf)) == -1) {
351 return; /* an error occurred */
355 /* read the replacement text if there is any */
356 ch = skipspaces(ch,0); /* find first character of the text */
358 if (class(ch) == STNL) {
359 /* Treat `#define something' as `#define something ""'
366 repl_text = get_text((nformals > 0) ? formals : 0, &length);
368 macro_def(id, repl_text, nformals, length, NOFLAG);
375 if (nestlevel >= IFDEPTH)
376 fatal("too many nested #if/#ifdef/#ifndef");
378 ifstack[++nestlevel] = 0;
384 if (nestlevel <= nestlow || (ifstack[nestlevel])) {
385 lexerror("#elif without corresponding #if");
388 else { /* restart at this level as if a #if is detected. */
399 if (nestlevel <= nestlow || (ifstack[nestlevel]))
400 lexerror("#else without corresponding #if");
401 else { /* mark this level as else-d */
402 ++(ifstack[nestlevel]);
411 if (nestlevel <= nestlow) {
412 lexerror("#endif without corresponding #if");
421 if (!ifexpr()) /* a false #if/#elif expression */
428 register struct idf *id;
430 /* how == 1 : ifdef; how == 0 : ifndef
433 if (!(id = GetIdentifier()))
434 lexerror("illegal #ifdef construction");
436 /* The next test is a shorthand for:
437 (how && !id->id_macro) || (!how && id->id_macro)
439 if (how ^ (id && id->id_macro != 0))
448 register struct idf *id;
450 /* Forget a macro definition. */
451 if (id = GetIdentifier()) {
452 if (id->id_macro) { /* forget the macro */
453 free_macro(id->id_macro);
454 id->id_macro = (struct macro *) 0;
455 } /* else: don't complain */
458 lexerror("illegal #undef construction");
463 getparams(buf, parbuf)
467 /* getparams() reads the formal parameter list of a macro
469 The number of parameters is returned.
470 As a formal parameter list is expected when calling this
471 routine, -1 is returned if an error is detected, for
473 #define one(1), where 1 is not an identifier.
474 Note that the '(' has already been eaten.
475 The names of the formal parameters are stored into parbuf.
477 register char **pbuf = &buf[0];
479 register char *ptr = &parbuf[0];
480 register char **pbuf2;
484 if (c == ')') { /* no parameters: #define name() */
488 for (;;) { /* eat the formal parameter list */
489 if (class(c) != STIDF) { /* not an identifier */
490 lexerror("#define: bad formal parameter");
493 *pbuf = ptr; /* name of the formal */
495 if (ptr >= &parbuf[PARBUFSIZE])
496 fatal("formal parameter buffer overflow");
497 do { /* eat the identifier name */
500 if (ptr >= &parbuf[PARBUFSIZE])
501 fatal("formal parameter buffer overflow");
503 *(ptr - 1) = '\0'; /* mark end of the name */
505 /* Check if this formal parameter is already used.
506 Usually, macros do not have many parameters, so ...
508 for (pbuf2 = pbuf - 1; pbuf2 >= &buf[0]; pbuf2--) {
509 if (!strcmp(*pbuf2, *pbuf)) {
510 warning("formal parameter \"%s\" already used",
517 if (c == ')') { /* end of the formal parameter list */
522 lexerror("#define: bad formal parameter list");
532 macro_def(id, text, nformals, length, flags)
533 register struct idf *id;
536 register struct macro *newdef = id->id_macro;
538 /* macro_def() puts the contents and information of a macro
539 definition into a structure and stores it into the symbol
540 table entry belonging to the name of the macro.
541 A warning is given if the definition overwrites another.
543 if (newdef) { /* is there a redefinition? */
544 if (macroeq(newdef->mc_text, text))
546 lexwarning("redefine \"%s\"", id->id_text);
549 id->id_macro = newdef = new_macro();
550 newdef->mc_text = text; /* replacement text */
551 newdef->mc_nps = nformals; /* nr of formals */
552 newdef->mc_length = length; /* length of repl. text */
553 newdef->mc_flag = flags; /* special flags */
554 newdef->mc_count = 0;
561 /* find_name() returns the index of "nm" in the namelist
562 "index" if it can be found there. 0 is returned if it is
565 register char **ip = &index[0];
568 if (strcmp(nm, *ip++) == 0)
569 return ip - &index[0];
570 /* arrived here, nm is not in the name list. */
575 get_text(formals, length)
579 /* get_text() copies the replacement text of a macro
580 definition with zero, one or more parameters, thereby
581 substituting each formal parameter by a special character
582 (non-ascii: 0200 & (order-number in the formal parameter
583 list)) in order to substitute this character later by the
584 actual parameter. The replacement text is copied into
585 itself because the copied text will contain fewer or the
586 same amount of characters. The length of the replacement
590 finite automaton : we are only interested in
591 identifiers, because they might be replaced by some actual
592 parameter. Other tokens will not be seen as such.
595 register int text_size;
596 char *text = Malloc(text_size = ITEXTSIZE);
597 register int pos = 0;
601 while ((c != EOI) && (class(c) != STNL)) {
602 if (c == '\\') { /* check for "\\\n" */
605 /* More than one line is used for the
607 Replace "\\\n" by " ".
615 if (pos == text_size)
616 text = Srealloc(text, text_size += RTEXTSIZE);
623 /* text[pos++] = ' '; ??? Why ??? */
628 if (pos == text_size)
629 text = Srealloc(text, text_size += RTEXTSIZE);
632 if (formals && class(c) == STIDF) {
633 char id_buf[IDFSIZE + 1];
634 register id_size = 0;
637 /* read identifier: it may be a formal parameter */
638 id_buf[id_size++] = c;
641 if (id_size <= IDFSIZE)
642 id_buf[id_size++] = c;
644 id_buf[--id_size] = '\0';
645 if (n = find_name(id_buf, formals)) {
646 /* construct the formal parameter mark */
647 text[pos++] = FORMALP | (char) n;
648 if (pos == text_size)
649 text = Srealloc(text,
650 text_size += RTEXTSIZE);
653 register char *ptr = &id_buf[0];
655 while (pos + id_size >= text_size)
656 text = Srealloc(text,
657 text_size += RTEXTSIZE);
658 while (text[pos++] = *ptr++) ;
664 if (pos == text_size)
665 text = Srealloc(text, text_size += RTEXTSIZE);
674 #define BLANK(ch) ((ch == ' ') || (ch == '\t'))
676 /* macroeq() decides whether two macro replacement texts are
677 identical. This version compares the texts, which occur
678 as strings, without taking care of the leading and trailing
679 blanks (spaces and tabs).
683 register char *s, *t;
686 /* skip leading spaces */
687 while (BLANK(*s)) s++;
688 while (BLANK(*t)) t++;
689 /* first non-blank encountered in both strings */
690 /* The actual comparison loop: */
691 while (*s && *s == *t)
693 /* two cases are possible when arrived here: */
694 if (*s == '\0') { /* *s == '\0' */
695 while (BLANK(*t)) t++;
698 else { /* *s != *t */
699 while (BLANK(*s)) s++;
700 while (BLANK(*t)) t++;
701 return (*s == '\0') && (*t == '\0');
713 if ((tok = GetToken(&tk)) == IDENTIFIER) {
714 if (strcmp(tk.tk_idf->id_text, "line") != 0) {
715 error("illegal # line");
721 if (tok != INTEGER) {
722 error("illegal # line");
726 do_line((unsigned int) tk.tk_ival);
735 /* we do a PushBack because we don't want to skip the next line
736 if the last character was a newline
747 int t = GetToken(&tk);
750 LineNumber = l; /* the number of the next input line */
751 if (t == STRING) { /* is there a filespecifier? */
753 if (options['g'] && strcmp(FileName, tk.tk_bts) != 0) {
754 C_ms_std(tk.tk_bts, N_SOL, 0);
756 #endif /* DBSYMTAB */
757 FileName = tk.tk_bts;