xref: /plan9/sys/src/cmd/mk/parse.c (revision 219b2ee8daee37f4aad58d63f21287faa8e4ffdc)
1 #include	"mk.h"
2 
3 char *infile;
4 int inline;
5 static int rhead(char *, Word **, Word **, int *, char **);
6 static char *rbody(Biobuf*);
7 extern Word *target1;
8 
9 void
10 parse(char *f, int fd, int varoverride, int ruleoverride)
11 {
12 	int hline;
13 	char *body;
14 	Word *head, *tail;
15 	int attr, set;
16 	char *prog, *inc;
17 	int newfd;
18 	Biobuf in;
19 	Bufblock *buf;
20 
21 	if(fd < 0){
22 		perror(f);
23 		Exit();
24 	}
25 	ipush();
26 	infile = strdup(f);
27 	inline = 1;
28 	Binit(&in, fd, OREAD);
29 	buf = newbuf();
30 	inc = 0;
31 	while(assline(&in, buf)){
32 		hline = inline;
33 		switch(rhead(buf->start, &head, &tail, &attr, &prog))
34 		{
35 		case '<':
36 			if((tail == 0) || ((inc = wtos(tail)) == 0)){
37 				SYNERR(-1);
38 				fprint(2, "missing include file name\n");
39 				Exit();
40 			}
41 			if((newfd = open(inc, 0)) < 0){
42 				fprint(2, "warning: skipping missing include file: ");
43 				perror(inc);
44 			} else
45 				parse(inc, newfd, 0, 1);
46 			break;
47 		case ':':
48 			body = rbody(&in);
49 			addrules(head, tail, body, attr, hline, ruleoverride, prog);
50 			break;
51 		case '=':
52 			if(head->next){
53 				SYNERR(-1);
54 				fprint(2, "multiple vars on left side of assignment\n");
55 				Exit();
56 			}
57 			if(symlook(head->s, S_OVERRIDE, (char *)0)){
58 				set = varoverride;
59 				symdel(head->s, S_OVERRIDE);
60 			} else {
61 				set = 1;
62 				if(varoverride)
63 					symlook(head->s, S_OVERRIDE, "");
64 			}
65 			if(set){
66 /*
67 char *cp;
68 dumpw("tail", tail);
69 cp = wtos(tail); print("assign %s to %s\n", head->s, cp); free(cp);
70 */
71 				setvar(head->s, (char *) tail);
72 				symlook(head->s, S_WESET, "");
73 			}
74 			if(attr)
75 				symlook(head->s, S_NOEXPORT, "");
76 			break;
77 		default:
78 			SYNERR(hline);
79 			fprint(2, "expected one of :<=\n");
80 			Exit();
81 			break;
82 		}
83 	}
84 	close(fd);
85 	freebuf(buf);
86 	ipop();
87 }
88 
89 void
90 addrules(Word *head, Word *tail, char *body, int attr, int hline, int override, char *prog)
91 {
92 	Word *w;
93 
94 	assert("addrules args", head && body);
95 	if((target1 == 0) && !(attr&REGEXP))
96 		frule(head);
97 	for(w = head; w; w = w->next)
98 		addrule(w->s, tail, body, head, attr, hline, override, prog);
99 }
100 
101 static int
102 rhead(char *line, Word **h, Word **t, int *attr, char **prog)
103 {
104 	char *p;
105 	char *pp;
106 	int sep;
107 	Rune r;
108 	int n;
109 	Word *w;
110 
111 	p = charin(line,":=<");
112 	if(p == 0)
113 		return('?');
114 	sep = *p;
115 	*p++ = 0;
116 	*attr = 0;
117 	*prog = 0;
118 /*print("SEP: %c\n", sep);*/
119 	if(sep == '='){
120 		pp = charin(p, "'= \t");
121 		if (pp && *pp == '=') {
122 			while (p != pp) {
123 				n = chartorune(&r, p);
124 				switch(r)
125 				{
126 				default:
127 					SYNERR(-1);
128 					fprint(2, "unknown attribute '%c'\n",*p);
129 					Exit();
130 				case 'U':
131 					*attr = 1;
132 					break;
133 				}
134 				p += n;
135 			}
136 			p++;		/* skip trailing '=' */
137 		}
138 	}
139 	if((sep == ':') && *p && (*p != ' ') && (*p != '\t')){
140 		while (*p) {
141 			n = chartorune(&r, p);
142 			if (r == ':')
143 				break;
144 			p += n;
145 			switch(r)
146 			{
147 			default:
148 				SYNERR(-1);
149 				fprint(2, "unknown attribute '%c'\n", p[-1]);
150 				Exit();
151 			case '<':
152 				*attr |= RED;
153 				break;
154 			case 'D':
155 				*attr |= DEL;
156 				break;
157 			case 'E':
158 				*attr |= NOMINUSE;
159 				break;
160 			case 'n':
161 				*attr |= NOVIRT;
162 				break;
163 			case 'N':
164 				*attr |= NOREC;
165 				break;
166 			case 'P':
167 				pp = charin(p, ":");
168 				if (pp == 0 || *pp == 0)
169 					goto eos;
170 				*pp = 0;
171 				*prog = strdup(p);
172 				*pp = ':';
173 				p = pp;
174 				break;
175 			case 'Q':
176 				*attr |= QUIET;
177 				break;
178 			case 'R':
179 				*attr |= REGEXP;
180 				break;
181 			case 'U':
182 				*attr |= UPD;
183 				break;
184 			case 'V':
185 				*attr |= VIR;
186 				break;
187 			}
188 		}
189 		if (*p++ != ':') {
190 	eos:
191 			SYNERR(-1);
192 			fprint(2, "missing trailing :\n");
193 			Exit();
194 		}
195 	}
196 	*h = w = stow(line);
197 	if(!*w->s) {
198 		if (sep != '<') {
199 			SYNERR(inline-1);
200 			fprint(2, "no var on left side of assignment/rule\n");
201 			Exit();
202 		}
203 	}
204 	*t = stow(p);
205 	return(sep);
206 }
207 
208 static char *
209 rbody(Biobuf *in)
210 {
211 	Bufblock *buf;
212 	int r, lastr;
213 	char *p;
214 
215 	lastr = '\n';
216 	buf = newbuf();
217 	for(;;){
218 		r = Bgetrune(in);
219 		if (r < 0)
220 			break;
221 		if (lastr == '\n') {
222 			if (r == '#')
223 				rinsert(buf, r);
224 			else if (r != ' ' && r != '\t') {
225 				Bungetrune(in);
226 				break;
227 			}
228 		} else
229 			rinsert(buf, r);
230 		lastr = r;
231 		if (r == '\n')
232 			inline++;
233 	}
234 	insert(buf, 0);
235 	p = strdup(buf->start);
236 	freebuf(buf);
237 	return p;
238 }
239 
240 struct input
241 {
242 	char *file;
243 	int line;
244 	struct input *next;
245 };
246 static struct input *inputs = 0;
247 
248 void
249 ipush(void)
250 {
251 	struct input *in, *me;
252 
253 	me = (struct input *)Malloc(sizeof(*me));
254 	me->file = infile;
255 	me->line = inline;
256 	me->next = 0;
257 	if(inputs == 0)
258 		inputs = me;
259 	else {
260 		for(in = inputs; in->next; )
261 			in = in->next;
262 		in->next = me;
263 	}
264 }
265 
266 void
267 ipop(void)
268 {
269 	struct input *in, *me;
270 
271 	assert("pop input list", inputs != 0);
272 	if(inputs->next == 0){
273 		me = inputs;
274 		inputs = 0;
275 	} else {
276 		for(in = inputs; in->next->next; )
277 			in = in->next;
278 		me = in->next;
279 		in->next = 0;
280 	}
281 	infile = me->file;
282 	inline = me->line;
283 	free((char *)me);
284 }
285