scc

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

parser.c (16076B)


      1 #include <assert.h>
      2 #include <ctype.h>
      3 #include <errno.h>
      4 #include <limits.h>
      5 #include <stdarg.h>
      6 #include <stdio.h>
      7 #include <stdlib.h>
      8 #include <string.h>
      9 
     10 #include "make.h"
     11 
     12 #define MAXREPL  30
     13 #define TABSIZ   64
     14 #define MAXTOKEN FILENAME_MAX
     15 #define ITEM     128
     16 
     17 typedef struct macro Macro;
     18 
     19 enum inputype {
     20 	FTFILE,
     21 	FTEXPAN,
     22 };
     23 
     24 enum {
     25 	STBEGIN,
     26 	STINTERNAL,
     27 	STREPLACE,
     28 	STTO,
     29 	STEND,
     30 };
     31 
     32 struct input {
     33 	int siz;
     34 	int type;
     35 
     36 	FILE *fp;
     37 	struct loc loc;
     38 
     39 	int pos;
     40 	char *buf;
     41 
     42 	struct input *prev;
     43 };
     44 
     45 struct macro {
     46 	char *name;
     47 	char *value;
     48 	int where;
     49 
     50 	struct macro *next;
     51 };
     52 
     53 static struct input *input;
     54 static char token[MAXTOKEN];
     55 static int tok;
     56 static Macro *htab[TABSIZ];
     57 
     58 void
     59 dumpmacros(void)
     60 {
     61 	Macro **pp, *p;
     62 
     63 	for (pp = htab; pp < &htab[TABSIZ]; ++pp) {
     64 		for (p = *pp; p; p = p->next)
     65 			printf("%s = %s\n", p->name, getmacro(p->name));
     66 	}
     67 }
     68 
     69 static Macro *
     70 lookup(char *name)
     71 {
     72 	Macro *mp;
     73 	int h = hash(name) & TABSIZ-1;
     74 
     75 	for (mp = htab[h]; mp && strcmp(mp->name, name); mp = mp->next)
     76 		;
     77 
     78 	if (mp)
     79 		return mp;
     80 
     81 	mp = emalloc(sizeof(*mp));
     82 	mp->name = estrdup(name);
     83 	mp->value = estrdup("");
     84 	mp->next = htab[h];
     85 	mp->where = UNDEF;
     86 	htab[h] = mp;
     87 
     88 	return mp;
     89 }
     90 
     91 static char *
     92 macroinfo(char *name, int *pwhere, Macro **mpp)
     93 {
     94 	char *s, *t;
     95 	int hide, where;
     96 	Macro *mp = lookup(name);
     97 
     98 	hide = 0;
     99 	if (!strcmp(name, "SHELL") || !strcmp(name, "MAKEFLAGS"))
    100 		hide = 1;
    101 
    102 	s = mp->value;
    103 	where = mp->where;
    104 
    105 	if (!s && !hide) {
    106 		where = ENVIRON;
    107 		s = getenv(name);
    108 	}
    109 
    110 	if (eflag && !hide) {
    111 		t = getenv(name);
    112 		if (t) {
    113 			where = ENVIRON;
    114 			s = t;
    115 		}
    116 	}
    117 
    118 	if (pwhere)
    119 		*pwhere = where;
    120 	if (mpp)
    121 		*mpp = mp;
    122 
    123 	return s;
    124 }
    125 
    126 char *
    127 getmacro(char *name)
    128 {
    129 	return macroinfo(name, NULL, NULL);
    130 }
    131 
    132 void
    133 setmacro(char *name, char *val, int where, int export)
    134 {
    135 	int owhere, set;
    136 	char *s;
    137 	Macro *mp;
    138 
    139 	assert(where != ENVIRON);
    140 
    141 	s = macroinfo(name, &owhere, &mp);
    142 
    143 	/*
    144 	 *  Default values are defined before anything else, and marked
    145 	 *  as MAKEFILES because they are injected as parseable text, and
    146 	 *  MAKEFILE variables are always overriden. ENVIRON macros are
    147 	 *  generated in macroinfo() and this is why this function should
    148 	 *  not receive a where == ENVIRON ever.
    149 	 */
    150 
    151 	switch (owhere) {
    152 	case UNDEF:
    153 	case MAKEFILE:
    154 		set = 1;
    155 		break;
    156 	case ENVIRON:
    157 		set = (where == MAKEFLAGS || where == CMDLINE);
    158 		set |= (where == MAKEFILE && !eflag);
    159 		break;
    160 	case MAKEFLAGS:
    161 		set = (where == CMDLINE || where == MAKEFLAGS);
    162 		break;
    163 	case CMDLINE:
    164 		set = (where == CMDLINE);
    165 		break;
    166 	default:
    167 		abort();
    168 	}
    169 
    170 	if (!set) {
    171 		debug("hidding override of %s from '%s' to '%s'", name, s, val);
    172 	} else {
    173 		debug("override %s from '%s' to '%s'", name, s, val);
    174 		free(mp->value);
    175 		mp->value = estrdup(val);
    176 		mp->where = where;
    177 
    178 		if (export && strcmp(name, "SHELL") != 0) {
    179 			debug("exporting macro %s", name);
    180 			exportvar(name, val);
    181 		}
    182 	}
    183 }
    184 
    185 void
    186 freeloc(struct loc *loc)
    187 {
    188 	free(loc->fname);
    189 }
    190 
    191 static struct loc *
    192 getloc(void)
    193 {
    194 	struct input *ip;
    195 
    196 	for (ip = input; ip && ip->type != FTFILE; ip = ip->prev)
    197 		;
    198 	if (!ip)
    199 		return NULL;
    200 
    201 	return &ip->loc;
    202 }
    203 
    204 
    205 void
    206 error(char *fmt, ...)
    207 {
    208 	va_list va;
    209 	struct loc *loc;
    210 
    211 	fprintf(stderr, "make: error: ");
    212 	if ((loc = getloc()) != NULL)
    213 		fprintf(stderr, "%s:%d: ", loc->fname, loc->lineno);
    214 
    215 	va_start(va, fmt);
    216 	vfprintf(stderr, fmt, va);
    217 	va_end(va);
    218 	putc('\n', stderr);
    219 
    220 	exit(EXIT_FAILURE);
    221 }
    222 
    223 void
    224 warning(char *fmt, ...)
    225 {
    226 	va_list va;
    227 	struct loc *loc;
    228 
    229 	fprintf(stderr, "make: warning: ");
    230 	if ((loc = getloc()) != NULL)
    231 		fprintf(stderr, "%s:%d: ", loc->fname, loc->lineno);
    232 
    233 	va_start(va, fmt);
    234 	vfprintf(stderr, fmt, va);
    235 	va_end(va);
    236 	putc('\n', stderr);
    237 }
    238 
    239 static void
    240 pop(void)
    241 {
    242 	struct input *ip = input->prev;
    243 
    244 	if (input->type == FTFILE) {
    245 		if (input->fp)
    246 			fclose(input->fp);
    247 		freeloc(&input->loc);
    248 	}
    249 	free(input->buf);
    250 	free(input);
    251 
    252 	input = ip;
    253 }
    254 
    255 static void
    256 push(int type, ...)
    257 {
    258 	int line, len, pos;
    259 	FILE *fp = NULL;
    260 	char *buf, *s, *fname = NULL;
    261 	va_list va;
    262 	struct input *ip;
    263 
    264 	va_start(va, type);
    265 	switch (type) {
    266 	case FTFILE:
    267 		fp = va_arg(va, FILE *);
    268 		s = va_arg(va, char *);
    269 		line = va_arg(va, int);
    270 		fname = estrdup(s);
    271 		buf = emalloc(BUFSIZ);
    272 		pos = len = BUFSIZ;
    273 		break;
    274 	case FTEXPAN:
    275 		s = va_arg(va, char *);
    276 		buf = estrdup(s);
    277 		line = pos = 0;
    278 		len = strlen(s);
    279 		break;
    280 	}
    281 	va_end(va);
    282 
    283 	ip = emalloc(sizeof(*ip));
    284 	ip->siz = len;
    285 	ip->buf = buf;
    286 	ip->type = type;
    287 	ip->fp = fp;
    288 	ip->loc.fname = fname;
    289 	ip->loc.lineno = line;
    290 	ip->pos = pos;
    291 	ip->prev = input;
    292 
    293 	input = ip;
    294 }
    295 
    296 static char *
    297 trim(char *s)
    298 {
    299 	size_t len;
    300 
    301 	while (isspace(*s))
    302 		s++;
    303 
    304 	for (len = strlen(s); len > 0 && isspace(s[len-1]); --len)
    305 		s[len-1] = '\0';
    306 
    307 	return s;
    308 }
    309 
    310 static void
    311 include(char *s)
    312 {
    313 	int len;
    314 	FILE *fp;
    315 	char *fil, *t;
    316 
    317 	s = trim(s);
    318 	fil = expandstring(s, NULL, getloc());
    319 
    320 	t = trim(fil);
    321 	if (strlen(t) != 0) {
    322 		debug("including '%s'", t);
    323 		if ((fp = fopen(t, "r")) == NULL)
    324 			error("opening %s:%s", t, strerror(errno));
    325 		push(FTFILE, fp, t, 0);
    326 	}
    327 
    328 	free(fil);
    329 }
    330 
    331 static char *
    332 nextline(void)
    333 {
    334 	int c;
    335 	FILE *fp;
    336 	char *s, *lim;
    337 
    338 	assert(input->type == FTFILE);
    339 
    340 repeat:
    341 	fp = input->fp;
    342 	if (!fp || feof(fp))
    343 		return NULL;
    344 
    345 	lim = &input->buf[input->siz];
    346 	for (s = input->buf; s < lim; *s++ = c) {
    347 		c = getc(fp);
    348 		if (c == '\n' || c == EOF) {
    349 			input->loc.lineno++;
    350 			*s++ = '\n';
    351 			break;
    352 		}
    353 		if (c > UCHAR_MAX || c < 0)
    354 			error("invalid character '%c' (%d)", c, c);
    355 	}
    356 
    357 
    358 	if (s == lim)
    359 		error("too long line");
    360 	if (ferror(fp))
    361 		error(strerror(errno));
    362 	*s = '\0';
    363 
    364 	if (!strcmp(input->buf, ""))
    365 		goto repeat;
    366 
    367 	if (strncmp(input->buf, "include", 7) == 0) {
    368 		input->pos = input->siz;
    369 		include(input->buf+7);
    370 		goto repeat;
    371 	}
    372 
    373 	input->pos = 0;
    374 
    375 
    376 	return input->buf;
    377 }
    378 
    379 static int
    380 empty(struct input *ip)
    381 {
    382 	return ip->pos == ip->siz || ip->buf[ip->pos] == '\0';
    383 }
    384 
    385 static int
    386 moreinput(void)
    387 {
    388 	while (input) {
    389 		if (!empty(input))
    390 			break;
    391 
    392 		switch (input->type) {
    393 		case FTEXPAN:
    394 			pop();
    395 			break;
    396 		case FTFILE:
    397 			if (!nextline())
    398 				pop();
    399 			break;
    400 		}
    401 	}
    402 
    403 	return input != NULL;
    404 }
    405 
    406 static int
    407 nextc(void)
    408 {
    409 	if (!moreinput())
    410 		return EOF;
    411 
    412 	return input->buf[input->pos++];
    413 }
    414 
    415 /*
    416  * This function only can be called after a call to nextc
    417  * that didn't return EOF. It can return '\0', but as
    418  * it is used only to check against '$' then it is not
    419  * a problem.
    420  */
    421 static int
    422 ahead(void)
    423 {
    424 	return input->buf[input->pos];
    425 }
    426 
    427 static int
    428 back(int c)
    429 {
    430 	if (c == EOF)
    431 		return c;
    432 	assert(input->pos > 0);
    433 	return input->buf[--input->pos] = c;
    434 }
    435 
    436 static void
    437 comment(void)
    438 {
    439 	int c;
    440 
    441 	while ((c = nextc()) != EOF && c != '\n') {
    442 		if (c == '\\' && nextc() == EOF)
    443 			break;
    444 	}
    445 }
    446 
    447 static void
    448 skipspaces(void)
    449 {
    450 	int c;
    451 
    452 	for (c = nextc(); c == ' ' || c == '\t'; c = nextc())
    453 		;
    454 	back(c);
    455 }
    456 
    457 static int
    458 validchar(int c)
    459 {
    460 	if (c == EOF)
    461 		return 0;
    462 	return c == '.' || c == '/' || c == '_' || c == '-' || isalnum(c);
    463 }
    464 
    465 static char *
    466 expandmacro(char *name)
    467 {
    468 	return expandstring(getmacro(name), NULL, getloc());
    469 }
    470 
    471 static void
    472 replace(char *line, char *repl, char *to)
    473 {
    474 	int siz, at, len, replsiz, tosiz, sep, pos;
    475 	char *oline, *s, *cur, *buf;
    476 
    477 	debug("replacing '%s', with '%s' to '%s'", line, repl, to);
    478 	oline = line;
    479 	tosiz = strlen(to);
    480 	replsiz = strlen(repl);
    481 
    482 	buf = NULL;
    483 	for (pos = 0; *line; pos += siz) {
    484 		cur = NULL;
    485 		siz = 0;
    486 
    487 		for (siz = 0; *line == ' ' || *line == '\t'; ++siz) {
    488 			cur = erealloc(cur, siz+1);
    489 			cur[siz] = *line++;
    490 		}
    491 
    492 		len = strcspn(line, " \t");
    493 		at = len - replsiz;
    494 		if (at < 0 || memcmp(line + at, repl, replsiz)) {
    495 			cur = erealloc(cur, siz + len);
    496 			memcpy(cur + siz, line, len);
    497 			siz += len;
    498 		} else {
    499 			cur = erealloc(cur, siz + at + tosiz);
    500 			memcpy(cur + siz, line, at);
    501 			memcpy(cur + siz + at, to, tosiz);
    502 			siz += at + tosiz;
    503 		}
    504 
    505 		line += len;
    506 		buf = erealloc(buf, pos + siz);
    507 		memcpy(buf + pos, cur, siz);
    508 		free(cur);
    509 	}
    510 
    511 	if (pos > 0) {
    512 		buf = erealloc(buf, pos + 1);
    513 		buf[pos] = '\0';
    514 		debug("\treplace '%s' with '%s'", oline, buf);
    515 		push(FTEXPAN, buf);
    516 	}
    517 
    518 	free(buf);
    519 }
    520 
    521 static void
    522 expandsimple(Target *tp)
    523 {
    524 	char *s;
    525 	Target **p;
    526 	int len, c;
    527 
    528 	switch (c = nextc()) {
    529 	case '@':
    530 		if (!tp || !tp->target)
    531 			return;
    532 		push(FTEXPAN, tp->target);
    533 		break;
    534 	case '<':
    535 		if (!tp || !tp->req)
    536 			return;
    537 		push(FTEXPAN, tp->req);
    538 		break;
    539 	case '*':
    540 		if (!tp || !tp->target)
    541 			return;
    542 		s = strrchr(tp->target, '.');
    543 		if (!s) {
    544 			push(FTEXPAN, tp->target);
    545 			return;
    546 		}
    547 
    548 		len = s - tp->target;
    549 		s = emalloc(len+1);
    550 		memcpy(s, tp->target, len);
    551 		s[len] = '\0';
    552 		push(FTEXPAN, s);
    553 		free(s);
    554 		break;
    555 	case '?':
    556 		if (!tp)
    557 			return;
    558 
    559 		if (tp->req && stamp(tp->req) > tp->stamp) {
    560 			push(FTEXPAN, " ");
    561 			push(FTEXPAN, tp->req);
    562 		}
    563 
    564 		for (p = tp->deps; p && *p; ++p) {
    565 			if (stamp((*p)->name) > tp->stamp) {
    566 				push(FTEXPAN, " ");
    567 				push(FTEXPAN, (*p)->name);
    568 			}
    569 		}
    570 		break;
    571 	default:
    572 		token[0] = c;
    573 		token[1] = '\0';
    574 		s = expandmacro(token);
    575 		push(FTEXPAN, s);
    576 		free(s);
    577 		break;
    578 	}
    579 }
    580 
    581 static int
    582 internal(int ch)
    583 {
    584 	switch (ch) {
    585 	case '@':
    586 	case '?':
    587 	case '*':
    588 	case '<':
    589 		return 1;
    590 	default:
    591 		return 0;
    592 	}
    593 }
    594 
    595 static void
    596 expansion(Target *tp)
    597 {
    598 	int delim, c, repli, toi, namei, st;
    599 	char name[MAXTOKEN], repl[MAXREPL], to[MAXREPL];
    600 	char *s, *erepl;
    601 
    602 	c = nextc();
    603 	if (c == '(')
    604 		delim = ')';
    605 	else if (c == '{')
    606 		delim = '}';
    607 	else
    608 		delim = 0;
    609 
    610 	if (!delim) {
    611 		back(c);
    612 		expandsimple(tp);
    613 		return;
    614 	}
    615 
    616 	s = NULL;
    617 	namei = repli = toi = 0;
    618 	st = STBEGIN;
    619 
    620 	while (st != STEND && (c = nextc()) != EOF) {
    621 		switch (st) {
    622 		case STBEGIN:
    623 			if (c == ':') {
    624 				st = STREPLACE;
    625 				name[namei] = '\0';
    626 				s = expandmacro(name);
    627 				break;
    628 			}
    629 			if (c == delim) {
    630 				name[namei] = '\0';
    631 				s = expandmacro(name);
    632 				goto no_replace;
    633 			}
    634 			if (namei == MAXTOKEN-1)
    635 				error("expansion text too long");
    636 
    637 			if (namei == 0 && internal(c)) {
    638 				name[namei++] = '$';
    639 				name[namei++] = c;
    640 				name[namei] = '\0';
    641 				st = STINTERNAL;
    642 				s = expandstring(name, tp, getloc());
    643 				break;
    644 			}
    645 
    646 			if (!validchar(c))
    647 				error("invalid macro name in expansion");
    648 			name[namei++] = c;
    649 			break;
    650 		case STINTERNAL:
    651 			if (c == delim)
    652 				goto no_replace;
    653 			if (c != ':')
    654 				error("invalid internal macro in expansion");
    655 			st = STREPLACE;
    656 			break;
    657 		case STREPLACE:
    658 			if (c == '=') {
    659 				st = STTO;
    660 				break;
    661 			}
    662 			if (c == delim)
    663 				error("invalid replacement pattern in expansion");
    664 			if (repli == MAXREPL-1)
    665 				error("macro replacement too big");
    666 			repl[repli++] = c;
    667 			break;
    668 		case STTO:
    669 			if (c == delim) {
    670 				st = STEND;
    671 				break;
    672 			}
    673 
    674 			if (toi == MAXREPL-1)
    675 				error("macro substiturion too big");
    676 			to[toi++] = c;
    677 			break;
    678 		}
    679 	}
    680 
    681 	if (c == EOF)
    682 		error("found eof while parsing expansion");
    683 
    684 	repl[repli] = '\0';
    685 	to[toi] = '\0';
    686 
    687 	erepl = expandstring(repl, tp, getloc());
    688 	replace(s, erepl, to);
    689 
    690 	free(erepl);
    691 	free(s);
    692 	return;
    693 
    694 no_replace:
    695 	push(FTEXPAN, s);
    696 	free(s);
    697 }
    698 
    699 /*
    700  * Horrible hack to do string expansion.
    701  * We cannot use normal push and nextc because that
    702  * would consume characters of the current file too.
    703  * For that reason it cleans the input and it recovers
    704  * it later.
    705  */
    706 char *
    707 expandstring(char *line, Target *tp, struct loc *loc)
    708 {
    709 	int c, n;
    710 	char *s;
    711 	struct input *ip = input;
    712 
    713 	input = NULL;
    714 	push(FTFILE, NULL, loc->fname, loc->lineno);
    715 	push(FTEXPAN, line);
    716 
    717 	n = 0;
    718 	s = NULL;
    719 	while ((c = nextc()) != EOF) {
    720 		if (c != '$') {
    721 			s = erealloc(s, ++n);
    722 			s[n-1] = c;
    723 			continue;
    724 		}
    725 
    726 		if ((c = nextc()) == '$') {
    727 			s = erealloc(s, n += 2);
    728 			s[n-2] = '$';
    729 			s[n-1] = '$';
    730 		} else {
    731 			back(c);
    732 			expansion(tp);
    733 		}
    734 	}
    735 
    736 	s = erealloc(s, n+1);
    737 	s[n] = '\0';
    738 	input = ip;
    739 
    740 	return s;
    741 }
    742 
    743 static int
    744 item(void)
    745 {
    746 	int c;
    747 	char *s;
    748 	char buf[MAXTOKEN];
    749 
    750 	for (s = buf; s < &buf[MAXTOKEN] - 1; ) {
    751 		c = nextc();
    752 		if (c == '$' && ahead() != '$')
    753 			expansion(NULL);
    754 		else if (validchar(c))
    755 			*s++ = c;
    756 		else
    757 			break;
    758 	}
    759 	back(c);
    760 
    761 	if (s >= &buf[MAXTOKEN] - 1)
    762 		error("token too long");
    763 	if (s == buf)
    764 		error("invalid empty token");
    765 	*s++ = '\0';
    766 	memcpy(token, buf, s - buf);
    767 
    768 	return ITEM;
    769 }
    770 
    771 static int
    772 next(void)
    773 {
    774 	int c;
    775 
    776 repeat:
    777 	/*
    778 	 * It is better to avoid skipspaces() here, because
    779 	 * it can generate the need for 2 calls to back(),
    780 	 * and we need the character anyway.
    781 	 */
    782 	c = nextc();
    783 	if (c == ' ' || c == '\t')
    784 		goto repeat;
    785 
    786 	if (c == '\\') {
    787 		if ((c = nextc()) == '\n')
    788 			goto repeat;
    789 		back(c);
    790 		c = '\\';
    791 	}
    792 
    793 	switch (c) {
    794 	case EOF:
    795 		strcpy(token, "<EOF>");
    796 		tok = EOF;
    797 		break;
    798 	case '$':
    799 		if ((c = nextc()) == '$')
    800 			goto single;
    801 		back(c);
    802 		expansion(NULL);
    803 		goto repeat;
    804 	case '#':
    805 		comment();
    806 		c = '\n';
    807 	case ';':
    808 	case ':':
    809 	case '=':
    810 	case '\n':
    811 	single:
    812 		token[0] = c;
    813 		token[1] = '\0';
    814 		tok = c;
    815 		break;
    816 	default:
    817 		if (!validchar(c))
    818 			error("unexpected character '%c'", c);
    819 		back(c);
    820 		tok = item();
    821 		break;
    822 	}
    823 
    824 	return tok;
    825 }
    826 
    827 static char *
    828 readmacrodef(void)
    829 {
    830 	int n, c;
    831 	char *line;
    832 
    833 	n = 0;
    834 	line = NULL;
    835 	while ((c = nextc()) != EOF) {
    836 		line = erealloc(line, n+1);
    837 		if (c == '\n')
    838 			break;
    839 		if (c == '#') {
    840 			comment();
    841 			break;
    842 		}
    843 		if (c == '\\') {
    844 			if ((c = nextc()) != '\n') {
    845 				back(c);
    846 				c = '\\';
    847 			} else {
    848 				skipspaces();
    849 				c = ' ';
    850 			}
    851 		}
    852 
    853 		line[n++] = c;
    854 	}
    855 	if (c == EOF)
    856 		error("EOF while looking for end of line");
    857 	line[n] = '\0';
    858 
    859 	return line;
    860 }
    861 
    862 static struct action
    863 readcmd(void)
    864 {
    865 	int n, c;
    866 	struct loc *loc;
    867 	struct action act;
    868 
    869 	skipspaces();
    870 
    871 	loc = getloc();
    872 	act.loc.fname = estrdup(loc->fname);
    873 	act.loc.lineno = loc->lineno;
    874 
    875 	n = 0;
    876 	act.line = NULL;
    877 	while ((c = nextc()) != EOF) {
    878 		act.line = erealloc(act.line, n+1);
    879 		if (c == '\n')
    880 			break;
    881 		if (c == '\\') {
    882 			if ((c = nextc()) == '\n') {
    883 				if ((c = nextc()) != '\t')
    884 					back(c);
    885 				continue;
    886 			}
    887 			back(c);
    888 			c = '\\';
    889 		}
    890 		act.line[n++] = c;
    891 	}
    892 	if (c == EOF)
    893 		error("EOF while looking for end of command");
    894 	act.line[n] = '\0';
    895 
    896 	return act;
    897 }
    898 
    899 static void
    900 rule(char *targets[], int ntargets)
    901 {
    902 	int c, i, j, ndeps, nactions;
    903 	struct action *acts;
    904 	char **deps = NULL;
    905 
    906 	if (ntargets == 0)
    907 		error("missing target");
    908 
    909 	for (ndeps = 0; next() == ITEM; ++ndeps) {
    910 		deps = erealloc(deps, (ndeps+1) * sizeof(char *));
    911 		deps[ndeps] = estrdup(token);
    912 	}
    913 
    914 	if (tok != '\n' && tok != ';')
    915 		error("garbage at the end of the line");
    916 
    917 	nactions = 0;
    918 	acts = NULL;
    919 	if (tok == ';') {
    920 		nactions++;
    921 		acts = erealloc(acts, nactions * sizeof(*acts));
    922 		acts[nactions-1] = readcmd();
    923 	}
    924 
    925 	for (;;) {
    926 		if ((c = nextc()) == '#') {
    927 			comment();
    928 			continue;
    929 		}
    930 		if (c != '\t')
    931 			break;
    932 		nactions++;
    933 		acts = erealloc(acts, nactions * sizeof(*acts));
    934 		acts[nactions-1] = readcmd();
    935 	}
    936 	back(c);
    937 
    938 	for (i = 0; i < ntargets; i++) {
    939 		addtarget(targets[i], ndeps);
    940 		for (j = 0; j < ndeps; j++)
    941 			adddep(targets[i], deps[j]);
    942 		if (nactions > 0)
    943 			addrule(targets[i], acts, nactions);
    944 	}
    945 
    946 	for (i = 0; i < ndeps; i++)
    947 		free(deps[i]);
    948 	free(deps);
    949 
    950 	for (i = 0; i < nactions; i++) {
    951 		free(acts[i].line);
    952 		freeloc(&acts[i].loc);
    953 	}
    954 	free(acts);
    955 }
    956 
    957 static void
    958 assign(char *macros[], int n)
    959 {
    960 	char *defs;
    961 
    962 	if (n != 1)
    963 		error("invalid macro definition");
    964 
    965 	skipspaces();
    966 	defs = readmacrodef();
    967 	setmacro(*macros, defs, MAKEFILE, NOEXPORT);
    968 	free(defs);
    969 }
    970 
    971 void
    972 parseinput(void)
    973 {
    974 	int i, n;
    975 	char **targets;
    976 
    977 	while (moreinput()) {
    978 		n = 0;
    979 		targets = NULL;
    980 
    981 		next();
    982 		if (tok == '\n')
    983 			continue;
    984 
    985 		while (tok == ITEM) {
    986 			n++;
    987 			targets = erealloc(targets, n * sizeof(char *));
    988 			targets[n-1] = estrdup(token);
    989 			next();
    990 		}
    991 
    992 		switch (tok) {
    993 		case ':':
    994 			rule(targets, n);
    995 			break;
    996 		case '=':
    997 			assign(targets, n);
    998 			break;
    999 		default:
   1000 			error("unexpected token '%s'(%d)", token, tok);
   1001 		}
   1002 
   1003 		for (i = 0; i < n; i++)
   1004 			free(targets[i]);
   1005 		free(targets);
   1006 	}
   1007 }
   1008 
   1009 int
   1010 parse(char *fname)
   1011 {
   1012 	FILE *fp;
   1013 
   1014 	if (!fname) {
   1015 		fp = stdin;
   1016 		fname = "<stdin>";
   1017 	} else if ((fp = fopen(fname, "r")) == NULL) {
   1018 		return 0;
   1019 	}
   1020 
   1021 	debug("parsing %s", fname);
   1022 	push(FTFILE, fp, fname, 0);
   1023 	parseinput();
   1024 
   1025 	return 1;
   1026 }
   1027 
   1028 void
   1029 inject(char *s)
   1030 {
   1031 	push(FTFILE, NULL, "<internal>", 0);
   1032 	push(FTEXPAN, s);
   1033 	parseinput();
   1034 }