tparse.c - plan9port - [fork] Plan 9 from user space | |
git clone git://src.adamsgaard.dk/plan9port | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
tparse.c (5593B) | |
--- | |
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 char *err; | |
21 | |
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 inc… | |
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\… | |
54 Exit(); | |
55 } | |
56 execinit(); | |
57 pid=pipecmd(p, envy, &newfd, shellt, shellcmd); | |
58 if(newfd < 0){ | |
59 fprint(2, "warning: skipping missing pro… | |
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… | |
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, (vo… | |
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; | |
100 } | |
101 } | |
102 } | |
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; | |
111 } | |
112 } | |
113 close(fd); | |
114 freebuf(buf); | |
115 ipop(); | |
116 popshell(); | |
117 } | |
118 | |
119 void | |
120 addrules(Word *head, Word *tail, char *body, int attr, int hline, char *… | |
121 { | |
122 Word *w; | |
123 | |
124 assert("addrules args", head && body); | |
125 /* tuck away first non-meta rule as default target*/ | |
126 if(target1 == 0 && !(attr®EXP)){ | |
127 for(w = head; w; w = w->next) | |
128 if(shellt->charin(w->s, "%&")) | |
129 break; | |
130 if(w == 0) | |
131 target1 = wdup(head); | |
132 } | |
133 for(w = head; w; w = w->next) | |
134 addrule(w->s, tail, body, head, attr, hline, prog); | |
135 } | |
136 | |
137 static int | |
138 rhead(char *line, Word **h, Word **t, int *attr, char **prog) | |
139 { | |
140 char *p; | |
141 char *pp; | |
142 int sep; | |
143 Rune r; | |
144 int n; | |
145 Word *w; | |
146 | |
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++; | |
155 } | |
156 *attr = 0; | |
157 *prog = 0; | |
158 if(sep == '='){ | |
159 pp = shellt->charin(p, shellt->termchars); /* ter… | |
160 if (pp && *pp == '=') { | |
161 while (p != pp) { | |
162 n = chartorune(&r, p); | |
163 switch(r) | |
164 { | |
165 default: | |
166 SYNERR(-1); | |
167 fprint(2, "unknown attribute '%c… | |
168 Exit(); | |
169 case 'U': | |
170 *attr = 1; | |
171 break; | |
172 } | |
173 p += n; | |
174 } | |
175 p++; /* skip trailing '=' */ | |
176 } | |
177 } | |
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) | |
185 { | |
186 default: | |
187 SYNERR(-1); | |
188 fprint(2, "unknown attribute '%c'\n", p[… | |
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; | |
223 } | |
224 } | |
225 if (*p++ != ':') { | |
226 eos: | |
227 SYNERR(-1); | |
228 fprint(2, "missing trailing :\n"); | |
229 Exit(); | |
230 } | |
231 } | |
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(); | |
237 } | |
238 *t = stow(p); | |
239 return(sep); | |
240 } | |
241 | |
242 static char * | |
243 rbody(Biobuf *in) | |
244 { | |
245 Bufblock *buf; | |
246 int r, lastr; | |
247 char *p; | |
248 | |
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; | |
261 } | |
262 } else | |
263 rinsert(buf, r); | |
264 lastr = r; | |
265 if (r == '\n') | |
266 mkinline++; | |
267 } | |
268 insert(buf, 0); | |
269 p = strdup(buf->start); | |
270 freebuf(buf); | |
271 return p; | |
272 } | |
273 | |
274 struct input | |
275 { | |
276 char *file; | |
277 int line; | |
278 struct input *next; | |
279 }; | |
280 static struct input *inputs = 0; | |
281 | |
282 void | |
283 ipush(void) | |
284 { | |
285 struct input *in, *me; | |
286 | |
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; | |
297 } | |
298 } | |
299 | |
300 void | |
301 ipop(void) | |
302 { | |
303 struct input *in, *me; | |
304 | |
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; | |
314 } | |
315 infile = me->file; | |
316 mkinline = me->line; | |
317 free((char *)me); | |
318 } |