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