master xplshn/aruu / cmd / posix / make / parser.c
   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
  17typedef struct macro Macro;
  18
  19enum inputype {
  20	FTFILE,
  21	FTEXPAN,
  22};
  23
  24enum {
  25	STBEGIN,
  26	STINTERNAL,
  27	STREPLACE,
  28	STTO,
  29	STEND,
  30};
  31
  32struct 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
  45struct macro {
  46	char *name;
  47	char *value;
  48	int where;
  49
  50	struct macro *next;
  51};
  52
  53static struct input *input;
  54static char token[MAXTOKEN];
  55static int tok;
  56static Macro *htab[TABSIZ];
  57
  58void
  59dumpmacros(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
  69static Macro *
  70lookup(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
  91static char *
  92macroinfo(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 (!hide && (where == UNDEF || where == INTERNAL || eflag)) {
 106		t = getenv(name);
 107		if (t) {
 108			where = ENVIRON;
 109			s = t;
 110		}
 111	}
 112
 113	if (pwhere)
 114		*pwhere = where;
 115	if (mpp)
 116		*mpp = mp;
 117
 118	return s;
 119}
 120
 121char *
 122getmacro(char *name)
 123{
 124	return macroinfo(name, NULL, NULL);
 125}
 126
 127void
 128setmacro(char *name, char *val, int where, int export)
 129{
 130	int owhere, set;
 131	char *s;
 132	Macro *mp;
 133
 134	assert(where != ENVIRON);
 135
 136	s = macroinfo(name, &owhere, &mp);
 137
 138	/*
 139	 *  Default values are defined before anything else, and marked
 140	 *  as INTERNAL because they are injected as parseable text, and
 141	 *  MAKEFILE and INTERNAL variables are always overriden. ENVIRON
 142	 *  macros are generated in macroinfo() and this is why this function
 143	 *  should not receive a where == ENVIRON ever.
 144	 */
 145	switch (owhere) {
 146	case UNDEF:
 147	case INTERNAL:
 148	case MAKEFILE:
 149		set = 1;
 150		break;
 151	case ENVIRON:
 152		set = (where == MAKEFLAGS || where == CMDLINE);
 153		set |= (where == MAKEFILE && !eflag);
 154		break;
 155	case MAKEFLAGS:
 156		set = (where == CMDLINE || where == MAKEFLAGS);
 157		break;
 158	case CMDLINE:
 159		set = (where == CMDLINE);
 160		break;
 161	default:
 162		abort();
 163	}
 164
 165	if (!set) {
 166		debug("hidding override of %s from '%s' to '%s'", name, s, val);
 167	} else {
 168		debug("override %s from '%s' to '%s'", name, s, val);
 169		free(mp->value);
 170		mp->value = estrdup(val);
 171		mp->where = where;
 172
 173		if (export && strcmp(name, "SHELL") != 0) {
 174			debug("exporting macro %s", name);
 175			exportvar(name, val);
 176		}
 177	}
 178}
 179
 180void
 181freeloc(struct loc *loc)
 182{
 183	free(loc->fname);
 184}
 185
 186static struct loc *
 187getloc(void)
 188{
 189	struct input *ip;
 190
 191	for (ip = input; ip && ip->type != FTFILE; ip = ip->prev)
 192		;
 193	if (!ip)
 194		return NULL;
 195
 196	return &ip->loc;
 197}
 198
 199
 200void
 201error(char *fmt, ...)
 202{
 203	va_list va;
 204	struct loc *loc;
 205
 206	fprintf(stderr, "make: error: ");
 207	if ((loc = getloc()) != NULL)
 208		fprintf(stderr, "%s:%d: ", loc->fname, loc->lineno);
 209
 210	va_start(va, fmt);
 211	vfprintf(stderr, fmt, va);
 212	va_end(va);
 213	putc('\n', stderr);
 214
 215	exit(EXIT_FAILURE);
 216}
 217
 218void
 219warning(char *fmt, ...)
 220{
 221	va_list va;
 222	struct loc *loc;
 223
 224	fprintf(stderr, "make: warning: ");
 225	if ((loc = getloc()) != NULL)
 226		fprintf(stderr, "%s:%d: ", loc->fname, loc->lineno);
 227
 228	va_start(va, fmt);
 229	vfprintf(stderr, fmt, va);
 230	va_end(va);
 231	putc('\n', stderr);
 232}
 233
 234static void
 235pop(void)
 236{
 237	struct input *ip = input->prev;
 238
 239	if (input->type == FTFILE) {
 240		if (input->fp)
 241			fclose(input->fp);
 242		freeloc(&input->loc);
 243	}
 244	free(input->buf);
 245	free(input);
 246
 247	input = ip;
 248}
 249
 250static void
 251push(int type, ...)
 252{
 253	int line, len, pos;
 254	FILE *fp = NULL;
 255	char *buf, *s, *fname = NULL;
 256	va_list va;
 257	struct input *ip;
 258
 259	va_start(va, type);
 260	switch (type) {
 261	case FTFILE:
 262		fp = va_arg(va, FILE *);
 263		s = va_arg(va, char *);
 264		line = va_arg(va, int);
 265		fname = estrdup(s);
 266		buf = emalloc(BUFSIZ);
 267		pos = len = BUFSIZ;
 268		break;
 269	case FTEXPAN:
 270		s = va_arg(va, char *);
 271		buf = estrdup(s);
 272		line = pos = 0;
 273		len = strlen(s);
 274		break;
 275	}
 276	va_end(va);
 277
 278	ip = emalloc(sizeof(*ip));
 279	ip->siz = len;
 280	ip->buf = buf;
 281	ip->type = type;
 282	ip->fp = fp;
 283	ip->loc.fname = fname;
 284	ip->loc.lineno = line;
 285	ip->pos = pos;
 286	ip->prev = input;
 287
 288	input = ip;
 289}
 290
 291static char *
 292trim(char *s)
 293{
 294	size_t len;
 295
 296	while (isspace(*s))
 297		s++;
 298
 299	for (len = strlen(s); len > 0 && isspace(s[len-1]); --len)
 300		s[len-1] = '\0';
 301
 302	return s;
 303}
 304
 305static void
 306include(char *s)
 307{
 308	FILE *fp;
 309	char *fil, *t;
 310
 311	s = trim(s);
 312	fil = expandstring(s, NULL, getloc());
 313
 314	t = trim(fil);
 315	if (strlen(t) != 0) {
 316		debug("including '%s'", t);
 317		if ((fp = fopen(t, "r")) == NULL)
 318			error("opening %s:%s", t, strerror(errno));
 319		push(FTFILE, fp, t, 0);
 320	}
 321
 322	free(fil);
 323}
 324
 325static char *
 326nextline(void)
 327{
 328	int c;
 329	FILE *fp;
 330	char *s, *lim;
 331
 332	assert(input->type == FTFILE);
 333
 334repeat:
 335	fp = input->fp;
 336	if (!fp || feof(fp))
 337		return NULL;
 338
 339	lim = &input->buf[input->siz];
 340	for (s = input->buf; s < lim; *s++ = c) {
 341		c = getc(fp);
 342		if (c == '\n' || c == EOF) {
 343			input->loc.lineno++;
 344			*s++ = '\n';
 345			break;
 346		}
 347		if (c > UCHAR_MAX || c < 0)
 348			error("invalid character '%c' (%d)", c, c);
 349	}
 350
 351
 352	if (s == lim)
 353		error("too long line");
 354	if (ferror(fp))
 355		error(strerror(errno));
 356	*s = '\0';
 357
 358	if (!strcmp(input->buf, ""))
 359		goto repeat;
 360
 361	if (!strncmp(input->buf, "include", 7) && isblank(input->buf[7])) {
 362		input->pos = input->siz;
 363		include(input->buf+7);
 364		goto repeat;
 365	}
 366
 367	input->pos = 0;
 368
 369
 370	return input->buf;
 371}
 372
 373static int
 374empty(struct input *ip)
 375{
 376	return ip->pos == ip->siz || ip->buf[ip->pos] == '\0';
 377}
 378
 379static int
 380moreinput(void)
 381{
 382	while (input) {
 383		if (!empty(input))
 384			break;
 385
 386		switch (input->type) {
 387		case FTEXPAN:
 388			pop();
 389			break;
 390		case FTFILE:
 391			if (!nextline())
 392				pop();
 393			break;
 394		}
 395	}
 396
 397	return input != NULL;
 398}
 399
 400static int
 401nextc(void)
 402{
 403	if (!moreinput())
 404		return EOF;
 405
 406	return input->buf[input->pos++];
 407}
 408
 409/*
 410 * This function only can be called after a call to nextc
 411 * that didn't return EOF. It can return '\0', but as
 412 * it is used only to check against '$' then it is not
 413 * a problem.
 414 */
 415static int
 416ahead(void)
 417{
 418	return input->buf[input->pos];
 419}
 420
 421static int
 422back(int c)
 423{
 424	if (c == EOF)
 425		return c;
 426	assert(input->pos > 0);
 427	return input->buf[--input->pos] = c;
 428}
 429
 430static void
 431comment(void)
 432{
 433	int c;
 434
 435	while ((c = nextc()) != EOF && c != '\n') {
 436		if (c == '\\' && nextc() == EOF)
 437			break;
 438	}
 439}
 440
 441static void
 442skipspaces(void)
 443{
 444	int c;
 445
 446	for (c = nextc(); c == ' ' || c == '\t'; c = nextc())
 447		;
 448	back(c);
 449}
 450
 451static int
 452validchar(int c)
 453{
 454	if (c == EOF)
 455		return 0;
 456	return c == '.' || c == '/' || c == '_' || c == '-' || isalnum(c);
 457}
 458
 459static char *
 460expandmacro(char *name)
 461{
 462	char *s;
 463
 464	s = expandstring(getmacro(name), NULL, getloc());
 465	debug("macro %s expanded to '%s'", name, s);
 466
 467	return s;
 468}
 469
 470static void
 471replace(char *line, char *repl, char *to)
 472{
 473	int siz, at, len, replsiz, tosiz, pos;
 474	char *oline, *cur, *buf;
 475
 476	debug("replacing '%s', with '%s' to '%s'", line, repl, to);
 477	oline = line;
 478	tosiz = strlen(to);
 479	replsiz = strlen(repl);
 480
 481	buf = NULL;
 482	for (pos = 0; *line; pos += siz) {
 483		cur = NULL;
 484		siz = 0;
 485
 486		for (siz = 0; *line == ' ' || *line == '\t'; ++siz) {
 487			cur = erealloc(cur, siz+1);
 488			cur[siz] = *line++;
 489		}
 490
 491		len = strcspn(line, " \t");
 492		at = len - replsiz;
 493		if (at < 0 || memcmp(line + at, repl, replsiz)) {
 494			cur = erealloc(cur, siz + len);
 495			memcpy(cur + siz, line, len);
 496			siz += len;
 497		} else {
 498			cur = erealloc(cur, siz + at + tosiz);
 499			memcpy(cur + siz, line, at);
 500			memcpy(cur + siz + at, to, tosiz);
 501			siz += at + tosiz;
 502		}
 503
 504		line += len;
 505		buf = erealloc(buf, pos + siz);
 506		memcpy(buf + pos, cur, siz);
 507		free(cur);
 508	}
 509
 510	if (pos > 0) {
 511		buf = erealloc(buf, pos + 1);
 512		buf[pos] = '\0';
 513		debug("\treplace '%s' with '%s'", oline, buf);
 514		push(FTEXPAN, buf);
 515	}
 516
 517	free(buf);
 518}
 519
 520static void
 521expandsimple(Target *tp)
 522{
 523	char *s;
 524	Target **p;
 525	int len, c;
 526
 527	switch (c = nextc()) {
 528	case '@':
 529		if (!tp || !tp->target)
 530			return;
 531		push(FTEXPAN, tp->target);
 532		break;
 533	case '<':
 534		if (!tp || !tp->req)
 535			return;
 536		push(FTEXPAN, tp->req);
 537		break;
 538	case '*':
 539		if (!tp || !tp->target)
 540			return;
 541		s = strrchr(tp->target, '.');
 542		if (!s) {
 543			push(FTEXPAN, tp->target);
 544			return;
 545		}
 546
 547		len = s - tp->target;
 548		s = emalloc(len+1);
 549		memcpy(s, tp->target, len);
 550		s[len] = '\0';
 551		push(FTEXPAN, s);
 552		free(s);
 553		break;
 554	case '?':
 555		if (!tp)
 556			return;
 557
 558		if (tp->req && stamp(tp->req) > tp->stamp) {
 559			push(FTEXPAN, " ");
 560			push(FTEXPAN, tp->req);
 561		}
 562
 563		for (p = tp->deps; p && *p; ++p) {
 564			if (stamp((*p)->name) > tp->stamp) {
 565				push(FTEXPAN, " ");
 566				push(FTEXPAN, (*p)->name);
 567			}
 568		}
 569		break;
 570	default:
 571		token[0] = c;
 572		token[1] = '\0';
 573		s = expandmacro(token);
 574		push(FTEXPAN, s);
 575		free(s);
 576		break;
 577	}
 578}
 579
 580static int
 581internal(int ch)
 582{
 583	switch (ch) {
 584	case '@':
 585	case '?':
 586	case '*':
 587	case '<':
 588		return 1;
 589	default:
 590		return 0;
 591	}
 592}
 593
 594static void
 595expansion(Target *tp)
 596{
 597	int delim, c, repli, toi, namei, st;
 598	char name[MAXTOKEN], repl[MAXREPL], to[MAXREPL];
 599	char *s, *erepl;
 600
 601	c = nextc();
 602	if (c == '(')
 603		delim = ')';
 604	else if (c == '{')
 605		delim = '}';
 606	else
 607		delim = 0;
 608
 609	if (!delim) {
 610		back(c);
 611		expandsimple(tp);
 612		return;
 613	}
 614
 615	s = NULL;
 616	namei = repli = toi = 0;
 617	st = STBEGIN;
 618
 619	while (st != STEND && (c = nextc()) != EOF) {
 620		switch (st) {
 621		case STBEGIN:
 622			if (c == ':') {
 623				st = STREPLACE;
 624				name[namei] = '\0';
 625				s = expandmacro(name);
 626				break;
 627			}
 628			if (c == delim) {
 629				name[namei] = '\0';
 630				s = expandmacro(name);
 631				goto no_replace;
 632			}
 633			if (namei == MAXTOKEN-1)
 634				error("expansion text too long");
 635
 636			if (namei == 0 && internal(c)) {
 637				name[namei++] = '$';
 638				name[namei++] = c;
 639				name[namei] = '\0';
 640				st = STINTERNAL;
 641				s = expandstring(name, tp, getloc());
 642				break;
 643			}
 644
 645			if (!validchar(c))
 646				error("invalid macro name in expansion");
 647			name[namei++] = c;
 648			break;
 649		case STINTERNAL:
 650			if (c == delim)
 651				goto no_replace;
 652			if (c != ':')
 653				error("invalid internal macro in expansion");
 654			st = STREPLACE;
 655			break;
 656		case STREPLACE:
 657			if (c == '=') {
 658				st = STTO;
 659				break;
 660			}
 661			if (c == delim)
 662				error("invalid replacement pattern in expansion");
 663			if (repli == MAXREPL-1)
 664				error("macro replacement too big");
 665			repl[repli++] = c;
 666			break;
 667		case STTO:
 668			if (c == delim) {
 669				st = STEND;
 670				break;
 671			}
 672
 673			if (toi == MAXREPL-1)
 674				error("macro substiturion too big");
 675			to[toi++] = c;
 676			break;
 677		}
 678	}
 679
 680	if (c == EOF)
 681		error("found eof while parsing expansion");
 682
 683	repl[repli] = '\0';
 684	to[toi] = '\0';
 685
 686	erepl = expandstring(repl, tp, getloc());
 687	replace(s, erepl, to);
 688
 689	free(erepl);
 690	free(s);
 691	return;
 692
 693no_replace:
 694	push(FTEXPAN, s);
 695	free(s);
 696}
 697
 698/*
 699 * Horrible hack to do string expansion.
 700 * We cannot use normal push and nextc because that
 701 * would consume characters of the current file too.
 702 * For that reason it cleans the input and it recovers
 703 * it later.
 704 */
 705char *
 706expandstring(char *line, Target *tp, struct loc *loc)
 707{
 708	int c, n;
 709	char *s;
 710	struct input *ip = input;
 711
 712	input = NULL;
 713	push(FTFILE, NULL, loc->fname, loc->lineno);
 714	push(FTEXPAN, line);
 715
 716	n = 0;
 717	s = NULL;
 718	while ((c = nextc()) != EOF) {
 719		if (c != '$') {
 720			s = erealloc(s, ++n);
 721			s[n-1] = c;
 722			continue;
 723		}
 724
 725		if ((c = nextc()) == '$') {
 726			s = erealloc(s, n += 2);
 727			s[n-2] = '$';
 728			s[n-1] = '$';
 729		} else {
 730			back(c);
 731			expansion(tp);
 732		}
 733	}
 734
 735	s = erealloc(s, n+1);
 736	s[n] = '\0';
 737	input = ip;
 738
 739	return s;
 740}
 741
 742static int
 743item(void)
 744{
 745	int c;
 746	char *s;
 747	char buf[MAXTOKEN];
 748
 749	for (s = buf; s < &buf[MAXTOKEN] - 1; ) {
 750		c = nextc();
 751		if (c == '$' && ahead() != '$')
 752			expansion(NULL);
 753		else if (validchar(c))
 754			*s++ = c;
 755		else
 756			break;
 757	}
 758	back(c);
 759
 760	if (s >= &buf[MAXTOKEN] - 1)
 761		error("token too long");
 762	if (s == buf)
 763		error("invalid empty token");
 764	*s++ = '\0';
 765	memcpy(token, buf, s - buf);
 766
 767	return ITEM;
 768}
 769
 770static int
 771next(void)
 772{
 773	int c;
 774
 775repeat:
 776	/*
 777	 * It is better to avoid skipspaces() here, because
 778	 * it can generate the need for 2 calls to back(),
 779	 * and we need the character anyway.
 780	 */
 781	c = nextc();
 782	if (c == ' ' || c == '\t')
 783		goto repeat;
 784
 785	if (c == '\\') {
 786		if ((c = nextc()) == '\n')
 787			goto repeat;
 788		back(c);
 789		c = '\\';
 790	}
 791
 792	switch (c) {
 793	case EOF:
 794		strcpy(token, "<EOF>");
 795		tok = EOF;
 796		break;
 797	case '$':
 798		if ((c = nextc()) == '$')
 799			goto single;
 800		back(c);
 801		expansion(NULL);
 802		goto repeat;
 803	case '#':
 804		comment();
 805		c = '\n';
 806		/* fallthrough */
 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
 827static char *
 828readmacrodef(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
 862static struct action
 863readcmd(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
 899static void
 900rule(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
 957static void
 958assign(char *macros[], int where, 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, where, NOEXPORT);
 968	free(defs);
 969}
 970
 971void
 972parseinput(int where)
 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, where, 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
1009int
1010parse(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(MAKEFILE);
1024
1025	return 1;
1026}
1027
1028void
1029inject(char *s)
1030{
1031	push(FTFILE, NULL, "<internal>", 0);
1032	push(FTEXPAN, s);
1033	parseinput(INTERNAL);
1034}