Commit | Line | Data |
---|---|---|
0d061c44 BJ |
1 | static char *sccsid = "@(#)parse.c 4.1 %G%"; |
2 | ||
3 | #include "sh.h" | |
4 | ||
5 | /* | |
6 | * C shell | |
7 | */ | |
8 | ||
9 | /* | |
10 | * Perform aliasing on the word list lex | |
11 | * Do a (very rudimentary) parse to separate into commands. | |
12 | * If word 0 of a command has an alias, do it. | |
13 | * Repeat a maximum of 20 times. | |
14 | */ | |
15 | alias(lex) | |
16 | register struct wordent *lex; | |
17 | { | |
18 | int aleft = 21; | |
19 | jmp_buf osetexit; | |
20 | ||
21 | getexit(osetexit); | |
22 | setexit(); | |
23 | if (haderr) { | |
24 | resexit(osetexit); | |
25 | reset(); | |
26 | } | |
27 | if (--aleft == 0) | |
28 | error("Alias loop"); | |
29 | asyntax(lex->next, lex); | |
30 | resexit(osetexit); | |
31 | } | |
32 | ||
33 | asyntax(p1, p2) | |
34 | register struct wordent *p1, *p2; | |
35 | { | |
36 | ||
37 | while (p1 != p2) | |
38 | if (any(p1->word[0], ";&\n")) | |
39 | p1 = p1->next; | |
40 | else { | |
41 | asyn0(p1, p2); | |
42 | return; | |
43 | } | |
44 | } | |
45 | ||
46 | asyn0(p1, p2) | |
47 | struct wordent *p1; | |
48 | register struct wordent *p2; | |
49 | { | |
50 | register struct wordent *p; | |
51 | register int l = 0; | |
52 | ||
53 | for (p = p1; p != p2; p = p->next) | |
54 | switch (p->word[0]) { | |
55 | ||
56 | case '(': | |
57 | l++; | |
58 | continue; | |
59 | ||
60 | case ')': | |
61 | l--; | |
62 | if (l < 0) | |
63 | error("Too many )'s"); | |
64 | continue; | |
65 | ||
66 | case '>': | |
67 | if (p->next != p2 && eq(p->next->word, "&")) | |
68 | p = p->next; | |
69 | continue; | |
70 | ||
71 | case '&': | |
72 | case '|': | |
73 | case ';': | |
74 | case '\n': | |
75 | if (l != 0) | |
76 | continue; | |
77 | asyn3(p1, p); | |
78 | asyntax(p->next, p2); | |
79 | return; | |
80 | } | |
81 | if (l == 0) | |
82 | asyn3(p1, p2); | |
83 | } | |
84 | ||
85 | asyn3(p1, p2) | |
86 | struct wordent *p1; | |
87 | register struct wordent *p2; | |
88 | { | |
89 | register struct varent *ap; | |
90 | struct wordent alout; | |
91 | register bool redid; | |
92 | ||
93 | if (p1 == p2) | |
94 | return; | |
95 | if (p1->word[0] == '(') { | |
96 | for (p2 = p2->prev; p2->word[0] != ')'; p2 = p2->prev) | |
97 | if (p2 == p1) | |
98 | return; | |
99 | if (p2 == p1->next) | |
100 | return; | |
101 | asyn0(p1->next, p2); | |
102 | return; | |
103 | } | |
104 | ap = adrof1(p1->word, &aliases); | |
105 | if (ap == 0) | |
106 | return; | |
107 | alhistp = p1->prev; | |
108 | alhistt = p2; | |
109 | alvec = ap->vec; | |
110 | redid = lex(&alout); | |
111 | alhistp = alhistt = 0; | |
112 | alvec = 0; | |
113 | if (err) { | |
114 | freelex(&alout); | |
115 | error(err); | |
116 | } | |
117 | if (p1->word[0] && eq(p1->word, alout.next->word)) { | |
118 | char *cp = alout.next->word; | |
119 | ||
120 | alout.next->word = strspl("\200", cp); | |
121 | xfree(cp); | |
122 | } | |
123 | p1 = freenod(p1, redid ? p2 : p1->next); | |
124 | if (alout.next != &alout) { | |
125 | p1->next->prev = alout.prev->prev; | |
126 | alout.prev->prev->next = p1->next; | |
127 | alout.next->prev = p1; | |
128 | p1->next = alout.next; | |
129 | xfree(alout.prev->word); | |
130 | xfree((char *)(alout.prev)); | |
131 | } | |
132 | reset(); /* throw! */ | |
133 | } | |
134 | ||
135 | struct wordent * | |
136 | freenod(p1, p2) | |
137 | register struct wordent *p1, *p2; | |
138 | { | |
139 | register struct wordent *retp = p1->prev; | |
140 | ||
141 | while (p1 != p2) { | |
142 | xfree(p1->word); | |
143 | p1 = p1->next; | |
144 | xfree((char *)(p1->prev)); | |
145 | } | |
146 | retp->next = p2; | |
147 | p2->prev = retp; | |
148 | return (retp); | |
149 | } | |
150 | ||
151 | #define PHERE 1 | |
152 | #define PIN 2 | |
153 | #define POUT 4 | |
154 | #define PDIAG 8 | |
155 | ||
156 | /* | |
157 | * syntax | |
158 | * empty | |
159 | * syn0 | |
160 | */ | |
161 | struct command * | |
162 | syntax(p1, p2, flags) | |
163 | register struct wordent *p1, *p2; | |
164 | int flags; | |
165 | { | |
166 | ||
167 | while (p1 != p2) | |
168 | if (any(p1->word[0], ";&\n")) | |
169 | p1 = p1->next; | |
170 | else | |
171 | return (syn0(p1, p2, flags)); | |
172 | return (0); | |
173 | } | |
174 | ||
175 | /* | |
176 | * syn0 | |
177 | * syn1 | |
178 | * syn1 & syntax | |
179 | */ | |
180 | struct command * | |
181 | syn0(p1, p2, flags) | |
182 | struct wordent *p1, *p2; | |
183 | int flags; | |
184 | { | |
185 | register struct wordent *p; | |
186 | register struct command *t, *t1; | |
187 | int l; | |
188 | ||
189 | l = 0; | |
190 | for (p = p1; p != p2; p = p->next) | |
191 | switch (p->word[0]) { | |
192 | ||
193 | case '(': | |
194 | l++; | |
195 | continue; | |
196 | ||
197 | case ')': | |
198 | l--; | |
199 | if (l < 0) | |
200 | seterr("Too many )'s"); | |
201 | continue; | |
202 | ||
203 | case '|': | |
204 | if (p->word[1] == '|') | |
205 | continue; | |
206 | /* fall into ... */ | |
207 | ||
208 | case '>': | |
209 | if (p->next != p2 && eq(p->next->word, "&")) | |
210 | p = p->next; | |
211 | continue; | |
212 | ||
213 | case '&': | |
214 | if (l != 0) | |
215 | break; | |
216 | if (p->word[1] == '&') | |
217 | continue; | |
218 | t1 = syn1(p1, p, flags); | |
219 | if (t1->t_dtyp == TLST) { | |
220 | t = (struct command *) calloc(1, sizeof (*t)); | |
221 | t->t_dtyp = TPAR; | |
222 | t->t_dflg = FAND|FINT; | |
223 | t->t_dspr = t1; | |
224 | t1 = t; | |
225 | } else | |
226 | t1->t_dflg |= FAND|FINT; | |
227 | t = (struct command *) calloc(1, sizeof (*t)); | |
228 | t->t_dtyp = TLST; | |
229 | t->t_dflg = 0; | |
230 | t->t_dcar = t1; | |
231 | t->t_dcdr = syntax(p, p2, flags); | |
232 | return(t); | |
233 | } | |
234 | if (l == 0) | |
235 | return (syn1(p1, p2, flags)); | |
236 | seterr("Too many ('s"); | |
237 | return (0); | |
238 | } | |
239 | ||
240 | /* | |
241 | * syn1 | |
242 | * syn1a | |
243 | * syn1a ; syntax | |
244 | */ | |
245 | struct command * | |
246 | syn1(p1, p2, flags) | |
247 | struct wordent *p1, *p2; | |
248 | int flags; | |
249 | { | |
250 | register struct wordent *p; | |
251 | register struct command *t; | |
252 | int l; | |
253 | ||
254 | l = 0; | |
255 | for (p = p1; p != p2; p = p->next) | |
256 | switch (p->word[0]) { | |
257 | ||
258 | case '(': | |
259 | l++; | |
260 | continue; | |
261 | ||
262 | case ')': | |
263 | l--; | |
264 | continue; | |
265 | ||
266 | case ';': | |
267 | case '\n': | |
268 | if (l != 0) | |
269 | break; | |
270 | t = (struct command *) calloc(1, sizeof (*t)); | |
271 | t->t_dtyp = TLST; | |
272 | t->t_dcar = syn1a(p1, p, flags); | |
273 | t->t_dcdr = syntax(p->next, p2, flags); | |
274 | if (t->t_dcdr == 0) | |
275 | t->t_dcdr = t->t_dcar, t->t_dcar = 0; | |
276 | return (t); | |
277 | } | |
278 | return (syn1a(p1, p2, flags)); | |
279 | } | |
280 | ||
281 | /* | |
282 | * syn1a | |
283 | * syn1b | |
284 | * syn1b || syn1a | |
285 | */ | |
286 | struct command * | |
287 | syn1a(p1, p2, flags) | |
288 | struct wordent *p1, *p2; | |
289 | int flags; | |
290 | { | |
291 | register struct wordent *p; | |
292 | register struct command *t; | |
293 | register int l = 0; | |
294 | ||
295 | for (p = p1; p != p2; p = p->next) | |
296 | switch (p->word[0]) { | |
297 | ||
298 | case '(': | |
299 | l++; | |
300 | continue; | |
301 | ||
302 | case ')': | |
303 | l--; | |
304 | continue; | |
305 | ||
306 | case '|': | |
307 | if (p->word[1] != '|') | |
308 | continue; | |
309 | if (l == 0) { | |
310 | t = (struct command *) calloc(1, sizeof (*t)); | |
311 | t->t_dtyp = TOR; | |
312 | t->t_dcar = syn1b(p1, p, flags); | |
313 | t->t_dcdr = syn1a(p->next, p2, flags); | |
314 | t->t_dflg = 0; | |
315 | return (t); | |
316 | } | |
317 | continue; | |
318 | } | |
319 | return (syn1b(p1, p2, flags)); | |
320 | } | |
321 | ||
322 | /* | |
323 | * syn1b | |
324 | * syn2 | |
325 | * syn2 && syn1b | |
326 | */ | |
327 | struct command * | |
328 | syn1b(p1, p2, flags) | |
329 | struct wordent *p1, *p2; | |
330 | int flags; | |
331 | { | |
332 | register struct wordent *p; | |
333 | register struct command *t; | |
334 | register int l = 0; | |
335 | ||
336 | l = 0; | |
337 | for (p = p1; p != p2; p = p->next) | |
338 | switch (p->word[0]) { | |
339 | ||
340 | case '(': | |
341 | l++; | |
342 | continue; | |
343 | ||
344 | case ')': | |
345 | l--; | |
346 | continue; | |
347 | ||
348 | case '&': | |
349 | if (p->word[1] == '&' && l == 0) { | |
350 | t = (struct command *) calloc(1, sizeof (*t)); | |
351 | t->t_dtyp = TAND; | |
352 | t->t_dcar = syn2(p1, p, flags); | |
353 | t->t_dcdr = syn1b(p->next, p2, flags); | |
354 | t->t_dflg = 0; | |
355 | return (t); | |
356 | } | |
357 | continue; | |
358 | } | |
359 | return (syn2(p1, p2, flags)); | |
360 | } | |
361 | ||
362 | /* | |
363 | * syn2 | |
364 | * syn3 | |
365 | * syn3 | syn2 | |
366 | * syn3 |& syn2 | |
367 | */ | |
368 | struct command * | |
369 | syn2(p1, p2, flags) | |
370 | struct wordent *p1, *p2; | |
371 | int flags; | |
372 | { | |
373 | register struct wordent *p, *pn; | |
374 | register struct command *t; | |
375 | register int l = 0; | |
376 | int f; | |
377 | ||
378 | for (p = p1; p != p2; p = p->next) | |
379 | switch (p->word[0]) { | |
380 | ||
381 | case '(': | |
382 | l++; | |
383 | continue; | |
384 | ||
385 | case ')': | |
386 | l--; | |
387 | continue; | |
388 | ||
389 | case '|': | |
390 | if (l != 0) | |
391 | continue; | |
392 | t = (struct command *) calloc(1, sizeof (*t)); | |
393 | f = flags | POUT; | |
394 | pn = p->next; | |
395 | if (pn != p2 && pn->word[0] == '&') { | |
396 | f |= PDIAG; | |
397 | t->t_dflg |= FDIAG; | |
398 | } | |
399 | t->t_dtyp = TFIL; | |
400 | t->t_dcar = syn3(p1, p, f); | |
401 | if (pn != p2 && pn->word[0] == '&') | |
402 | p = pn; | |
403 | t->t_dcdr = syn2(p->next, p2, flags | PIN); | |
404 | return (t); | |
405 | } | |
406 | return (syn3(p1, p2, flags)); | |
407 | } | |
408 | ||
409 | char *RELPAR = "<>()"; | |
410 | ||
411 | /* | |
412 | * syn3 | |
413 | * ( syn0 ) [ < in ] [ > out ] | |
414 | * word word* [ < in ] [ > out ] | |
415 | * KEYWORD ( word* ) word* [ < in ] [ > out ] | |
416 | * | |
417 | * KEYWORD = (@ exit foreach if set switch test while) | |
418 | */ | |
419 | struct command * | |
420 | syn3(p1, p2, flags) | |
421 | struct wordent *p1, *p2; | |
422 | int flags; | |
423 | { | |
424 | register struct wordent *p; | |
425 | struct wordent *lp, *rp; | |
426 | register struct command *t; | |
427 | register int l; | |
428 | char **av; | |
429 | int n, c; | |
430 | bool specp = 0; | |
431 | ||
432 | if (p1 != p2) { | |
433 | p = p1; | |
434 | again: | |
435 | switch (srchx(p->word)) { | |
436 | ||
437 | case ZELSE: | |
438 | p = p->next; | |
439 | if (p != p2) | |
440 | goto again; | |
441 | break; | |
442 | ||
443 | case ZEXIT: | |
444 | case ZFOREACH: | |
445 | case ZIF: | |
446 | case ZLET: | |
447 | case ZSET: | |
448 | case ZSWITCH: | |
449 | case ZWHILE: | |
450 | specp = 1; | |
451 | break; | |
452 | } | |
453 | } | |
454 | n = 0; | |
455 | l = 0; | |
456 | for (p = p1; p != p2; p = p->next) | |
457 | switch (p->word[0]) { | |
458 | ||
459 | case '(': | |
460 | if (specp) | |
461 | n++; | |
462 | l++; | |
463 | continue; | |
464 | ||
465 | case ')': | |
466 | if (specp) | |
467 | n++; | |
468 | l--; | |
469 | continue; | |
470 | ||
471 | case '>': | |
472 | case '<': | |
473 | if (l != 0) { | |
474 | if (specp) | |
475 | n++; | |
476 | continue; | |
477 | } | |
478 | if (p->next == p2) | |
479 | continue; | |
480 | if (any(p->next->word[0], RELPAR)) | |
481 | continue; | |
482 | n--; | |
483 | continue; | |
484 | ||
485 | default: | |
486 | if (!specp && l != 0) | |
487 | continue; | |
488 | n++; | |
489 | continue; | |
490 | } | |
491 | if (n < 0) | |
492 | n = 0; | |
493 | t = (struct command *) calloc(1, sizeof (*t)); | |
494 | av = (char **) calloc(n + 1, sizeof (char **)); | |
495 | t->t_dcom = av; | |
496 | n = 0; | |
497 | if (p2->word[0] == ')') | |
498 | t->t_dflg = FPAR; | |
499 | lp = 0; | |
500 | rp = 0; | |
501 | l = 0; | |
502 | for (p = p1; p != p2; p = p->next) { | |
503 | c = p->word[0]; | |
504 | switch (c) { | |
505 | ||
506 | case '(': | |
507 | if (l == 0) { | |
508 | if (lp != 0 && !specp) | |
509 | seterr("Badly placed ("); | |
510 | lp = p->next; | |
511 | } | |
512 | l++; | |
513 | goto savep; | |
514 | ||
515 | case ')': | |
516 | l--; | |
517 | if (l == 0) | |
518 | rp = p; | |
519 | goto savep; | |
520 | ||
521 | case '>': | |
522 | if (l != 0) | |
523 | goto savep; | |
524 | if (p->word[1] == '>') | |
525 | t->t_dflg |= FCAT; | |
526 | if (p->next != p2 && eq(p->next->word, "&")) { | |
527 | t->t_dflg |= FDIAG, p = p->next; | |
528 | if (flags & (POUT|PDIAG)) | |
529 | goto badout; | |
530 | } | |
531 | if (p->next != p2 && eq(p->next->word, "!")) | |
532 | t->t_dflg |= FANY, p = p->next; | |
533 | if (p->next == p2) { | |
534 | missfile: | |
535 | seterr("Missing name for redirect"); | |
536 | continue; | |
537 | } | |
538 | p = p->next; | |
539 | if (any(p->word[0], RELPAR)) | |
540 | goto missfile; | |
541 | if ((flags & POUT) && (flags & PDIAG) == 0 || t->t_drit) | |
542 | badout: | |
543 | seterr("Ambiguous output redirect"); | |
544 | else | |
545 | t->t_drit = savestr(p->word); | |
546 | continue; | |
547 | ||
548 | case '<': | |
549 | if (l != 0) | |
550 | goto savep; | |
551 | if (p->word[1] == '<') | |
552 | t->t_dflg |= FHERE; | |
553 | if (p->next == p2) | |
554 | goto missfile; | |
555 | p = p->next; | |
556 | if (any(p->word[0], RELPAR)) | |
557 | goto missfile; | |
558 | if ((flags & PHERE) && (t->t_dflg & FHERE)) | |
559 | seterr("Can't << within ()'s"); | |
560 | else if ((flags & PIN) || t->t_dlef) | |
561 | seterr("Ambiguous input redirect"); | |
562 | else | |
563 | t->t_dlef = savestr(p->word); | |
564 | continue; | |
565 | ||
566 | savep: | |
567 | if (!specp) | |
568 | continue; | |
569 | default: | |
570 | if (l != 0 && !specp) | |
571 | continue; | |
572 | if (err == 0) | |
573 | av[n] = savestr(p->word); | |
574 | n++; | |
575 | continue; | |
576 | } | |
577 | } | |
578 | if (lp != 0 && !specp) { | |
579 | if (n != 0) | |
580 | seterr("Badly placed ()'s"); | |
581 | t->t_dtyp = TPAR; | |
582 | t->t_dspr = syn0(lp, rp, PHERE); | |
583 | } else { | |
584 | if (n == 0) | |
585 | seterr("Invalid null command"); | |
586 | t->t_dtyp = TCOM; | |
587 | } | |
588 | return (t); | |
589 | } | |
590 | ||
591 | freesyn(t) | |
592 | register struct command *t; | |
593 | { | |
594 | register char **v; | |
595 | ||
596 | if (t == 0) | |
597 | return; | |
598 | switch (t->t_dtyp) { | |
599 | ||
600 | case TCOM: | |
601 | for (v = t->t_dcom; *v; v++) | |
602 | xfree(*v); | |
603 | xfree((char *)(t->t_dcom)); | |
604 | goto lr; | |
605 | ||
606 | case TPAR: | |
607 | freesyn(t->t_dspr); | |
608 | /* fall into ... */ | |
609 | ||
610 | lr: | |
611 | xfree(t->t_dlef), xfree(t->t_drit); | |
612 | break; | |
613 | ||
614 | case TAND: | |
615 | case TOR: | |
616 | case TFIL: | |
617 | case TLST: | |
618 | freesyn(t->t_dcar), freesyn(t->t_dcdr); | |
619 | break; | |
620 | } | |
621 | xfree((char *)t); | |
622 | } |