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.36 1998/02/09 09:48:59 ceriel Exp $ */
6 /* PREPROCESSOR: CONTROLLINE INTERPRETER */
19 #include "botch_free.h"
21 #include "parbufsize.h"
37 extern char options[];
38 extern char **inctable; /* list of include directories */
39 extern char *getwdir();
40 char ifstack[IFDEPTH]; /* if-stack: the content of an entry is */
41 /* 1 if a corresponding ELSE has been */
47 GetIdentifier(skiponerr)
48 int skiponerr; /* skip the rest of the line on error */
50 /* returns a pointer to the descriptor of the identifier that is
51 read from the input stream. When the input doe not contain
52 an identifier, the rest of the line is skipped when
53 skiponerr is on, and a null-pointer is returned.
54 The substitution of macros is disabled.
56 int tmp = UnknownIdIsZero;
60 UnknownIdIsZero = ReplaceMacros = 0;
63 UnknownIdIsZero = tmp;
64 if (tok != IDENTIFIER) {
65 if (skiponerr && tok != EOI) SkipToNewLine();
66 return (struct idf *)0;
71 /* domacro() is the control line interpreter. The '#' has already
72 been read by the lexical analyzer by which domacro() is called.
73 The token appearing directly after the '#' is obtained by calling
74 the basic lexical analyzing function GetToken() and is interpreted
75 to perform the action belonging to that token.
76 An error message is produced when the token is not recognized,
77 i.e. it is not one of "define" .. "undef" , integer or newline.
81 struct token tk; /* the token itself */
86 toknum = GetToken(&tk);
88 switch(toknum) { /* select control line action */
89 case IDENTIFIER: /* is it a macro keyword? */
90 switch (tk.tk_idf->id_resmac) {
91 case K_DEFINE: /* "define" */
94 case K_ELIF: /* "elif" */
97 case K_ELSE: /* "else" */
100 case K_ENDIF: /* "endif" */
103 case K_IF: /* "if" */
106 case K_IFDEF: /* "ifdef" */
109 case K_IFNDEF: /* "ifndef" */
112 case K_INCLUDE: /* "include" */
115 case K_LINE: /* "line" */
116 /* set LineNumber and FileName according to
119 if (GetToken(&tk) != INTEGER) {
120 lexerror("bad #line syntax");
124 do_line((unsigned int)tk.tk_ival);
126 case K_ERROR: /* "error" */
129 case K_PRAGMA: /* "pragma" */
132 case K_UNDEF: /* "undef" */
133 do_undef((struct idf *) 0);
136 /* invalid word seen after the '#' */
137 lexerror("%s: unknown control", tk.tk_idf->id_text);
141 case INTEGER: /* # <integer> [<filespecifier>]? */
142 do_line((unsigned int)tk.tk_ival);
144 case EOI: /* only `#' on this line: do nothing, ignore */
146 default: /* invalid token following '#' */
147 lexerror("illegal # line");
154 int lint_skip_comment;
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 */
178 ch = GetChar(); /* read first character after newline */
179 while (class(ch) == STSKIP)
189 /* A possible '/' is not pushed back */
192 if (ch != '*') UnGetChar();
202 toknum = GetToken(&tk);
204 if (toknum != IDENTIFIER) {
205 if (toknum != INTEGER) {
206 lexerror("illegal # line");
211 /* an IDENTIFIER: look for #if, #ifdef and #ifndef
212 without interpreting them.
213 Interpret #else, #elif and #endif if they occur
216 switch(tk.tk_idf->id_resmac) {
219 /* invalid word seen after the '#' */
220 lexwarning("%s: unknown control", tk.tk_idf->id_text);
238 if (ifstack[nestlevel])
239 lexerror("#elif after #else");
240 if (!to_endif && nestlevel == skiplevel) {
251 else SkipToNewLine(); /* otherwise done in ifexpr() */
254 if (ifstack[nestlevel])
255 lexerror("#else after #else");
256 ++(ifstack[nestlevel]);
257 if (!to_endif && nestlevel == skiplevel) {
258 if (SkipToNewLine()) {
260 lexstrict("garbage following #else");
268 else SkipToNewLine();
271 ASSERT(nestlevel > nestlow);
272 if (nestlevel == skiplevel) {
273 if (SkipToNewLine()) {
275 lexstrict("garbage following #endif");
284 else SkipToNewLine();
294 /* ifexpr() returns whether the restricted constant
295 expression following #if or #elif evaluates to true. This
296 is done by calling the LLgen generated subparser for
297 constant expressions. The result of this expression will
298 be given in the extern long variable "ifval".
301 int errors = err_occurred;
306 PushLex(); /* NEW parser */
307 If_expr(); /* invoke constant expression parser */
308 PopLex(); /* OLD parser */
311 return (errors == err_occurred) && (ifval != (arith)0);
316 /* do_include() performs the inclusion of a file.
323 AccFileSpecifier = 1;
324 if (((tok = GetToken(&tk)) == FILESPECIFIER) || tok == STRING)
327 lexerror("bad include syntax");
330 AccFileSpecifier = 0;
331 if (SkipToNewLine()) {
332 lexerror("bad include syntax");
334 inctable[0] = WorkingDir;
336 if (!InsertFile(filenm, &inctable[tok==FILESPECIFIER],&result)){
337 lexerror("cannot open include file \"%s\"", filenm);
338 add_dependency(filenm);
342 add_dependency(result);
343 WorkingDir = getwdir(result);
351 C_ms_stb_cst(FileName, N_BINCL, 0, (arith) 0);
353 #endif /* DBSYMTAB */
354 if (result != filenm) free(filenm);
361 /* do_define() interprets a #define control line.
363 struct idf *id; /* the #defined identifier's descriptor */
364 int nformals = -1; /* keep track of the number of formals */
365 char *formals[NPARAMS]; /* pointers to the names of the formals */
366 char parbuf[PARBUFSIZE]; /* names of formals */
367 char *repl_text; /* start of the replacement text */
368 int length; /* length of the replacement text */
372 /* read the #defined macro's name */
373 if (!(id = GetIdentifier(1))) {
374 lexerror("illegal #define line");
377 /* there is a formal parameter list if the identifier is
378 followed immediately by a '('.
382 if ((nformals = getparams(formals, parbuf)) == -1) {
384 return; /* an error occurred */
388 /* read the replacement text if there is any */
389 ch = skipspaces(ch,0); /* find first character of the text */
391 /* UnGetChar() is not right when replacement starts with a '/' */
393 repl_text = get_text((nformals > 0) ? formals : 0, &length);
394 macro_def(id, repl_text, nformals, length, NOFLAG);
400 if (nestlevel >= IFDEPTH)
401 fatal("too many nested #if/#ifdef/#ifndef");
403 ifstack[++nestlevel] = 0;
408 if (nestlevel <= nestlow) {
409 lexerror("#elif without corresponding #if");
412 else { /* restart at this level as if a #if is detected. */
413 if (ifstack[nestlevel]) {
414 lexerror("#elif after #else");
427 lexstrict("garbage following #else");
428 if (nestlevel <= nestlow)
429 lexerror("#else without corresponding #if");
430 else { /* mark this level as else-d */
431 if (ifstack[nestlevel]) {
432 lexerror("#else after #else");
434 ++(ifstack[nestlevel]);
441 if (SkipToNewLine()) {
443 lexstrict("garbage following #endif");
445 if (nestlevel <= nestlow) {
446 lexerror("#endif without corresponding #if");
454 if (!ifexpr()) /* a false #if/#elif expression */
460 register struct idf *id;
462 /* how == 1 : ifdef; how == 0 : ifndef
465 if (!(id = GetIdentifier(1)))
466 lexerror("illegal #ifdef construction");
467 else if (SkipToNewLine())
469 lexstrict("garbage following #%s <identifier>",
470 how ? "ifdef" : "ifndef");
472 /* The next test is a shorthand for:
473 (how && !id->id_macro) || (!how && id->id_macro)
475 if (how ^ (id && id->id_macro != 0))
479 /* argidf != NULL when the undef came from a -U option */
483 register struct idf *id = argidf;
485 /* Forget a macro definition. */
486 if (id || (id = GetIdentifier(1))) {
487 if (id->id_macro) { /* forget the macro */
488 if (id->id_macro->mc_flag & NOUNDEF) {
489 lexerror("it is not allowed to undef %s", id->id_text);
491 free(id->id_macro->mc_text);
492 free_macro(id->id_macro);
493 id->id_macro = (struct macro *) 0;
495 } /* else: don't complain */
499 lexstrict("garbage following #undef");
503 lexerror("illegal #undef construction");
510 char *bp = get_text((char **) 0, &len);
512 lexerror("user error: %s", bp);
518 getparams(buf, parbuf)
522 /* getparams() reads the formal parameter list of a macro
524 The number of parameters is returned.
525 As a formal parameter list is expected when calling this
526 routine, -1 is returned if an error is detected, for
528 #define one(1), where 1 is not an identifier.
529 Note that the '(' has already been eaten.
530 The names of the formal parameters are stored into parbuf.
532 register char **pbuf = &buf[0];
534 register char *ptr = &parbuf[0];
535 register char **pbuf2;
539 if (c == ')') { /* no parameters: #define name() */
543 for (;;) { /* eat the formal parameter list */
544 if (class(c) != STIDF && class(c) != STELL) {
545 lexerror("#define: bad formal parameter");
548 *pbuf = ptr; /* name of the formal */
550 if (ptr >= &parbuf[PARBUFSIZE])
551 fatal("formal parameter buffer overflow");
552 do { /* eat the identifier name */
555 if (ptr >= &parbuf[PARBUFSIZE])
556 fatal("formal parameter buffer overflow");
558 *(ptr - 1) = '\0'; /* mark end of the name */
560 /* Check if this formal parameter is already used.
561 Usually, macros do not have many parameters, so ...
563 for (pbuf2 = pbuf - 1; pbuf2 >= &buf[0]; pbuf2--) {
564 if (!strcmp(*pbuf2, *pbuf)) {
565 lexerror("formal parameter \"%s\" already used",
572 if (c == ')') { /* end of the formal parameter list */
577 lexerror("#define: bad formal parameter list");
586 macro_def(id, text, nformals, length, flags)
587 register struct idf *id;
590 register struct macro *newdef = id->id_macro;
592 /* macro_def() puts the contents and information of a macro
593 definition into a structure and stores it into the symbol
594 table entry belonging to the name of the macro.
595 An error is given if there was already a definition
597 if (newdef) { /* is there a redefinition? */
598 if (newdef->mc_flag & NOUNDEF) {
599 lexerror("it is not allowed to redefine %s", id->id_text);
600 } else if (!macroeq(newdef->mc_text, text))
601 lexerror("illegal redefine of \"%s\"", id->id_text);
605 id->id_macro = newdef = new_macro();
606 newdef->mc_text = text; /* replacement text */
607 newdef->mc_nps = nformals; /* nr of formals */
608 newdef->mc_length = length; /* length of repl. text */
609 newdef->mc_flag = flags; /* special flags */
616 /* find_name() returns the index of "nm" in the namelist
617 "index" if it can be found there. 0 is returned if it is
620 register char **ip = &index[0];
623 if (strcmp(nm, *ip++) == 0)
624 return ip - &index[0];
625 /* arrived here, nm is not in the name list. */
629 #define BLANK(ch) ((ch == ' ') || (ch == '\t'))
632 get_text(formals, length)
636 /* get_text() copies the replacement text of a macro
637 definition with zero, one or more parameters, thereby
638 substituting each formal parameter by a special character
639 (non-ascii: 0200 & (order-number in the formal parameter
640 list)) in order to substitute this character later by the
641 actual parameter. The replacement text is copied into
642 itself because the copied text will contain fewer or the
643 same amount of characters. The length of the replacement
647 finite automaton : we are interested in
648 1- white space, sequences must be mapped onto 1 single
650 2- identifiers, since they might be replaced by some
652 3- strings and character constants, since replacing
653 variables within them is illegal, and white-space is
655 4- comment, same as for 1
656 Other tokens will not be seen as such.
660 register struct repl *repl = &repls;
665 repl->r_ptr = repl->r_text = Malloc(repl->r_size = ITEXTSIZE);
667 while ((c != EOI) && (class(c) != STNL)) {
674 if (c == '\'' || c == '"') {
675 register int delim = c;
683 if (c == '\\') add2repl(repl, GetChar());
685 } while (c != delim && c != EOI && class(c) != STNL);
686 if (c == EOI || class(c) == STNL) {
687 lexstrict("unclosed opening %c", delim);
692 } else if (c == '/') {
706 && (class(c) == STIDF || class(c) == STELL)) {
707 char id_buf[IDFSIZE + 1];
708 register char *idp = id_buf;
711 /* read identifier: it may be a formal parameter */
715 if (idp <= &id_buf[IDFSIZE])
724 /* construct the formal parameter mark or identifier */
725 if (n = find_name(id_buf, formals))
726 add2repl(repl, FORMALP | (char) n);
729 while (*idp) add2repl(repl, *idp++);
731 } else if (class(c) == STNUM) {
739 if (class(c) != STNUM) {
745 while(in_idf(c) || c == '.') {
747 if((c = GetChar()) == 'e' || c == 'E') {
750 if (c == '+' || c == '-') {
765 *length = repl->r_ptr - repl->r_text;
766 return Realloc(repl->r_text, (unsigned)(repl->r_ptr - repl->r_text +1));
769 /* macroeq() decides whether two macro replacement texts are
770 identical. This version compares the texts, which occur
771 as strings, without taking care of the leading and trailing
772 blanks (spaces and tabs).
775 register char *s, *t;
778 /* skip leading spaces */
779 while (BLANK(*s)) s++;
780 while (BLANK(*t)) t++;
781 /* first non-blank encountered in both strings */
782 /* The actual comparison loop: */
783 while (*s && *s == *t)
785 /* two cases are possible when arrived here: */
786 if (*s == '\0') { /* *s == '\0' */
787 while (BLANK(*t)) t++;
790 else { /* *s != *t */
791 while (BLANK(*s)) s++;
792 while (BLANK(*t)) t++;
793 return (*s == '\0') && (*t == '\0');
799 GetIdentifier(skiponerr)
800 int skiponerr; /* skip the rest of the line on error */
802 /* returns a pointer to the descriptor of the identifier that is
803 read from the input stream. When the input does not contain
804 an identifier, the rest of the line is skipped when
805 skiponerr is on, and a null-pointer is returned.
806 The substitution of macros is disabled.
812 if (tok != IDENTIFIER) {
813 if (skiponerr && tok != EOI) SkipToNewLine();
814 return (struct idf *)0;
825 if ((tok = GetToken(&tk)) == IDENTIFIER) {
826 if (! strcmp(tk.tk_idf->id_text, "pragma")) {
831 } else if (tok == INTEGER) {
832 do_line((unsigned int) tk.tk_ival);
836 lexerror("illegal # line");
847 int t = GetToken(&tk);
849 if (t != EOI) SkipToNewLine();
850 LineNumber = l; /* the number of the next input line */
851 if (t == STRING) { /* is there a filespecifier? */
853 * Do not attempt to free the old string, since it might
854 * be used in a def structure.
857 if (options['g'] && strcmp(FileName, tk.tk_bts) != 0) {
858 C_ms_std(tk.tk_bts, N_SOL, 0);
860 #endif /* DBSYMTAB */
861 FileName = tk.tk_bts;