scc

simple c99 compiler
git clone git://git.simple-cc.org/scc
Log | Files | Refs | README | LICENSE

cpp.c (23323B)


      1 #include <assert.h>
      2 #include <ctype.h>
      3 #include <limits.h>
      4 #include <stdio.h>
      5 #include <stdlib.h>
      6 #include <string.h>
      7 #include <time.h>
      8 
      9 #include <scc/cstd.h>
     10 #include <scc/scc.h>
     11 #include "cc1.h"
     12 
     13 struct ifstate {
     14 	unsigned char done;
     15 	unsigned char enabled;
     16 	unsigned char iselse;
     17 };
     18 
     19 static unsigned ncmdlines;
     20 static Symbol *symline, *symfile;
     21 static struct ifstate ifstate[NR_COND];
     22 static int cppoff;
     23 static struct items dirinclude;
     24 
     25 unsigned cppctx;
     26 int disexpand;
     27 
     28 void
     29 defdefine(char *name, char *val, char *source)
     30 {
     31 	char buffer[INPUTSIZ+1];
     32 	char *def, *fmt = "#define %s %s\n";
     33 	Symbol *sym = &(Symbol) {
     34 		.name = name,
     35 		.flags = SDECLARED,
     36 	};
     37 
     38 	if (!val)
     39 		val = "";
     40 	if (strlen(fmt) + strlen(name) + strlen(val) > INPUTSIZ) {
     41 		errorp("macro definition '%s' too big", name);
     42 		return;
     43 	}
     44 
     45 	sprintf(buffer, fmt, name, val);
     46 	lineno = ++ncmdlines;
     47 
     48 	addinput(IPARAM, buffer, FAIL);
     49 	cpp();
     50 	delinput();
     51 }
     52 
     53 void
     54 undefmacro(char *s)
     55 {
     56 	killsym(lookup(NS_CPP, s, NOALLOC));
     57 }
     58 
     59 void
     60 icpp(void)
     61 {
     62 	struct tm *tm;
     63 	time_t t;
     64 	static char sdate[14], stime[11];
     65 	static struct {
     66 		char *name;
     67 		char *value;
     68 	} *bp, list[] = {
     69 		{"__STDC__", "1"},
     70 		{"__STDC_HOSTED__", "1"},
     71 		{"__SCC__", "1"},
     72 		{"__DATE__", sdate},
     73 		{"__TIME__", stime},
     74 		{"__STDC_VERSION__", STDC_VERSION},
     75 		{"__LINE__", NULL},
     76 		{"__FILE__", NULL},
     77 		{"__FLT_EVAL_METHOD__", "0"},
     78 		{NULL, NULL}
     79 	};
     80 
     81 	t = time(NULL);
     82 	tm = localtime(&t);
     83 	strftime(sdate, sizeof(sdate), "\"%b %d %Y\"", tm);
     84 	strftime(stime, sizeof(stime), "\"%H:%M:%S\"", tm);
     85 
     86 	for (bp = list; bp->name; ++bp)
     87 		defdefine(bp->name, bp->value, "built-in");
     88 
     89 	symline = lookup(NS_CPP, "__LINE__", ALLOC);
     90 	symfile = lookup(NS_CPP, "__FILE__", ALLOC);
     91 
     92 	ncmdlines = 0;
     93 }
     94 
     95 static char *
     96 appendpar(Macro *mp, char *s, int len)
     97 {
     98 	char *arg;
     99 	int siz = mp->argsiz;
    100 
    101 	if (len+1 > INT_MAX - siz) {
    102 		error("too long argument invoking macro \"%s\"",
    103 		      mp->sym->name);
    104 	}
    105 
    106 	mp->arg = xrealloc(mp->arg, siz + len + 1);
    107 	memcpy(mp->arg + siz, s, len);
    108 	mp->argsiz = siz += len;
    109 	mp->arg[siz] = '\0';
    110 }
    111 
    112 static void
    113 paren(Macro *mp)
    114 {
    115 	for (;;) {
    116 		switch (*input->p) {
    117 		case ')':
    118 			appendpar(mp, input->p++, 1);
    119 			return;
    120 		case '(':
    121 			appendpar(mp, input->p++, 1);
    122 			paren(mp);
    123 			break;
    124 		case '"':
    125 		case '\'':
    126 			next();
    127 			assert(yytoken == STRING || yytoken == CONSTANT);
    128 			appendpar(mp, yytext, yylen);
    129 			break;
    130 		case '\0':
    131 			if (!moreinput())
    132 				goto unterminated;
    133 			continue;
    134 		default:
    135 			appendpar(mp, input->p++, 1);
    136 			break;
    137 		}
    138 	}
    139 
    140 unterminated:
    141 	error("unterminated argument list invoking macro \"%s\"",
    142 	      mp->sym->name);
    143 }
    144 
    145 static int
    146 cppspace(int c)
    147 {
    148 	return c == ' ' || c == '\t' || c == '\v' ||
    149 	       c == '\n' || c == '\f' || c == '\r';
    150 }
    151 
    152 static char *
    153 parameter(Macro *mp, int n)
    154 {
    155 	int siz;
    156 	char *s, *begin, *end;
    157 
    158 	mp->arg = NULL;
    159 	mp->argsiz = 0;
    160 
    161 	for (;;) {
    162 		switch (*input->p) {
    163 		case '"':
    164 		case '\'':
    165 			next();
    166 			assert(yytoken == STRING || yytoken == CONSTANT);
    167 			appendpar(mp, yytext, yylen);
    168 			break;
    169 		case '(':
    170 			appendpar(mp, input->p++, 1);
    171 			paren(mp);
    172 			break;
    173 		case ',':
    174 			if (n+1 == mp->npars)
    175 				goto append;
    176 		case ')':
    177 			begin = mp->arg;
    178 			end = begin + mp->argsiz;
    179 
    180 			while (begin < end && cppspace(*begin))
    181 				begin++;
    182 			while (end > begin && cppspace(end[-1]))
    183 				end--;
    184 
    185 			siz = end - begin;
    186 			s = memcpy(xmalloc(siz + 1), begin, siz);
    187 			s[siz] = '\0';
    188 
    189 			return s;
    190 		case '\0':
    191 			if (!moreinput())
    192 				goto unterminated;
    193 			continue;
    194 		default:
    195 		append:
    196 			appendpar(mp, input->p++, 1);
    197 			break;
    198 		}
    199 	}
    200 
    201 unterminated:
    202 	error("unterminated argument list invoking macro \"%s\"",
    203 	      mp->sym->name);
    204 }
    205 
    206 static int
    207 parsepars(Macro *mp)
    208 {
    209 	int c, n;
    210 	char *name;
    211 
    212 	if (mp->npars == -1)
    213 		return 1;
    214 	if (ahead() != '(')
    215 		return 0;
    216 
    217 	input->p++;
    218 	name = mp->sym->name;
    219 
    220 	if (mp->npars == 0 && ahead() == ')') {
    221 		input->p++;
    222 		return 1;
    223 	}
    224 
    225 	disexpand = 1;
    226 	for (n = 0; n < NR_MACROARG; ) {
    227 		mp->arglist = xrealloc(mp->arglist, (n+1)*sizeof(char *));
    228 		mp->arglist[n] = parameter(mp, n);
    229 		DBG("MACRO fetched arg '%s'", mp->arglist[n]);
    230 		n++;
    231 
    232 		c = *input->p++;
    233 		if (c == ')')
    234 			break;
    235 		if (c != ',')
    236 			error("incorrect macro function-alike invocation of \"%s\"", name);
    237 	}
    238 	disexpand = 0;
    239 
    240 	if (n == mp->npars)
    241 		return 1;
    242 
    243 	if (n == mp->npars-1 && mp->sym->flags & SVARIADIC) {
    244 		DBG("MACRO defaulted __VA_ARGS__ to \"\"");
    245 		mp->arglist = xrealloc(mp->arglist, (n+1)*sizeof(char *));
    246 		mp->arglist[n] = xstrdup("");
    247 		return 1;
    248 	}
    249 
    250 	error("macro \"%s\" received %d arguments, but it takes %d",
    251 	      mp->sym->name, n, mp->npars);
    252 }
    253 
    254 static int
    255 concatoper(char *def, char *cur)
    256 {
    257 	char *s;
    258 
    259 	for (s = cur + 4; cppspace(*s); ++s)
    260 		;
    261 	if (*s == CONCAT)
    262 		return 1;
    263 
    264 	for (s = cur; s > def && cppspace(s[-1]); --s)
    265 		;
    266 	if (s > def && s[-1] == CONCAT)
    267 		return 1;
    268 
    269 	return 0;
    270 }
    271 
    272 static int
    273 stringoper(char **bpp, int *sizep, char *arg)
    274 {
    275 	int c, esc, delim, siz;
    276 	char *bp;
    277 
    278 	bp = *bpp;
    279 	siz = *sizep;
    280 
    281 	if (siz < 3)
    282 		return 0;
    283 
    284 	esc = delim = 0;
    285 
    286 	*bp++ = '"';
    287 	while ((c = *arg++) != '\0') {
    288 		switch (c) {
    289 		case '\'':
    290 		case '"':
    291 			if (!esc) {
    292 				if (!delim)
    293 					delim = c;
    294 				else if (delim == c)
    295 					delim = 0;
    296 			}
    297 
    298 			if (c == '"') {
    299 				if (siz < 4)
    300 					return 0;
    301 				*bp++ = '\\';
    302 				siz--;
    303 			} else {
    304 				if (siz < 3)
    305 					return 0;
    306 			}
    307 
    308 			*bp++ = c;
    309 			siz--;
    310 			break;
    311 		case '\\':
    312 			if (!delim)
    313 				goto copy;
    314 			if (siz < 4)
    315 				return 0;
    316 			*bp++ = '\\';
    317 			*bp++ = '\\';
    318 			siz -= 2;
    319 
    320 			if (!esc) {
    321 				esc = 1;
    322 				continue;
    323 			}
    324 			break;
    325 		default:
    326 			if (!delim && cppspace(c)) {
    327 				while (cppspace(*arg))
    328 					++arg;
    329 				c = ' ';
    330 			}
    331 		copy:
    332 			if (siz < 3)
    333 				return 0;
    334 			*bp++ = c;
    335 			siz--;
    336 			break;
    337 		}
    338 		esc = 0;
    339 	}
    340 	*bp++ = '"';
    341 
    342 	*bpp = bp;
    343 	*sizep = siz;
    344 
    345 	return 1;
    346 }
    347 
    348 static int
    349 expandarg(char *arg, char *def, char *curdef, char *buf, int bufsiz)
    350 {
    351 	int siz;
    352 	char *s = buf;
    353 
    354 	/* gives priority to concatenation operators */
    355 	if (concatoper(def, curdef)) {
    356 		char *p;
    357 		int c;
    358 
    359 		/*
    360 		 * ignore NOEXPAND and EXPAND because ## has
    361 		 * precedence over macro expansion, and we just
    362 		 * want the argument as it is
    363 		 */
    364 		for (siz = 0, p = arg; (c = *p) != '\0'; p++) {
    365 			if (c == NOEXPAND || c == EXPAND)
    366 				continue;
    367 			if (siz == bufsiz - 1)
    368 				return -1;
    369 			*buf++ = c;
    370 			siz++;
    371 		}
    372 		*buf = '\0';
    373 	} else {
    374 		int n;
    375 		char noex[2] = {0, 0}, ex[2] = {0, 0};
    376 
    377 		/*
    378 		 * Here we have to deal with a special case,
    379 		 * because the recursive input expansion deals
    380 		 * correctly with the hideset manipulation,
    381 		 * but once the macro expansion is flattened in
    382 		 * a buffer associated to the macro expansion
    383 		 * all the hideset information is lost. To solve
    384 		 * this problem we have to add annotation tokens
    385 		 * to maintain this information and avoid expanding
    386 		 * macros hidden due to the recursive hidesets
    387 		 */
    388 		addinput(IPARAM, arg, FAIL);
    389 		for (siz = 0; ; siz += n) {
    390 			yyspace = noex[0] = ex[0] = '\0';
    391 			if (next() == EOFTOK)
    392 				break;
    393 
    394 			if (yytoken == IDEN) {
    395 				Symbol *sym = yylval.cppsym;
    396 				if (disexpand || sym && sym->hide) {
    397 					noex[0] = NOEXPAND;
    398 					ex[0] = EXPAND;
    399 				}
    400 			}
    401 
    402 			n = snprintf(buf, bufsiz, "%s%s%s%s",
    403 			             yyspace ? " " : "", noex, yytext, ex);
    404 
    405 			if (n < 0 || n == bufsiz)
    406 				return -1;
    407 
    408 			buf += n;
    409 			bufsiz -= n;
    410 		}
    411 		delinput();
    412 	}
    413 
    414 	DBG("MACRO parameter '%s' expanded to '%s'", arg, s);
    415 
    416 	return siz;
    417 }
    418 
    419 static int
    420 copymacro(Macro *mp)
    421 {
    422 	int delim, c, esc;
    423 	char *s, *p, *arg, *bp;
    424 	int size, bufsiz;
    425 
    426 	if (mp->sym == symfile)
    427 		return sprintf(mp->buffer, "\"%s\" ", filenam);
    428 	if (mp->sym == symline)
    429 		return sprintf(mp->buffer, "%d ", lineno);
    430 
    431 	bp = mp->buffer;
    432 	bufsiz = mp->bufsiz;
    433 	for (s = mp->def; c = *s; ++s) {
    434 		switch (c) {
    435 		case '\'':
    436 			delim = '\'';
    437 			goto search_delim;
    438 		case '\"':
    439 			delim = '"';
    440 		search_delim:
    441 			esc = 0;
    442 			p = s;
    443 			for (++s; c = *s; ++s) {
    444 				if (c == '\\' && !esc)
    445 					esc = 1;
    446 				else if (c == delim &&!esc)
    447 					break;
    448 				else
    449 					esc = 0;
    450 			}
    451 			size = s - p + 1;
    452 			if (size > bufsiz)
    453 				goto expansion_too_long;
    454 			memcpy(bp, p, size);
    455 			bufsiz -= size;
    456 			bp += size;
    457 			break;
    458 		case CONCAT:
    459 			/* token concatenation operator */
    460 			DBG("MACRO concat");
    461 			while (cppspace(bp[-1]))
    462 				--bp, ++bufsiz;
    463 			while (cppspace(s[1]))
    464 				++s;
    465 			break;
    466 		case STRINGIZE:
    467 			/* stringfier operator */
    468 			DBG("MACRO stringize");
    469 			arg = mp->arglist[atoi(s += 2)];
    470 			s += 2;
    471 
    472 			if (!stringoper(&bp, &bufsiz, arg))
    473 				goto expansion_too_long;
    474 			break;
    475 		case MACROPAR:
    476 			/* parameter substitution */
    477 			arg = mp->arglist[atoi(s+1)];
    478 			size = expandarg(arg, mp->def, s, bp, bufsiz);
    479 			if (size < 0)
    480 				goto expansion_too_long;
    481 			bp += size;
    482 			bufsiz -= size;
    483 			s += 3;
    484 			break;
    485 		default:
    486 			if (bufsiz-- == 0)
    487 				goto expansion_too_long;
    488 			*bp++ = c;
    489 			break;
    490 		}
    491 	}
    492 	*bp = '\0';
    493 
    494 	return bp - mp->buffer;
    495 
    496 expansion_too_long:
    497 	error("macro expansion of \"%s\" too long", mp->sym->name);
    498 }
    499 
    500 /*
    501  * Functions to deal with macro hidesets. Yes, this sucks, a lot,
    502  * but before blaming me read
    503  * https://www.spinellis.gr/blog/20060626/cpp.algo.pdf
    504  * It is not my fault.
    505  */
    506 static void
    507 addhideset(Symbol *sym)
    508 {
    509 	Symbol **set, **p;
    510 
    511 	set = input->hideset;
    512 	for (p = set; p < &set[NR_MACROARG-1] && *p; ++p) {
    513 		if (*p == sym)
    514 			return;
    515 	}
    516 
    517 	if (p == &set[NR_MACROARG])
    518 		error("too complex macro expansion");
    519 
    520 	*p = sym;
    521 	DBG("MACRO Adding %s to hideset of %s",
    522 	    sym->name, input->macro->sym->name);
    523 }
    524 
    525 static void
    526 hide(Symbol *sym)
    527 {
    528 	DBG("SYM: hidding symbol %s %d", sym->name, sym->hide);
    529 	sym->hide = 1;
    530 }
    531 
    532 static void
    533 unhide(Symbol *sym)
    534 {
    535 	DBG("SYM: unhidding symbol %s %d", sym->name, sym->hide);
    536 	sym->hide = 0;
    537 }
    538 
    539 void
    540 unsethideset(Input *ip)
    541 {
    542 	Symbol **p;
    543 
    544 	for (p = ip->hideset; *p; ++p)
    545 		unhide(*p);
    546 }
    547 
    548 void
    549 sethideset(Input *ip)
    550 {
    551 	Symbol **p;
    552 
    553 	for (p = ip->hideset; *p; ++p)
    554 		hide(*p);
    555 }
    556 
    557 void
    558 delmacro(Macro *mp)
    559 {
    560 	int i;
    561 	Symbol **p;
    562 
    563 	if (!mp)
    564 		return;
    565 
    566 	if (mp->arglist) {
    567 		for (i = 0; i < mp->npars; i++)
    568 			free(mp->arglist[i]);
    569 	}
    570 
    571 	free(mp->arglist);
    572 	free(mp);
    573 }
    574 
    575 Macro *
    576 newmacro(Symbol *sym)
    577 {
    578 	Macro *mp;
    579 
    580 	mp = memset(xmalloc(sizeof(*mp)), 0, sizeof(*mp));
    581 	mp->sym = sym;
    582 	mp->def = sym->u.s + 3;
    583 	if (sym->u.s)
    584 		mp->npars = atoi(sym->u.s);
    585 
    586 	return mp;
    587 }
    588 
    589 static void
    590 intersect(Symbol **dst, Symbol **set)
    591 {
    592 	Symbol *sym, **cur, **p;
    593 
    594 	for (cur = dst; sym = *cur; ++cur) {
    595 		for (p = set; *p && *p != sym; ++p)
    596 			;
    597 		if (*p)
    598 			*dst++ = sym;
    599 	}
    600 
    601 	while (dst != cur)
    602 		*dst++ = NULL;
    603 }
    604 
    605 int
    606 expand(Symbol *sym)
    607 {
    608 	int spc, siz;
    609 	Macro *mp;
    610 
    611 	DBG("MACRO '%s' detected disexpand=%d hide=%d",
    612 	    sym->name, disexpand, sym->hide);
    613 
    614 	if (disexpand || sym->hide || sym->token != IDEN)
    615 		return 0;
    616 
    617 	spc = yyspace;
    618 	mp = newmacro(sym);
    619 	mp->fname = filenam;
    620 	memcpy(mp->hideset, input->hideset, sizeof(mp->hideset));
    621 
    622 	if (!parsepars(mp)) {
    623 		delmacro(mp);
    624 		return 0;
    625 	}
    626 
    627 	if (mp->npars != -1)
    628 		intersect(mp->hideset, input->hideset);
    629 	addinput(IMACRO, mp, FAIL);
    630 	addhideset(sym);
    631 	hide(sym);
    632 
    633 	mp->buffer = input->line;
    634 	mp->bufsiz = INPUTSIZ-1;
    635 
    636 	siz = copymacro(mp);
    637 	mp->buffer[siz] = '\0';
    638 	yyspace = spc;
    639 
    640 	DBG("MACRO '%s' expanded to :'%s'", mp->sym->name, mp->buffer);
    641 
    642 	return 1;
    643 }
    644 
    645 static int
    646 getpars(Symbol *args[NR_MACROARG])
    647 {
    648 	int n, c;
    649 	Symbol *sym;
    650 
    651 	if (*input->p != '(')
    652 		return -1;
    653 
    654 	/* skip the '(' */
    655 	next();
    656 	next();
    657 	if (yytoken == ')')
    658 		return 0;
    659 
    660 	n = 0;
    661 	do {
    662 		if (n == NR_MACROARG) {
    663 			cpperror("too many parameters in macro");
    664 			return NR_MACROARG;
    665 		}
    666 
    667 		if (yytoken == ELLIPSIS) {
    668 			sym = newsym(NS_MACROPAR, "__VA_ARGS__");
    669 		} else if (yytoken == IDEN) {
    670 			sym = yylval.sym;
    671 			next();
    672 		} else {
    673 			cpperror("macro arguments must be identifiers");
    674 			return NR_MACROARG;
    675 		}
    676 
    677 		if (!install(NS_MACROPAR, sym)) {
    678 			errorp("duplicated macro parameter '%s'", sym->name);
    679 		} else {
    680 			sym->flags |= SUSED;
    681 			args[n++] = sym;
    682 		}
    683 
    684 		if (accept(ELLIPSIS))
    685 			break;
    686 
    687 	} while (accept(','));
    688 
    689 	if (yytoken != ')') {
    690 		cpperror("expected ')' at the end of macro argument list");
    691 		return NR_MACROARG;
    692 	}
    693 
    694 	return n;
    695 }
    696 
    697 static int
    698 getdefs(Symbol *args[NR_MACROARG], int nargs, char *buffer, size_t bufsiz)
    699 {
    700 	Symbol **argp;
    701 	char c, *bp, *s, *p;
    702 	int len, id, token, prevc, ispar;
    703 
    704 	while (cppspace(*input->p))
    705 		++input->p;
    706 
    707 	bp = buffer;
    708 	for (prevc = 0; (c = *input->p) != '\n' && c != '\0'; ++input->p) {
    709 		len = 1;
    710 		ispar = 0;
    711 		s = &c;
    712 		token = c;
    713 
    714 		if (c == '#') {
    715 			if (input->p[1] == '#') {
    716 				c = token = CONCAT;
    717 				++input->p;
    718 			} else {
    719 				c = token = STRINGIZE;
    720 				while (cppspace(input->p[1]))
    721 					++input->p;
    722 			}
    723 		} else if (c == '"' || c == '\'' || c == '_' || isalpha(c)) {
    724 			next();
    725 			assert(yytoken == STRING ||
    726 			       yytoken == CONSTANT ||
    727 			       yytoken == IDEN);
    728 			token = yytoken;
    729 			s = yytext;
    730 			len = yylen;
    731 			--input->p;
    732 		}
    733 
    734 		if (token == IDEN && nargs > 0) {
    735 			for (argp = args; argp < &args[nargs]; ++argp) {
    736 				if (*argp == yylval.sym) {
    737 					id = argp - args;
    738 					sprintf(yytext,
    739 						"%c%02d%c", MACROPAR, id, MACROPAR);
    740 					ispar = 1;
    741 					yylen = len = 4;
    742 					break;
    743 				}
    744 			}
    745 		}
    746 
    747 		if (prevc == 0 && token == CONCAT)
    748 			goto wrong_concat;
    749 
    750 		if (prevc == STRINGIZE && !ispar) {
    751 			cpperror("'#' is not followed by a macro parameter");
    752 			return 0;
    753 		}
    754 
    755 		if (len >= bufsiz) {
    756 			cpperror("macro too long");
    757 			return 0;
    758 		}
    759 
    760 		memcpy(bp, s, len);
    761 		bp += len;
    762 		bufsiz -= len;
    763 		prevc = token;
    764 	}
    765 
    766 end_loop:
    767 	if ((yytoken = c) == '\0')
    768 		yytoken = EOFTOK;
    769 	if (prevc == CONCAT)
    770 		goto wrong_concat;
    771 	for ( ; bp > buffer && cppspace(bp[-1]); --bp);
    772 		;
    773 	*bp = '\0';
    774 	return 1;
    775 
    776 wrong_concat:
    777 	cpperror("'##' cannot appear at either ends of a macro expansion");
    778 	return 0;
    779 }
    780 
    781 static void
    782 define(void)
    783 {
    784 	int n;
    785 	Symbol *sym,*args[NR_MACROARG];
    786 	char buff[LINESIZ+1];
    787 	unsigned flags = SDECLARED|SSTRING;
    788 
    789 	if (cppoff)
    790 		return;
    791 
    792 	namespace = NS_CPP;
    793 	next();
    794 
    795 	if (yytoken != IDEN) {
    796 		cpperror("macro names must be identifiers");
    797 		return;
    798 	}
    799 	sym = yylval.sym;
    800 
    801 	namespace = NS_MACROPAR;   /* Avoid polution in NS_CPP */
    802 	if ((n = getpars(args)) == NR_MACROARG)
    803 		goto delete;
    804 	if (n > 0 && strcmp(args[n-1]->name, "__VA_ARGS__") == 0)
    805 		flags |= SVARIADIC;
    806 
    807 	sprintf(buff, "%02d#", n);
    808 	if (!getdefs(args, n, buff+3, LINESIZ-3))
    809 		goto delete;
    810 
    811 	if (sym->flags & SDECLARED) {
    812 		if (strcmp(sym->u.s, buff) != 0)
    813 			warn("'%s' redefined", sym->name);
    814 		free(sym->u.s);
    815 	} else {
    816 		sym = install(NS_CPP, sym);
    817 		sym->flags |= flags;
    818 	}
    819 
    820 	sym->u.s = xstrdup(buff);
    821 	DBG("MACRO '%s' defined as '%s'", sym->name, buff);
    822 	return;
    823 
    824 delete:
    825 	killsym(sym);
    826 }
    827 
    828 void
    829 incdir(char *dir)
    830 {
    831 	if (!dir || *dir == '\0')
    832 		die("cc1: incorrect -I flag");
    833 	newitem(&dirinclude, dir);
    834 }
    835 
    836 static int
    837 includefile(char *dir, char *file, size_t filelen)
    838 {
    839 	size_t dirlen;
    840 	char path[FILENAME_MAX];
    841 
    842 	if (!dir) {
    843 		dirlen = 0;
    844 		if (filelen > FILENAME_MAX-1)
    845 			return 0;
    846 	} else {
    847 		dirlen = strlen(dir);
    848 		if (dirlen + filelen > FILENAME_MAX-2)
    849 			return 0;
    850 		memcpy(path, dir, dirlen);
    851 		if (dir[dirlen-1] != '/')
    852 			path[dirlen++] = '/';
    853 	}
    854 	memcpy(path+dirlen, file, filelen);
    855 	path[dirlen + filelen] = '\0';
    856 
    857 	return addinput(IFILE, path, NOFAIL);
    858 }
    859 
    860 static char *
    861 cwd(char *buf)
    862 {
    863 	char *p, *s = filenam;
    864 	size_t len;
    865 
    866 	if ((p = strrchr(s, '/')) == NULL)
    867 		return NULL;
    868 	if ((len = p - s) >= FILENAME_MAX)
    869 		die("cc1: current work directory too long");
    870 	memcpy(buf, s, len);
    871 	buf[len] = '\0';
    872 	return buf;
    873 }
    874 
    875 static void
    876 include(void)
    877 {
    878 	char dir[FILENAME_MAX], file[FILENAME_MAX], *p, **bp;
    879 	size_t filelen;
    880 	int n;
    881 
    882 	if (cppoff)
    883 		return;
    884 
    885 	disexpand = 0;
    886 	namespace = NS_IDEN;
    887 	next();
    888 
    889 	switch (*yytext) {
    890 	case '<':
    891 		if ((p = strchr(input->begin, '>')) == NULL || p[-1] == '<')
    892 			goto bad_include;
    893 		filelen = p - input->begin;
    894 		if (filelen >= FILENAME_MAX)
    895 			goto too_long;
    896 		memcpy(file, input->begin, filelen);
    897 		file[filelen] = '\0';
    898 
    899 		input->begin = input->p = p+1;
    900 		if (next() != '\n')
    901 			goto trailing_characters;
    902 
    903 		break;
    904 	case '"':
    905 		if (yylen < 3)
    906 			goto bad_include;
    907 		filelen = yylen-2;
    908 		if (filelen >= FILENAME_MAX)
    909 			goto too_long;
    910 		memcpy(file, yytext+1, filelen);
    911 		file[filelen] = '\0';
    912 
    913 		if (next() != '\n')
    914 			goto trailing_characters;
    915 
    916 		if (includefile(cwd(dir), file, filelen))
    917 			goto its_done;
    918 		break;
    919 	default:
    920 		goto bad_include;
    921 	}
    922 
    923 	n = dirinclude.n;
    924 	for (bp = dirinclude.s; n--; ++bp) {
    925 		if (includefile(*bp, file, filelen))
    926 			goto its_done;
    927 	}
    928 	cpperror("included file '%s' not found", file);
    929 
    930 its_done:
    931 	return;
    932 
    933 trailing_characters:
    934 	cpperror("trailing characters after preprocessor directive");
    935 	return;
    936 
    937 too_long:
    938 	cpperror("too long file name in #include");
    939 	return;
    940 
    941 bad_include:
    942 	cpperror("#include expects \"FILENAME\" or <FILENAME>");
    943 	return;
    944 }
    945 
    946 static void
    947 line(void)
    948 {
    949 	long n;
    950 	char *endp, *fname;
    951 
    952 	if (cppoff)
    953 		return;
    954 
    955 	disexpand = 0;
    956 	next();
    957 	n = strtol(yytext, &endp, 10);
    958 	if (n <= 0 || n > USHRT_MAX || *endp != '\0') {
    959 		cpperror("first parameter of #line is not a positive integer");
    960 		return;
    961 	}
    962 
    963 	next();
    964 	if (yytoken == '\n') {
    965 		fname = NULL;
    966 	} else {
    967 		if (*yytext != '\"' || yylen == 1) {
    968 			cpperror("second parameter of #line is not a valid filename");
    969 			return;
    970 		}
    971 		fname = yylval.sym->u.s;
    972 	}
    973 	setloc(fname, n - 1);
    974 	if (yytoken != '\n')
    975 		next();
    976 }
    977 
    978 static void
    979 pragma(void)
    980 {
    981 	if (cppoff)
    982 		return;
    983 	next();
    984 	warn("ignoring pragma '%s'", yytext);
    985 	*input->p = '\0';
    986 	next();
    987 }
    988 
    989 static void
    990 usererr(void)
    991 {
    992 	if (cppoff)
    993 		return;
    994 	cpperror("#error %s", input->p);
    995 	exit(EXIT_FAILURE);
    996 	next();
    997 }
    998 
    999 
   1000 Node *
   1001 defined(void)
   1002 {
   1003 	Symbol *sym;
   1004 	int paren;
   1005 
   1006 	disexpand = 1;
   1007 	next();
   1008 	paren = accept('(');
   1009 	if (yytoken != IDEN && yytoken != TYPEIDEN)
   1010 		cpperror("operator 'defined' requires an identifier");
   1011 	if (yytoken == TYPEIDEN || !(yylval.sym->flags & SDECLARED))
   1012 		sym = zero;
   1013 	else
   1014 		sym = one;
   1015 	disexpand = 0;
   1016 	next();
   1017 	if (paren)
   1018 		expect(')');
   1019 	return constnode(sym);
   1020 }
   1021 
   1022 static void
   1023 ifclause(int negate, int isifdef)
   1024 {
   1025 	Symbol *sym;
   1026 	unsigned n;
   1027 	int enabled, done;
   1028 	Node *expr;
   1029 
   1030 	if (cppctx == NR_COND-1)
   1031 		error("too many nesting levels of conditional inclusion");
   1032 	n = cppctx++;
   1033 	DBG("CPP ifclause updates cppctx=%d", cppctx);
   1034 
   1035 	if (n > 0 && !ifstate[n-1].enabled) {
   1036 		done = 1;
   1037 		enabled = 0;
   1038 		goto disabled;
   1039 	}
   1040 
   1041 	namespace = NS_CPP;
   1042 	next();
   1043 
   1044 	if (isifdef) {
   1045 		if (yytoken != IDEN) {
   1046 			cpperror("no macro name given in #%s directive",
   1047 			         (negate) ? "ifndef" : "ifdef");
   1048 			return;
   1049 		}
   1050 		sym = yylval.sym;
   1051 		next();
   1052 		enabled = (sym->flags & SDECLARED) != 0;
   1053 		if (!enabled)
   1054 			killsym(sym);
   1055 	} else {
   1056 		/* TODO: catch recovery here */
   1057 		if ((expr = iconstexpr()) == NULL) {
   1058 			cpperror("parameter of #if is not an integer constant expression");
   1059 			return;
   1060 		}
   1061 		DBG("CPP if expr=%d", expr->sym->u.i);
   1062 		enabled = expr->sym->u.i != 0;
   1063 		freetree(expr);
   1064 	}
   1065 
   1066 	if (negate)
   1067 		enabled = !enabled;
   1068 	done = enabled;
   1069 
   1070 disabled:
   1071 	cppoff = !enabled;
   1072 	DBG("CPP if result=%d", enabled);
   1073 	ifstate[n].done = done;
   1074 	ifstate[n].enabled = enabled;
   1075 	ifstate[n].iselse = 0;
   1076 }
   1077 
   1078 static void
   1079 cppif(void)
   1080 {
   1081 	DBG("CPP line=%u if cppctx=%d", lineno, cppctx);
   1082 	disexpand = 0;
   1083 	ifclause(0, 0);
   1084 }
   1085 
   1086 static void
   1087 ifdef(void)
   1088 {
   1089 	DBG("CPP line=%u ifdef cppctx=%d", lineno, cppctx);
   1090 	ifclause(0, 1);
   1091 }
   1092 
   1093 static void
   1094 ifndef(void)
   1095 {
   1096 	DBG("CPP line=%u ifndef cppctx=%d", lineno, cppctx);
   1097 	ifclause(1, 1);
   1098 }
   1099 
   1100 static void
   1101 cppelse(void)
   1102 {
   1103 	DBG("CPP line=%u else cppctx=%d", lineno, cppctx);
   1104 
   1105 	if (cppctx == 0 || ifstate[cppctx-1].iselse) {
   1106 		cpperror("#else without #ifdef/ifndef");
   1107 		return;
   1108 	}
   1109 
   1110 	/*
   1111 	 * If we are disabled by a upper ifdef then ifclause() already
   1112 	 * marked us as disabled and done. So if we are done then we
   1113 	 * disable cpp because or ifclause was true, or it was disabled
   1114 	 * by the upper. If we are not done, then it is our turn.
   1115 	 */
   1116 	if (ifstate[cppctx-1].done) {
   1117 		ifstate[cppctx-1].enabled = 0;
   1118 		cppoff = 1;
   1119 	} else {
   1120 		ifstate[cppctx-1].done = 1;
   1121 		ifstate[cppctx-1].enabled = 1;
   1122 		cppoff = 0;
   1123 	}
   1124 	ifstate[cppctx-1].iselse = 1;
   1125 
   1126 	next();
   1127 }
   1128 
   1129 static void
   1130 elif(void)
   1131 {
   1132 	DBG("CPP line=%u elif cppctx=%d", lineno, cppctx);
   1133 
   1134 	if (cppctx == 0 || ifstate[cppctx-1].iselse) {
   1135 		cpperror("#elif without #ifdef/ifndef");
   1136 		return;
   1137 	}
   1138 
   1139 	/*
   1140 	 * If we are disabled by a upper ifdef then ifclause() already
   1141 	 * marked us as disabled and done. So if we are done then we
   1142 	 * disable cpp because or ifclause was true, or it was disabled
   1143 	 * by the upper. If we are not done, then we have to evaluate
   1144 	 * the if condition.
   1145 	 */
   1146 	if (ifstate[cppctx-1].done) {
   1147 		ifstate[cppctx-1].enabled = 0;
   1148 		cppoff = 1;
   1149 	} else {
   1150 		--cppctx;
   1151 		DBG("elif updates cppctx=%d", cppctx);
   1152 		cppif();
   1153 	}
   1154 }
   1155 
   1156 static void
   1157 endif(void)
   1158 {
   1159 	DBG("CPP line=%u endif cppctx=%d", lineno, cppctx);
   1160 
   1161 	if (cppctx == 0)
   1162 		error("#endif without #if");
   1163 
   1164 	if (cppctx > 1)
   1165 		cppoff = !ifstate[cppctx - 2].enabled;
   1166 	else
   1167 		cppoff = 0;
   1168 
   1169 	--cppctx;
   1170 	DBG("CPP endif updates cppctx=%d", cppctx);
   1171 	next();
   1172 }
   1173 
   1174 static void
   1175 undef(void)
   1176 {
   1177 	if (cppoff)
   1178 		return;
   1179 
   1180 	namespace = NS_CPP;
   1181 	next();
   1182 	if (yytoken != IDEN) {
   1183 		error("no macro name given in #undef directive");
   1184 		return;
   1185 	}
   1186 	killsym(yylval.sym);
   1187 	next();
   1188 }
   1189 
   1190 int
   1191 cpp(void)
   1192 {
   1193 	static struct {
   1194 		unsigned char token;
   1195 		void (*fun)(void);
   1196 	} *bp, clauses [] = {
   1197 		{DEFINE, define},
   1198 		{INCLUDE, include},
   1199 		{LINE, line},
   1200 		{IFDEF, ifdef},
   1201 		{IF, cppif},
   1202 		{ELIF, elif},
   1203 		{IFNDEF, ifndef},
   1204 		{ELSE, cppelse},
   1205 		{ENDIF, endif},
   1206 		{UNDEF, undef},
   1207 		{PRAGMA, pragma},
   1208 		{ERROR, usererr},
   1209 		{0, NULL}
   1210 	};
   1211 	int ns;
   1212 	char *p;
   1213 
   1214 	for (p = input->p; cppspace(*p); ++p)
   1215 		;
   1216 
   1217 	if (*p != '#') {
   1218 		if (cppoff)
   1219 			*input->p = '\0';
   1220 		return cppoff;
   1221 	}
   1222 	input->p = p+1;
   1223 
   1224 	disexpand = 1;
   1225 	lexmode = CPPMODE;
   1226 	ns = namespace;
   1227 	namespace = NS_CPPCLAUSES;
   1228 	next();
   1229 	namespace = NS_IDEN;
   1230 
   1231 	if (yytoken == '\n')
   1232 		goto ret;
   1233 
   1234 	for (bp = clauses; bp->token && bp->token != yytoken; ++bp)
   1235 		;
   1236 	if (!bp->token) {
   1237 		errorp("incorrect preprocessor directive '%s'", yytext);
   1238 		goto ret;
   1239 	}
   1240 
   1241 	DBG("CPP %s", yytext);
   1242 
   1243 	/*
   1244 	 * create a new context to avoid polish the current context,
   1245 	 * and to get all the symbols freed at the end
   1246 	 */
   1247 	pushctx();
   1248 	(*bp->fun)();
   1249 	popctx();
   1250 
   1251 	/*
   1252 	 * #include changes the content of input->line, so the correctness
   1253 	 * of the line must be checked in the own include(), and we have
   1254 	 * to skip this tests. For the same reason include() is the only
   1255 	 * function which does not prepare the next token
   1256 	 */
   1257 	if (bp->token == INCLUDE)
   1258 		goto ret;
   1259 
   1260 	if (yytoken != '\n' && yytoken != EOFTOK && !cppoff)
   1261 		cpperror("trailing characters after preprocessor directive");
   1262 
   1263 ret:
   1264 	disexpand = 0;
   1265 	lexmode = CCMODE;
   1266 	namespace = ns;
   1267 
   1268 	/*
   1269 	 * at this point we know that the cpp line is processed, and any error
   1270 	 * is generated but as next is called we cannot be sure that input is
   1271 	 * valid anymore, but in case of begin valid we want to discard any
   1272 	 * pending input in the current line
   1273 	 */
   1274 	if (input)
   1275 		*input->p = '\0';
   1276 
   1277 	return 1;
   1278 }
   1279 
   1280 void
   1281 ppragmaln(void)
   1282 {
   1283 	static char file[FILENAME_MAX];
   1284 	static unsigned nline;
   1285 	char *s;
   1286 
   1287 	putchar('\n');
   1288 	if (strcmp(file, filenam)) {
   1289 		strcpy(file, filenam);
   1290 		s = "#line %u \"%s\"\n";
   1291 	} else if (nline+1 != lineno) {
   1292 		s = "#line %u\n";
   1293 	} else {
   1294 		s = "";
   1295 	}
   1296 	nline = lineno;
   1297 	printf(s, nline, file);
   1298 
   1299 	for (s = input->line; isspace(*s); ++s)
   1300 		putchar(*s);
   1301 	yyspace = 0;
   1302 }
   1303 
   1304 void
   1305 outcpp(void)
   1306 {
   1307 	for (next(); yytoken != EOFTOK; next()) {
   1308 		if (onlyheader)
   1309 			continue;
   1310 		printf("%s%s", yyspace ? " " : "", yytext);
   1311 		yyspace = 0;
   1312 	}
   1313 	putchar('\n');
   1314 }