]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/mk/parse.c
ndb/dns: lookup *all* entries in dblookup(), v4 and v6 queries in parallel, remove...
[plan9front.git] / sys / src / cmd / mk / parse.c
1 #include        "mk.h"
2
3 char *infile;
4 int mkinline;
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)
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
21         if(fd < 0){
22                 perror(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: ");
44                                 perror(p);
45                         } else
46                                 parse(p, newfd, 0);
47                         break;
48                 case '|':
49                         p = wtos(tail, ' ');
50                         if(*p == 0){
51                                 SYNERR(-1);
52                                 fprint(2, "missing include program name\n");
53                                 Exit();
54                         }
55                         execinit();
56                         pid=pipecmd(p, envy, &newfd);
57                         if(newfd < 0){
58                                 fprint(2, "warning: skipping missing program file: ");
59                                 perror(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                         }
95                         if(attr)
96                                 symlook(head->s, S_NOEXPORT, (void *)"");
97                         break;
98                 default:
99                         SYNERR(hline);
100                         fprint(2, "expected one of :<=\n");
101                         Exit();
102                         break;
103                 }
104         }
105         close(fd);
106         freebuf(buf);
107         ipop();
108 }
109
110 void
111 addrules(Word *head, Word *tail, char *body, int attr, int hline, char *prog)
112 {
113         Word *w;
114
115         assert(/*addrules args*/ head && body);
116                 /* tuck away first non-meta rule as default target*/
117         if(target1 == 0 && !(attr&REGEXP)){
118                 for(w = head; w; w = w->next)
119                         if(charin(w->s, "%&"))
120                                 break;
121                 if(w == 0)
122                         target1 = wdup(head);
123         }
124         for(w = head; w; w = w->next)
125                 addrule(w->s, tail, body, head, attr, hline, prog);
126 }
127
128 static int
129 rhead(char *line, Word **h, Word **t, int *attr, char **prog)
130 {
131         char *p;
132         char *pp;
133         int sep;
134         Rune r;
135         int n;
136         Word *w;
137
138         p = charin(line,":=<");
139         if(p == 0)
140                 return('?');
141         sep = *p;
142         *p++ = 0;
143         if(sep == '<' && *p == '|'){
144                 sep = '|';
145                 p++;
146         }
147         *attr = 0;
148         *prog = 0;
149         if(sep == '='){
150                 pp = charin(p, termchars);      /* termchars is shell-dependent */
151                 if (pp && *pp == '=') {
152                         while (p != pp) {
153                                 n = chartorune(&r, p);
154                                 switch(r)
155                                 {
156                                 default:
157                                         SYNERR(-1);
158                                         fprint(2, "unknown attribute '%c'\n",*p);
159                                         Exit();
160                                 case 'U':
161                                         *attr = 1;
162                                         break;
163                                 }
164                                 p += n;
165                         }
166                         p++;            /* skip trailing '=' */
167                 }
168         }
169         if((sep == ':') && *p && (*p != ' ') && (*p != '\t')){
170                 while (*p) {
171                         n = chartorune(&r, p);
172                         if (r == ':')
173                                 break;
174                         p += n;
175                         switch(r)
176                         {
177                         default:
178                                 SYNERR(-1);
179                                 fprint(2, "unknown attribute '%c'\n", p[-1]);
180                                 Exit();
181                         case 'D':
182                                 *attr |= DEL;
183                                 break;
184                         case 'E':
185                                 *attr |= NOMINUSE;
186                                 break;
187                         case 'n':
188                                 *attr |= NOVIRT;
189                                 break;
190                         case 'N':
191                                 *attr |= NOREC;
192                                 break;
193                         case 'P':
194                                 pp = utfrune(p, ':');
195                                 if (pp == 0 || *pp == 0)
196                                         goto eos;
197                                 *pp = 0;
198                                 *prog = strdup(p);
199                                 *pp = ':';
200                                 p = pp;
201                                 break;
202                         case 'Q':
203                                 *attr |= QUIET;
204                                 break;
205                         case 'R':
206                                 *attr |= REGEXP;
207                                 break;
208                         case 'U':
209                                 *attr |= UPD;
210                                 break;
211                         case 'V':
212                                 *attr |= VIR;
213                                 break;
214                         }
215                 }
216                 if (*p++ != ':') {
217         eos:
218                         SYNERR(-1);
219                         fprint(2, "missing trailing :\n");
220                         Exit();
221                 }
222         }
223         *h = w = stow(line);
224         if(*w->s == 0 && sep != '<' && sep != '|') {
225                 SYNERR(mkinline-1);
226                 fprint(2, "no var on left side of assignment/rule\n");
227                 Exit();
228         }
229         *t = stow(p);
230         return(sep);
231 }
232
233 static char *
234 rbody(Biobuf *in)
235 {
236         Bufblock *buf;
237         int r, lastr;
238         char *p;
239
240         lastr = '\n';
241         buf = newbuf();
242         for(;;){
243                 r = Bgetrune(in);
244                 if (r < 0)
245                         break;
246                 if (lastr == '\n') {
247                         if (r == '#')
248                                 rinsert(buf, r);
249                         else if (r != ' ' && r != '\t') {
250                                 Bungetrune(in);
251                                 break;
252                         }
253                 } else
254                         rinsert(buf, r);
255                 lastr = r;
256                 if (r == '\n')
257                         mkinline++;
258         }
259         insert(buf, 0);
260         p = strdup(buf->start);
261         freebuf(buf);
262         return p;
263 }
264
265 struct input
266 {
267         char *file;
268         int line;
269         struct input *next;
270 };
271 static struct input *inputs = 0;
272
273 void
274 ipush(void)
275 {
276         struct input *in, *me;
277
278         me = (struct input *)Malloc(sizeof(*me));
279         me->file = infile;
280         me->line = mkinline;
281         me->next = 0;
282         if(inputs == 0)
283                 inputs = me;
284         else {
285                 for(in = inputs; in->next; )
286                         in = in->next;
287                 in->next = me;
288         }
289 }
290
291 void
292 ipop(void)
293 {
294         struct input *in, *me;
295
296         assert(/*pop input list*/ inputs != 0);
297         if(inputs->next == 0){
298                 me = inputs;
299                 inputs = 0;
300         } else {
301                 for(in = inputs; in->next->next; )
302                         in = in->next;
303                 me = in->next;
304                 in->next = 0;
305         }
306         infile = me->file;
307         mkinline = me->line;
308         free((char *)me);
309 }