xref: /plan9/sys/src/cmd/mk/parse.c (revision 7dd7cddf99dd7472612f1413b4da293630e6b1bc)
13e12c5d1SDavid du Colombier #include	"mk.h"
23e12c5d1SDavid du Colombier 
33e12c5d1SDavid du Colombier char *infile;
4*7dd7cddfSDavid du Colombier int mkinline;
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
parse(char * f,int fd,int varoverride)10*7dd7cddfSDavid du Colombier parse(char *f, int fd, int varoverride)
113e12c5d1SDavid du Colombier {
123e12c5d1SDavid du Colombier 	int hline;
133e12c5d1SDavid du Colombier 	char *body;
143e12c5d1SDavid du Colombier 	Word *head, *tail;
15*7dd7cddfSDavid du Colombier 	int attr, set, pid;
16*7dd7cddfSDavid du Colombier 	char *prog, *p;
17219b2ee8SDavid 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);
27*7dd7cddfSDavid du Colombier 	mkinline = 1;
283e12c5d1SDavid du Colombier 	Binit(&in, fd, OREAD);
293e12c5d1SDavid du Colombier 	buf = newbuf();
303e12c5d1SDavid du Colombier 	while(assline(&in, buf)){
31*7dd7cddfSDavid du Colombier 		hline = mkinline;
323e12c5d1SDavid du Colombier 		switch(rhead(buf->start, &head, &tail, &attr, &prog))
333e12c5d1SDavid du Colombier 		{
343e12c5d1SDavid du Colombier 		case '<':
35*7dd7cddfSDavid du Colombier 			p = wtos(tail, ' ');
36*7dd7cddfSDavid du Colombier 			if(*p == 0){
373e12c5d1SDavid du Colombier 				SYNERR(-1);
383e12c5d1SDavid du Colombier 				fprint(2, "missing include file name\n");
393e12c5d1SDavid du Colombier 				Exit();
403e12c5d1SDavid du Colombier 			}
41*7dd7cddfSDavid du Colombier 			newfd = open(p, OREAD);
42*7dd7cddfSDavid du Colombier 			if(newfd < 0){
43219b2ee8SDavid du Colombier 				fprint(2, "warning: skipping missing include file: ");
44*7dd7cddfSDavid du Colombier 				perror(p);
45219b2ee8SDavid du Colombier 			} else
46*7dd7cddfSDavid du Colombier 				parse(p, newfd, 0);
47*7dd7cddfSDavid du Colombier 			break;
48*7dd7cddfSDavid du Colombier 		case '|':
49*7dd7cddfSDavid du Colombier 			p = wtos(tail, ' ');
50*7dd7cddfSDavid du Colombier 			if(*p == 0){
51*7dd7cddfSDavid du Colombier 				SYNERR(-1);
52*7dd7cddfSDavid du Colombier 				fprint(2, "missing include program name\n");
53*7dd7cddfSDavid du Colombier 				Exit();
54*7dd7cddfSDavid du Colombier 			}
55*7dd7cddfSDavid du Colombier 			execinit();
56*7dd7cddfSDavid du Colombier 			pid=pipecmd(p, envy, &newfd);
57*7dd7cddfSDavid du Colombier 			if(newfd < 0){
58*7dd7cddfSDavid du Colombier 				fprint(2, "warning: skipping missing program file: ");
59*7dd7cddfSDavid du Colombier 				perror(p);
60*7dd7cddfSDavid du Colombier 			} else
61*7dd7cddfSDavid du Colombier 				parse(p, newfd, 0);
62*7dd7cddfSDavid du Colombier 			while(waitup(-3, &pid) >= 0)
63*7dd7cddfSDavid du Colombier 				;
64*7dd7cddfSDavid du Colombier 			if(pid != 0){
65*7dd7cddfSDavid du Colombier 				fprint(2, "bad include program status\n");
66*7dd7cddfSDavid du Colombier 				Exit();
67*7dd7cddfSDavid du Colombier 			}
683e12c5d1SDavid du Colombier 			break;
693e12c5d1SDavid du Colombier 		case ':':
703e12c5d1SDavid du Colombier 			body = rbody(&in);
71*7dd7cddfSDavid du Colombier 			addrules(head, tail, body, attr, hline, prog);
723e12c5d1SDavid du Colombier 			break;
733e12c5d1SDavid du Colombier 		case '=':
743e12c5d1SDavid du Colombier 			if(head->next){
753e12c5d1SDavid du Colombier 				SYNERR(-1);
763e12c5d1SDavid du Colombier 				fprint(2, "multiple vars on left side of assignment\n");
773e12c5d1SDavid du Colombier 				Exit();
783e12c5d1SDavid du Colombier 			}
79*7dd7cddfSDavid du Colombier 			if(symlook(head->s, S_OVERRIDE, 0)){
803e12c5d1SDavid du Colombier 				set = varoverride;
813e12c5d1SDavid du Colombier 			} else {
823e12c5d1SDavid du Colombier 				set = 1;
833e12c5d1SDavid du Colombier 				if(varoverride)
84*7dd7cddfSDavid du Colombier 					symlook(head->s, S_OVERRIDE, (void *)"");
853e12c5d1SDavid du Colombier 			}
863e12c5d1SDavid du Colombier 			if(set){
873e12c5d1SDavid du Colombier /*
883e12c5d1SDavid du Colombier char *cp;
893e12c5d1SDavid du Colombier dumpw("tail", tail);
90*7dd7cddfSDavid du Colombier cp = wtos(tail, ' '); print("assign %s to %s\n", head->s, cp); free(cp);
913e12c5d1SDavid du Colombier */
92*7dd7cddfSDavid du Colombier 				setvar(head->s, (void *) tail);
93*7dd7cddfSDavid du Colombier 				symlook(head->s, S_WESET, (void *)"");
943e12c5d1SDavid du Colombier 			}
953e12c5d1SDavid du Colombier 			if(attr)
96*7dd7cddfSDavid du Colombier 				symlook(head->s, S_NOEXPORT, (void *)"");
973e12c5d1SDavid du Colombier 			break;
983e12c5d1SDavid du Colombier 		default:
993e12c5d1SDavid du Colombier 			SYNERR(hline);
1003e12c5d1SDavid du Colombier 			fprint(2, "expected one of :<=\n");
1013e12c5d1SDavid du Colombier 			Exit();
1023e12c5d1SDavid du Colombier 			break;
1033e12c5d1SDavid du Colombier 		}
1043e12c5d1SDavid du Colombier 	}
1053e12c5d1SDavid du Colombier 	close(fd);
1063e12c5d1SDavid du Colombier 	freebuf(buf);
1073e12c5d1SDavid du Colombier 	ipop();
1083e12c5d1SDavid du Colombier }
1093e12c5d1SDavid du Colombier 
1103e12c5d1SDavid du Colombier void
addrules(Word * head,Word * tail,char * body,int attr,int hline,char * prog)111*7dd7cddfSDavid du Colombier addrules(Word *head, Word *tail, char *body, int attr, int hline, char *prog)
1123e12c5d1SDavid du Colombier {
1133e12c5d1SDavid du Colombier 	Word *w;
1143e12c5d1SDavid du Colombier 
115*7dd7cddfSDavid du Colombier 	assert(/*addrules args*/ head && body);
116*7dd7cddfSDavid du Colombier 		/* tuck away first non-meta rule as default target*/
117*7dd7cddfSDavid du Colombier 	if(target1 == 0 && !(attr&REGEXP)){
1183e12c5d1SDavid du Colombier 		for(w = head; w; w = w->next)
119*7dd7cddfSDavid du Colombier 			if(charin(w->s, "%&"))
120*7dd7cddfSDavid du Colombier 				break;
121*7dd7cddfSDavid du Colombier 		if(w == 0)
122*7dd7cddfSDavid du Colombier 			target1 = wdup(head);
123*7dd7cddfSDavid du Colombier 	}
124*7dd7cddfSDavid du Colombier 	for(w = head; w; w = w->next)
125*7dd7cddfSDavid du Colombier 		addrule(w->s, tail, body, head, attr, hline, prog);
1263e12c5d1SDavid du Colombier }
1273e12c5d1SDavid du Colombier 
1283e12c5d1SDavid du Colombier static int
rhead(char * line,Word ** h,Word ** t,int * attr,char ** prog)1293e12c5d1SDavid du Colombier rhead(char *line, Word **h, Word **t, int *attr, char **prog)
1303e12c5d1SDavid du Colombier {
1313e12c5d1SDavid du Colombier 	char *p;
1323e12c5d1SDavid du Colombier 	char *pp;
1333e12c5d1SDavid du Colombier 	int sep;
1343e12c5d1SDavid du Colombier 	Rune r;
1353e12c5d1SDavid du Colombier 	int n;
1363e12c5d1SDavid du Colombier 	Word *w;
1373e12c5d1SDavid du Colombier 
1383e12c5d1SDavid du Colombier 	p = charin(line,":=<");
1393e12c5d1SDavid du Colombier 	if(p == 0)
1403e12c5d1SDavid du Colombier 		return('?');
1413e12c5d1SDavid du Colombier 	sep = *p;
1423e12c5d1SDavid du Colombier 	*p++ = 0;
143*7dd7cddfSDavid du Colombier 	if(sep == '<' && *p == '|'){
144*7dd7cddfSDavid du Colombier 		sep = '|';
145*7dd7cddfSDavid du Colombier 		p++;
146*7dd7cddfSDavid du Colombier 	}
1473e12c5d1SDavid du Colombier 	*attr = 0;
1483e12c5d1SDavid du Colombier 	*prog = 0;
1493e12c5d1SDavid du Colombier 	if(sep == '='){
150*7dd7cddfSDavid du Colombier 		pp = charin(p, termchars);	/* termchars is shell-dependent */
151219b2ee8SDavid du Colombier 		if (pp && *pp == '=') {
1523e12c5d1SDavid du Colombier 			while (p != pp) {
1533e12c5d1SDavid du Colombier 				n = chartorune(&r, p);
1543e12c5d1SDavid du Colombier 				switch(r)
1553e12c5d1SDavid du Colombier 				{
1563e12c5d1SDavid du Colombier 				default:
1573e12c5d1SDavid du Colombier 					SYNERR(-1);
1583e12c5d1SDavid du Colombier 					fprint(2, "unknown attribute '%c'\n",*p);
1593e12c5d1SDavid du Colombier 					Exit();
1603e12c5d1SDavid du Colombier 				case 'U':
1613e12c5d1SDavid du Colombier 					*attr = 1;
1623e12c5d1SDavid du Colombier 					break;
1633e12c5d1SDavid du Colombier 				}
1643e12c5d1SDavid du Colombier 				p += n;
1653e12c5d1SDavid du Colombier 			}
1663e12c5d1SDavid du Colombier 			p++;		/* skip trailing '=' */
1673e12c5d1SDavid du Colombier 		}
1683e12c5d1SDavid du Colombier 	}
1693e12c5d1SDavid du Colombier 	if((sep == ':') && *p && (*p != ' ') && (*p != '\t')){
1703e12c5d1SDavid du Colombier 		while (*p) {
1713e12c5d1SDavid du Colombier 			n = chartorune(&r, p);
1723e12c5d1SDavid du Colombier 			if (r == ':')
1733e12c5d1SDavid du Colombier 				break;
1743e12c5d1SDavid du Colombier 			p += n;
1753e12c5d1SDavid du Colombier 			switch(r)
1763e12c5d1SDavid du Colombier 			{
1773e12c5d1SDavid du Colombier 			default:
1783e12c5d1SDavid du Colombier 				SYNERR(-1);
1793e12c5d1SDavid du Colombier 				fprint(2, "unknown attribute '%c'\n", p[-1]);
1803e12c5d1SDavid du Colombier 				Exit();
1813e12c5d1SDavid du Colombier 			case 'D':
1823e12c5d1SDavid du Colombier 				*attr |= DEL;
1833e12c5d1SDavid du Colombier 				break;
1843e12c5d1SDavid du Colombier 			case 'E':
1853e12c5d1SDavid du Colombier 				*attr |= NOMINUSE;
1863e12c5d1SDavid du Colombier 				break;
1873e12c5d1SDavid du Colombier 			case 'n':
1883e12c5d1SDavid du Colombier 				*attr |= NOVIRT;
1893e12c5d1SDavid du Colombier 				break;
1903e12c5d1SDavid du Colombier 			case 'N':
1913e12c5d1SDavid du Colombier 				*attr |= NOREC;
1923e12c5d1SDavid du Colombier 				break;
1933e12c5d1SDavid du Colombier 			case 'P':
194*7dd7cddfSDavid du Colombier 				pp = utfrune(p, ':');
1953e12c5d1SDavid du Colombier 				if (pp == 0 || *pp == 0)
1963e12c5d1SDavid du Colombier 					goto eos;
1973e12c5d1SDavid du Colombier 				*pp = 0;
1983e12c5d1SDavid du Colombier 				*prog = strdup(p);
1993e12c5d1SDavid du Colombier 				*pp = ':';
2003e12c5d1SDavid du Colombier 				p = pp;
2013e12c5d1SDavid du Colombier 				break;
2023e12c5d1SDavid du Colombier 			case 'Q':
2033e12c5d1SDavid du Colombier 				*attr |= QUIET;
2043e12c5d1SDavid du Colombier 				break;
2053e12c5d1SDavid du Colombier 			case 'R':
2063e12c5d1SDavid du Colombier 				*attr |= REGEXP;
2073e12c5d1SDavid du Colombier 				break;
2083e12c5d1SDavid du Colombier 			case 'U':
2093e12c5d1SDavid du Colombier 				*attr |= UPD;
2103e12c5d1SDavid du Colombier 				break;
2113e12c5d1SDavid du Colombier 			case 'V':
2123e12c5d1SDavid du Colombier 				*attr |= VIR;
2133e12c5d1SDavid du Colombier 				break;
2143e12c5d1SDavid du Colombier 			}
2153e12c5d1SDavid du Colombier 		}
2163e12c5d1SDavid du Colombier 		if (*p++ != ':') {
2173e12c5d1SDavid du Colombier 	eos:
2183e12c5d1SDavid du Colombier 			SYNERR(-1);
2193e12c5d1SDavid du Colombier 			fprint(2, "missing trailing :\n");
2203e12c5d1SDavid du Colombier 			Exit();
2213e12c5d1SDavid du Colombier 		}
2223e12c5d1SDavid du Colombier 	}
2233e12c5d1SDavid du Colombier 	*h = w = stow(line);
224*7dd7cddfSDavid du Colombier 	if(*w->s == 0 && sep != '<' && sep != '|') {
225*7dd7cddfSDavid du Colombier 		SYNERR(mkinline-1);
2263e12c5d1SDavid du Colombier 		fprint(2, "no var on left side of assignment/rule\n");
2273e12c5d1SDavid du Colombier 		Exit();
2283e12c5d1SDavid du Colombier 	}
2293e12c5d1SDavid du Colombier 	*t = stow(p);
2303e12c5d1SDavid du Colombier 	return(sep);
2313e12c5d1SDavid du Colombier }
2323e12c5d1SDavid du Colombier 
2333e12c5d1SDavid du Colombier static char *
rbody(Biobuf * in)2343e12c5d1SDavid du Colombier rbody(Biobuf *in)
2353e12c5d1SDavid du Colombier {
2363e12c5d1SDavid du Colombier 	Bufblock *buf;
2373e12c5d1SDavid du Colombier 	int r, lastr;
2383e12c5d1SDavid du Colombier 	char *p;
2393e12c5d1SDavid du Colombier 
2403e12c5d1SDavid du Colombier 	lastr = '\n';
2413e12c5d1SDavid du Colombier 	buf = newbuf();
2423e12c5d1SDavid du Colombier 	for(;;){
2433e12c5d1SDavid du Colombier 		r = Bgetrune(in);
2443e12c5d1SDavid du Colombier 		if (r < 0)
2453e12c5d1SDavid du Colombier 			break;
2463e12c5d1SDavid du Colombier 		if (lastr == '\n') {
2473e12c5d1SDavid du Colombier 			if (r == '#')
2483e12c5d1SDavid du Colombier 				rinsert(buf, r);
2493e12c5d1SDavid du Colombier 			else if (r != ' ' && r != '\t') {
2503e12c5d1SDavid du Colombier 				Bungetrune(in);
2513e12c5d1SDavid du Colombier 				break;
2523e12c5d1SDavid du Colombier 			}
2533e12c5d1SDavid du Colombier 		} else
2543e12c5d1SDavid du Colombier 			rinsert(buf, r);
2553e12c5d1SDavid du Colombier 		lastr = r;
2563e12c5d1SDavid du Colombier 		if (r == '\n')
257*7dd7cddfSDavid du Colombier 			mkinline++;
2583e12c5d1SDavid du Colombier 	}
2593e12c5d1SDavid du Colombier 	insert(buf, 0);
2603e12c5d1SDavid du Colombier 	p = strdup(buf->start);
2613e12c5d1SDavid du Colombier 	freebuf(buf);
2623e12c5d1SDavid du Colombier 	return p;
2633e12c5d1SDavid du Colombier }
2643e12c5d1SDavid du Colombier 
2653e12c5d1SDavid du Colombier struct input
2663e12c5d1SDavid du Colombier {
2673e12c5d1SDavid du Colombier 	char *file;
2683e12c5d1SDavid du Colombier 	int line;
2693e12c5d1SDavid du Colombier 	struct input *next;
2703e12c5d1SDavid du Colombier };
2713e12c5d1SDavid du Colombier static struct input *inputs = 0;
2723e12c5d1SDavid du Colombier 
2733e12c5d1SDavid du Colombier void
ipush(void)2743e12c5d1SDavid du Colombier ipush(void)
2753e12c5d1SDavid du Colombier {
2763e12c5d1SDavid du Colombier 	struct input *in, *me;
2773e12c5d1SDavid du Colombier 
2783e12c5d1SDavid du Colombier 	me = (struct input *)Malloc(sizeof(*me));
2793e12c5d1SDavid du Colombier 	me->file = infile;
280*7dd7cddfSDavid du Colombier 	me->line = mkinline;
2813e12c5d1SDavid du Colombier 	me->next = 0;
2823e12c5d1SDavid du Colombier 	if(inputs == 0)
2833e12c5d1SDavid du Colombier 		inputs = me;
2843e12c5d1SDavid du Colombier 	else {
2853e12c5d1SDavid du Colombier 		for(in = inputs; in->next; )
2863e12c5d1SDavid du Colombier 			in = in->next;
2873e12c5d1SDavid du Colombier 		in->next = me;
2883e12c5d1SDavid du Colombier 	}
2893e12c5d1SDavid du Colombier }
2903e12c5d1SDavid du Colombier 
2913e12c5d1SDavid du Colombier void
ipop(void)2923e12c5d1SDavid du Colombier ipop(void)
2933e12c5d1SDavid du Colombier {
2943e12c5d1SDavid du Colombier 	struct input *in, *me;
2953e12c5d1SDavid du Colombier 
296*7dd7cddfSDavid du Colombier 	assert(/*pop input list*/ inputs != 0);
2973e12c5d1SDavid du Colombier 	if(inputs->next == 0){
2983e12c5d1SDavid du Colombier 		me = inputs;
2993e12c5d1SDavid du Colombier 		inputs = 0;
3003e12c5d1SDavid du Colombier 	} else {
3013e12c5d1SDavid du Colombier 		for(in = inputs; in->next->next; )
3023e12c5d1SDavid du Colombier 			in = in->next;
3033e12c5d1SDavid du Colombier 		me = in->next;
3043e12c5d1SDavid du Colombier 		in->next = 0;
3053e12c5d1SDavid du Colombier 	}
3063e12c5d1SDavid du Colombier 	infile = me->file;
307*7dd7cddfSDavid du Colombier 	mkinline = me->line;
3083e12c5d1SDavid du Colombier 	free((char *)me);
3093e12c5d1SDavid du Colombier }
310