xref: /plan9/sys/src/cmd/mk/parse.c (revision 219b2ee8daee37f4aad58d63f21287faa8e4ffdc)
13e12c5d1SDavid du Colombier #include	"mk.h"
23e12c5d1SDavid du Colombier 
33e12c5d1SDavid du Colombier char *infile;
43e12c5d1SDavid du Colombier int inline;
53e12c5d1SDavid du Colombier static int rhead(char *, Word **, Word **, int *, char **);
63e12c5d1SDavid du Colombier static char *rbody(Biobuf*);
73e12c5d1SDavid du Colombier extern Word *target1;
83e12c5d1SDavid du Colombier 
93e12c5d1SDavid du Colombier void
103e12c5d1SDavid du Colombier parse(char *f, int fd, int varoverride, int ruleoverride)
113e12c5d1SDavid du Colombier {
123e12c5d1SDavid du Colombier 	int hline;
133e12c5d1SDavid du Colombier 	char *body;
143e12c5d1SDavid du Colombier 	Word *head, *tail;
153e12c5d1SDavid du Colombier 	int attr, set;
163e12c5d1SDavid du Colombier 	char *prog, *inc;
17*219b2ee8SDavid du Colombier 	int newfd;
183e12c5d1SDavid du Colombier 	Biobuf in;
193e12c5d1SDavid du Colombier 	Bufblock *buf;
203e12c5d1SDavid du Colombier 
213e12c5d1SDavid du Colombier 	if(fd < 0){
223e12c5d1SDavid du Colombier 		perror(f);
233e12c5d1SDavid du Colombier 		Exit();
243e12c5d1SDavid du Colombier 	}
253e12c5d1SDavid du Colombier 	ipush();
263e12c5d1SDavid du Colombier 	infile = strdup(f);
273e12c5d1SDavid du Colombier 	inline = 1;
283e12c5d1SDavid du Colombier 	Binit(&in, fd, OREAD);
293e12c5d1SDavid du Colombier 	buf = newbuf();
303e12c5d1SDavid du Colombier 	inc = 0;
313e12c5d1SDavid du Colombier 	while(assline(&in, buf)){
323e12c5d1SDavid du Colombier 		hline = inline;
333e12c5d1SDavid du Colombier 		switch(rhead(buf->start, &head, &tail, &attr, &prog))
343e12c5d1SDavid du Colombier 		{
353e12c5d1SDavid du Colombier 		case '<':
363e12c5d1SDavid du Colombier 			if((tail == 0) || ((inc = wtos(tail)) == 0)){
373e12c5d1SDavid du Colombier 				SYNERR(-1);
383e12c5d1SDavid du Colombier 				fprint(2, "missing include file name\n");
393e12c5d1SDavid du Colombier 				Exit();
403e12c5d1SDavid du Colombier 			}
41*219b2ee8SDavid du Colombier 			if((newfd = open(inc, 0)) < 0){
42*219b2ee8SDavid du Colombier 				fprint(2, "warning: skipping missing include file: ");
43*219b2ee8SDavid du Colombier 				perror(inc);
44*219b2ee8SDavid du Colombier 			} else
45*219b2ee8SDavid du Colombier 				parse(inc, newfd, 0, 1);
463e12c5d1SDavid du Colombier 			break;
473e12c5d1SDavid du Colombier 		case ':':
483e12c5d1SDavid du Colombier 			body = rbody(&in);
493e12c5d1SDavid du Colombier 			addrules(head, tail, body, attr, hline, ruleoverride, prog);
503e12c5d1SDavid du Colombier 			break;
513e12c5d1SDavid du Colombier 		case '=':
523e12c5d1SDavid du Colombier 			if(head->next){
533e12c5d1SDavid du Colombier 				SYNERR(-1);
543e12c5d1SDavid du Colombier 				fprint(2, "multiple vars on left side of assignment\n");
553e12c5d1SDavid du Colombier 				Exit();
563e12c5d1SDavid du Colombier 			}
573e12c5d1SDavid du Colombier 			if(symlook(head->s, S_OVERRIDE, (char *)0)){
583e12c5d1SDavid du Colombier 				set = varoverride;
593e12c5d1SDavid du Colombier 				symdel(head->s, S_OVERRIDE);
603e12c5d1SDavid du Colombier 			} else {
613e12c5d1SDavid du Colombier 				set = 1;
623e12c5d1SDavid du Colombier 				if(varoverride)
633e12c5d1SDavid du Colombier 					symlook(head->s, S_OVERRIDE, "");
643e12c5d1SDavid du Colombier 			}
653e12c5d1SDavid du Colombier 			if(set){
663e12c5d1SDavid du Colombier /*
673e12c5d1SDavid du Colombier char *cp;
683e12c5d1SDavid du Colombier dumpw("tail", tail);
693e12c5d1SDavid du Colombier cp = wtos(tail); print("assign %s to %s\n", head->s, cp); free(cp);
703e12c5d1SDavid du Colombier */
713e12c5d1SDavid du Colombier 				setvar(head->s, (char *) tail);
723e12c5d1SDavid du Colombier 				symlook(head->s, S_WESET, "");
733e12c5d1SDavid du Colombier 			}
743e12c5d1SDavid du Colombier 			if(attr)
753e12c5d1SDavid du Colombier 				symlook(head->s, S_NOEXPORT, "");
763e12c5d1SDavid du Colombier 			break;
773e12c5d1SDavid du Colombier 		default:
783e12c5d1SDavid du Colombier 			SYNERR(hline);
793e12c5d1SDavid du Colombier 			fprint(2, "expected one of :<=\n");
803e12c5d1SDavid du Colombier 			Exit();
813e12c5d1SDavid du Colombier 			break;
823e12c5d1SDavid du Colombier 		}
833e12c5d1SDavid du Colombier 	}
843e12c5d1SDavid du Colombier 	close(fd);
853e12c5d1SDavid du Colombier 	freebuf(buf);
863e12c5d1SDavid du Colombier 	ipop();
873e12c5d1SDavid du Colombier }
883e12c5d1SDavid du Colombier 
893e12c5d1SDavid du Colombier void
903e12c5d1SDavid du Colombier addrules(Word *head, Word *tail, char *body, int attr, int hline, int override, char *prog)
913e12c5d1SDavid du Colombier {
923e12c5d1SDavid du Colombier 	Word *w;
933e12c5d1SDavid du Colombier 
943e12c5d1SDavid du Colombier 	assert("addrules args", head && body);
953e12c5d1SDavid du Colombier 	if((target1 == 0) && !(attr&REGEXP))
963e12c5d1SDavid du Colombier 		frule(head);
973e12c5d1SDavid du Colombier 	for(w = head; w; w = w->next)
983e12c5d1SDavid du Colombier 		addrule(w->s, tail, body, head, attr, hline, override, prog);
993e12c5d1SDavid du Colombier }
1003e12c5d1SDavid du Colombier 
1013e12c5d1SDavid du Colombier static int
1023e12c5d1SDavid du Colombier rhead(char *line, Word **h, Word **t, int *attr, char **prog)
1033e12c5d1SDavid du Colombier {
1043e12c5d1SDavid du Colombier 	char *p;
1053e12c5d1SDavid du Colombier 	char *pp;
1063e12c5d1SDavid du Colombier 	int sep;
1073e12c5d1SDavid du Colombier 	Rune r;
1083e12c5d1SDavid du Colombier 	int n;
1093e12c5d1SDavid du Colombier 	Word *w;
1103e12c5d1SDavid du Colombier 
1113e12c5d1SDavid du Colombier 	p = charin(line,":=<");
1123e12c5d1SDavid du Colombier 	if(p == 0)
1133e12c5d1SDavid du Colombier 		return('?');
1143e12c5d1SDavid du Colombier 	sep = *p;
1153e12c5d1SDavid du Colombier 	*p++ = 0;
1163e12c5d1SDavid du Colombier 	*attr = 0;
1173e12c5d1SDavid du Colombier 	*prog = 0;
1183e12c5d1SDavid du Colombier /*print("SEP: %c\n", sep);*/
1193e12c5d1SDavid du Colombier 	if(sep == '='){
120*219b2ee8SDavid du Colombier 		pp = charin(p, "'= \t");
121*219b2ee8SDavid du Colombier 		if (pp && *pp == '=') {
1223e12c5d1SDavid du Colombier 			while (p != pp) {
1233e12c5d1SDavid du Colombier 				n = chartorune(&r, p);
1243e12c5d1SDavid du Colombier 				switch(r)
1253e12c5d1SDavid du Colombier 				{
1263e12c5d1SDavid du Colombier 				default:
1273e12c5d1SDavid du Colombier 					SYNERR(-1);
1283e12c5d1SDavid du Colombier 					fprint(2, "unknown attribute '%c'\n",*p);
1293e12c5d1SDavid du Colombier 					Exit();
1303e12c5d1SDavid du Colombier 				case 'U':
1313e12c5d1SDavid du Colombier 					*attr = 1;
1323e12c5d1SDavid du Colombier 					break;
1333e12c5d1SDavid du Colombier 				}
1343e12c5d1SDavid du Colombier 				p += n;
1353e12c5d1SDavid du Colombier 			}
1363e12c5d1SDavid du Colombier 			p++;		/* skip trailing '=' */
1373e12c5d1SDavid du Colombier 		}
1383e12c5d1SDavid du Colombier 	}
1393e12c5d1SDavid du Colombier 	if((sep == ':') && *p && (*p != ' ') && (*p != '\t')){
1403e12c5d1SDavid du Colombier 		while (*p) {
1413e12c5d1SDavid du Colombier 			n = chartorune(&r, p);
1423e12c5d1SDavid du Colombier 			if (r == ':')
1433e12c5d1SDavid du Colombier 				break;
1443e12c5d1SDavid du Colombier 			p += n;
1453e12c5d1SDavid du Colombier 			switch(r)
1463e12c5d1SDavid du Colombier 			{
1473e12c5d1SDavid du Colombier 			default:
1483e12c5d1SDavid du Colombier 				SYNERR(-1);
1493e12c5d1SDavid du Colombier 				fprint(2, "unknown attribute '%c'\n", p[-1]);
1503e12c5d1SDavid du Colombier 				Exit();
1513e12c5d1SDavid du Colombier 			case '<':
1523e12c5d1SDavid du Colombier 				*attr |= RED;
1533e12c5d1SDavid du Colombier 				break;
1543e12c5d1SDavid du Colombier 			case 'D':
1553e12c5d1SDavid du Colombier 				*attr |= DEL;
1563e12c5d1SDavid du Colombier 				break;
1573e12c5d1SDavid du Colombier 			case 'E':
1583e12c5d1SDavid du Colombier 				*attr |= NOMINUSE;
1593e12c5d1SDavid du Colombier 				break;
1603e12c5d1SDavid du Colombier 			case 'n':
1613e12c5d1SDavid du Colombier 				*attr |= NOVIRT;
1623e12c5d1SDavid du Colombier 				break;
1633e12c5d1SDavid du Colombier 			case 'N':
1643e12c5d1SDavid du Colombier 				*attr |= NOREC;
1653e12c5d1SDavid du Colombier 				break;
1663e12c5d1SDavid du Colombier 			case 'P':
1673e12c5d1SDavid du Colombier 				pp = charin(p, ":");
1683e12c5d1SDavid du Colombier 				if (pp == 0 || *pp == 0)
1693e12c5d1SDavid du Colombier 					goto eos;
1703e12c5d1SDavid du Colombier 				*pp = 0;
1713e12c5d1SDavid du Colombier 				*prog = strdup(p);
1723e12c5d1SDavid du Colombier 				*pp = ':';
1733e12c5d1SDavid du Colombier 				p = pp;
1743e12c5d1SDavid du Colombier 				break;
1753e12c5d1SDavid du Colombier 			case 'Q':
1763e12c5d1SDavid du Colombier 				*attr |= QUIET;
1773e12c5d1SDavid du Colombier 				break;
1783e12c5d1SDavid du Colombier 			case 'R':
1793e12c5d1SDavid du Colombier 				*attr |= REGEXP;
1803e12c5d1SDavid du Colombier 				break;
1813e12c5d1SDavid du Colombier 			case 'U':
1823e12c5d1SDavid du Colombier 				*attr |= UPD;
1833e12c5d1SDavid du Colombier 				break;
1843e12c5d1SDavid du Colombier 			case 'V':
1853e12c5d1SDavid du Colombier 				*attr |= VIR;
1863e12c5d1SDavid du Colombier 				break;
1873e12c5d1SDavid du Colombier 			}
1883e12c5d1SDavid du Colombier 		}
1893e12c5d1SDavid du Colombier 		if (*p++ != ':') {
1903e12c5d1SDavid du Colombier 	eos:
1913e12c5d1SDavid du Colombier 			SYNERR(-1);
1923e12c5d1SDavid du Colombier 			fprint(2, "missing trailing :\n");
1933e12c5d1SDavid du Colombier 			Exit();
1943e12c5d1SDavid du Colombier 		}
1953e12c5d1SDavid du Colombier 	}
1963e12c5d1SDavid du Colombier 	*h = w = stow(line);
1973e12c5d1SDavid du Colombier 	if(!*w->s) {
1983e12c5d1SDavid du Colombier 		if (sep != '<') {
1993e12c5d1SDavid du Colombier 			SYNERR(inline-1);
2003e12c5d1SDavid du Colombier 			fprint(2, "no var on left side of assignment/rule\n");
2013e12c5d1SDavid du Colombier 			Exit();
2023e12c5d1SDavid du Colombier 		}
2033e12c5d1SDavid du Colombier 	}
2043e12c5d1SDavid du Colombier 	*t = stow(p);
2053e12c5d1SDavid du Colombier 	return(sep);
2063e12c5d1SDavid du Colombier }
2073e12c5d1SDavid du Colombier 
2083e12c5d1SDavid du Colombier static char *
2093e12c5d1SDavid du Colombier rbody(Biobuf *in)
2103e12c5d1SDavid du Colombier {
2113e12c5d1SDavid du Colombier 	Bufblock *buf;
2123e12c5d1SDavid du Colombier 	int r, lastr;
2133e12c5d1SDavid du Colombier 	char *p;
2143e12c5d1SDavid du Colombier 
2153e12c5d1SDavid du Colombier 	lastr = '\n';
2163e12c5d1SDavid du Colombier 	buf = newbuf();
2173e12c5d1SDavid du Colombier 	for(;;){
2183e12c5d1SDavid du Colombier 		r = Bgetrune(in);
2193e12c5d1SDavid du Colombier 		if (r < 0)
2203e12c5d1SDavid du Colombier 			break;
2213e12c5d1SDavid du Colombier 		if (lastr == '\n') {
2223e12c5d1SDavid du Colombier 			if (r == '#')
2233e12c5d1SDavid du Colombier 				rinsert(buf, r);
2243e12c5d1SDavid du Colombier 			else if (r != ' ' && r != '\t') {
2253e12c5d1SDavid du Colombier 				Bungetrune(in);
2263e12c5d1SDavid du Colombier 				break;
2273e12c5d1SDavid du Colombier 			}
2283e12c5d1SDavid du Colombier 		} else
2293e12c5d1SDavid du Colombier 			rinsert(buf, r);
2303e12c5d1SDavid du Colombier 		lastr = r;
2313e12c5d1SDavid du Colombier 		if (r == '\n')
2323e12c5d1SDavid du Colombier 			inline++;
2333e12c5d1SDavid du Colombier 	}
2343e12c5d1SDavid du Colombier 	insert(buf, 0);
2353e12c5d1SDavid du Colombier 	p = strdup(buf->start);
2363e12c5d1SDavid du Colombier 	freebuf(buf);
2373e12c5d1SDavid du Colombier 	return p;
2383e12c5d1SDavid du Colombier }
2393e12c5d1SDavid du Colombier 
2403e12c5d1SDavid du Colombier struct input
2413e12c5d1SDavid du Colombier {
2423e12c5d1SDavid du Colombier 	char *file;
2433e12c5d1SDavid du Colombier 	int line;
2443e12c5d1SDavid du Colombier 	struct input *next;
2453e12c5d1SDavid du Colombier };
2463e12c5d1SDavid du Colombier static struct input *inputs = 0;
2473e12c5d1SDavid du Colombier 
2483e12c5d1SDavid du Colombier void
2493e12c5d1SDavid du Colombier ipush(void)
2503e12c5d1SDavid du Colombier {
2513e12c5d1SDavid du Colombier 	struct input *in, *me;
2523e12c5d1SDavid du Colombier 
2533e12c5d1SDavid du Colombier 	me = (struct input *)Malloc(sizeof(*me));
2543e12c5d1SDavid du Colombier 	me->file = infile;
2553e12c5d1SDavid du Colombier 	me->line = inline;
2563e12c5d1SDavid du Colombier 	me->next = 0;
2573e12c5d1SDavid du Colombier 	if(inputs == 0)
2583e12c5d1SDavid du Colombier 		inputs = me;
2593e12c5d1SDavid du Colombier 	else {
2603e12c5d1SDavid du Colombier 		for(in = inputs; in->next; )
2613e12c5d1SDavid du Colombier 			in = in->next;
2623e12c5d1SDavid du Colombier 		in->next = me;
2633e12c5d1SDavid du Colombier 	}
2643e12c5d1SDavid du Colombier }
2653e12c5d1SDavid du Colombier 
2663e12c5d1SDavid du Colombier void
2673e12c5d1SDavid du Colombier ipop(void)
2683e12c5d1SDavid du Colombier {
2693e12c5d1SDavid du Colombier 	struct input *in, *me;
2703e12c5d1SDavid du Colombier 
2713e12c5d1SDavid du Colombier 	assert("pop input list", inputs != 0);
2723e12c5d1SDavid du Colombier 	if(inputs->next == 0){
2733e12c5d1SDavid du Colombier 		me = inputs;
2743e12c5d1SDavid du Colombier 		inputs = 0;
2753e12c5d1SDavid du Colombier 	} else {
2763e12c5d1SDavid du Colombier 		for(in = inputs; in->next->next; )
2773e12c5d1SDavid du Colombier 			in = in->next;
2783e12c5d1SDavid du Colombier 		me = in->next;
2793e12c5d1SDavid du Colombier 		in->next = 0;
2803e12c5d1SDavid du Colombier 	}
2813e12c5d1SDavid du Colombier 	infile = me->file;
2823e12c5d1SDavid du Colombier 	inline = me->line;
2833e12c5d1SDavid du Colombier 	free((char *)me);
2843e12c5d1SDavid du Colombier }
285