Blob


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