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;
20 char *err;
22 if(fd < 0){
23 fprint(2, "open %s: %r\n", f);
24 Exit();
25 }
26 pushshell();
27 ipush();
28 infile = strdup(f);
29 mkinline = 1;
30 Binit(&in, fd, OREAD);
31 buf = newbuf();
32 while(assline(&in, buf)){
33 hline = mkinline;
34 switch(rhead(buf->start, &head, &tail, &attr, &prog))
35 {
36 case '<':
37 p = wtos(tail, ' ');
38 if(*p == 0){
39 SYNERR(-1);
40 fprint(2, "missing include file name\n");
41 Exit();
42 }
43 newfd = open(p, OREAD);
44 if(newfd < 0){
45 fprint(2, "warning: skipping missing include file %s: %r\n", p);
46 } else
47 parse(p, newfd, 0);
48 break;
49 case '|':
50 p = wtos(tail, ' ');
51 if(*p == 0){
52 SYNERR(-1);
53 fprint(2, "missing include program name\n");
54 Exit();
55 }
56 execinit();
57 pid=pipecmd(p, envy, &newfd, shellt, shellcmd);
58 if(newfd < 0){
59 fprint(2, "warning: skipping missing program file %s: %r\n", p);
60 } else
61 parse(p, newfd, 0);
62 while(waitup(-3, &pid) >= 0)
63 ;
64 if(pid != 0){
65 fprint(2, "bad include program status\n");
66 Exit();
67 }
68 break;
69 case ':':
70 body = rbody(&in);
71 addrules(head, tail, body, attr, hline, prog);
72 break;
73 case '=':
74 if(head->next){
75 SYNERR(-1);
76 fprint(2, "multiple vars on left side of assignment\n");
77 Exit();
78 }
79 if(symlook(head->s, S_OVERRIDE, 0)){
80 set = varoverride;
81 } else {
82 set = 1;
83 if(varoverride)
84 symlook(head->s, S_OVERRIDE, (void *)"");
85 }
86 if(set){
87 /*
88 char *cp;
89 dumpw("tail", tail);
90 cp = wtos(tail, ' '); print("assign %s to %s\n", head->s, cp); free(cp);
91 */
92 setvar(head->s, (void *) tail);
93 symlook(head->s, S_WESET, (void *)"");
94 if(strcmp(head->s, "MKSHELL") == 0){
95 if((err = setshell(tail)) != nil){
96 SYNERR(hline);
97 fprint(2, "%s\n", err);
98 Exit();
99 break;
103 if(attr)
104 symlook(head->s, S_NOEXPORT, (void *)"");
105 break;
106 default:
107 SYNERR(hline);
108 fprint(2, "expected one of :<=\n");
109 Exit();
110 break;
113 close(fd);
114 freebuf(buf);
115 ipop();
116 popshell();
119 void
120 addrules(Word *head, Word *tail, char *body, int attr, int hline, char *prog)
122 Word *w;
124 assert("addrules args", head && body);
125 /* tuck away first non-meta rule as default target*/
126 if(target1 == 0 && !(attr&REGEXP)){
127 for(w = head; w; w = w->next)
128 if(shellt->charin(w->s, "%&"))
129 break;
130 if(w == 0)
131 target1 = wdup(head);
133 for(w = head; w; w = w->next)
134 addrule(w->s, tail, body, head, attr, hline, prog);
137 static int
138 rhead(char *line, Word **h, Word **t, int *attr, char **prog)
140 char *p;
141 char *pp;
142 int sep;
143 Rune r;
144 int n;
145 Word *w;
147 p = shellt->charin(line,":=<");
148 if(p == 0)
149 return('?');
150 sep = *p;
151 *p++ = 0;
152 if(sep == '<' && *p == '|'){
153 sep = '|';
154 p++;
156 *attr = 0;
157 *prog = 0;
158 if(sep == '='){
159 pp = shellt->charin(p, shellt->termchars); /* termchars is shell-dependent */
160 if (pp && *pp == '=') {
161 while (p != pp) {
162 n = chartorune(&r, p);
163 switch(r)
165 default:
166 SYNERR(-1);
167 fprint(2, "unknown attribute '%c'\n",*p);
168 Exit();
169 case 'U':
170 *attr = 1;
171 break;
173 p += n;
175 p++; /* skip trailing '=' */
178 if((sep == ':') && *p && (*p != ' ') && (*p != '\t')){
179 while (*p) {
180 n = chartorune(&r, p);
181 if (r == ':')
182 break;
183 p += n;
184 switch(r)
186 default:
187 SYNERR(-1);
188 fprint(2, "unknown attribute '%c'\n", p[-1]);
189 Exit();
190 case 'D':
191 *attr |= DEL;
192 break;
193 case 'E':
194 *attr |= NOMINUSE;
195 break;
196 case 'n':
197 *attr |= NOVIRT;
198 break;
199 case 'N':
200 *attr |= NOREC;
201 break;
202 case 'P':
203 pp = utfrune(p, ':');
204 if (pp == 0 || *pp == 0)
205 goto eos;
206 *pp = 0;
207 *prog = strdup(p);
208 *pp = ':';
209 p = pp;
210 break;
211 case 'Q':
212 *attr |= QUIET;
213 break;
214 case 'R':
215 *attr |= REGEXP;
216 break;
217 case 'U':
218 *attr |= UPD;
219 break;
220 case 'V':
221 *attr |= VIR;
222 break;
225 if (*p++ != ':') {
226 eos:
227 SYNERR(-1);
228 fprint(2, "missing trailing :\n");
229 Exit();
232 *h = w = stow(line);
233 if(*w->s == 0 && sep != '<' && sep != '|' && sep != 'S') {
234 SYNERR(mkinline-1);
235 fprint(2, "no var on left side of assignment/rule\n");
236 Exit();
238 *t = stow(p);
239 return(sep);
242 static char *
243 rbody(Biobuf *in)
245 Bufblock *buf;
246 int r, lastr;
247 char *p;
249 lastr = '\n';
250 buf = newbuf();
251 for(;;){
252 r = Bgetrune(in);
253 if (r < 0)
254 break;
255 if (lastr == '\n') {
256 if (r == '#')
257 rinsert(buf, r);
258 else if (r != ' ' && r != '\t') {
259 Bungetrune(in);
260 break;
262 } else
263 rinsert(buf, r);
264 lastr = r;
265 if (r == '\n')
266 mkinline++;
268 insert(buf, 0);
269 p = strdup(buf->start);
270 freebuf(buf);
271 return p;
274 struct input
276 char *file;
277 int line;
278 struct input *next;
279 };
280 static struct input *inputs = 0;
282 void
283 ipush(void)
285 struct input *in, *me;
287 me = (struct input *)Malloc(sizeof(*me));
288 me->file = infile;
289 me->line = mkinline;
290 me->next = 0;
291 if(inputs == 0)
292 inputs = me;
293 else {
294 for(in = inputs; in->next; )
295 in = in->next;
296 in->next = me;
300 void
301 ipop(void)
303 struct input *in, *me;
305 assert("pop input list", inputs != 0);
306 if(inputs->next == 0){
307 me = inputs;
308 inputs = 0;
309 } else {
310 for(in = inputs; in->next->next; )
311 in = in->next;
312 me = in->next;
313 in->next = 0;
315 infile = me->file;
316 mkinline = me->line;
317 free((char *)me);