1 /*-
2 * Copyright (c) 1980, 1991, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * %sccs.include.redist.c%
6 */
7
8 #ifndef lint
9 static char sccsid[] = "@(#)parse.c 8.1 (Berkeley) 05/31/93";
10 #endif /* not lint */
11
12 #include <sys/types.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #if __STDC__
16 # include <stdarg.h>
17 #else
18 # include <varargs.h>
19 #endif
20
21 #include "csh.h"
22 #include "extern.h"
23
24 static void asyntax __P((struct wordent *, struct wordent *));
25 static void asyn0 __P((struct wordent *, struct wordent *));
26 static void asyn3 __P((struct wordent *, struct wordent *));
27 static struct wordent
28 *freenod __P((struct wordent *, struct wordent *));
29 static struct command
30 *syn0 __P((struct wordent *, struct wordent *, int));
31 static struct command
32 *syn1 __P((struct wordent *, struct wordent *, int));
33 static struct command
34 *syn1a __P((struct wordent *, struct wordent *, int));
35 static struct command
36 *syn1b __P((struct wordent *, struct wordent *, int));
37 static struct command
38 *syn2 __P((struct wordent *, struct wordent *, int));
39 static struct command
40 *syn3 __P((struct wordent *, struct wordent *, int));
41
42 #define ALEFT 21 /* max of 20 alias expansions */
43 #define HLEFT 11 /* max of 10 history expansions */
44 /*
45 * Perform aliasing on the word list lex
46 * Do a (very rudimentary) parse to separate into commands.
47 * If word 0 of a command has an alias, do it.
48 * Repeat a maximum of 20 times.
49 */
50 static int aleft;
51 extern int hleft;
52 void
alias(lex)53 alias(lex)
54 register struct wordent *lex;
55 {
56 jmp_buf osetexit;
57
58 aleft = ALEFT;
59 hleft = HLEFT;
60 getexit(osetexit);
61 (void) setexit();
62 if (haderr) {
63 resexit(osetexit);
64 reset();
65 }
66 if (--aleft == 0)
67 stderror(ERR_ALIASLOOP);
68 asyntax(lex->next, lex);
69 resexit(osetexit);
70 }
71
72 static void
asyntax(p1,p2)73 asyntax(p1, p2)
74 register struct wordent *p1, *p2;
75 {
76 while (p1 != p2)
77 if (any(";&\n", p1->word[0]))
78 p1 = p1->next;
79 else {
80 asyn0(p1, p2);
81 return;
82 }
83 }
84
85 static void
asyn0(p1,p2)86 asyn0(p1, p2)
87 struct wordent *p1;
88 register struct wordent *p2;
89 {
90 register struct wordent *p;
91 register int l = 0;
92
93 for (p = p1; p != p2; p = p->next)
94 switch (p->word[0]) {
95
96 case '(':
97 l++;
98 continue;
99
100 case ')':
101 l--;
102 if (l < 0)
103 stderror(ERR_TOOMANYRP);
104 continue;
105
106 case '>':
107 if (p->next != p2 && eq(p->next->word, STRand))
108 p = p->next;
109 continue;
110
111 case '&':
112 case '|':
113 case ';':
114 case '\n':
115 if (l != 0)
116 continue;
117 asyn3(p1, p);
118 asyntax(p->next, p2);
119 return;
120 }
121 if (l == 0)
122 asyn3(p1, p2);
123 }
124
125 static void
asyn3(p1,p2)126 asyn3(p1, p2)
127 struct wordent *p1;
128 register struct wordent *p2;
129 {
130 register struct varent *ap;
131 struct wordent alout;
132 register bool redid;
133
134 if (p1 == p2)
135 return;
136 if (p1->word[0] == '(') {
137 for (p2 = p2->prev; p2->word[0] != ')'; p2 = p2->prev)
138 if (p2 == p1)
139 return;
140 if (p2 == p1->next)
141 return;
142 asyn0(p1->next, p2);
143 return;
144 }
145 ap = adrof1(p1->word, &aliases);
146 if (ap == 0)
147 return;
148 alhistp = p1->prev;
149 alhistt = p2;
150 alvec = ap->vec;
151 redid = lex(&alout);
152 alhistp = alhistt = 0;
153 alvec = 0;
154 if (seterr) {
155 freelex(&alout);
156 stderror(ERR_OLD);
157 }
158 if (p1->word[0] && eq(p1->word, alout.next->word)) {
159 Char *cp = alout.next->word;
160
161 alout.next->word = Strspl(STRQNULL, cp);
162 xfree((ptr_t) cp);
163 }
164 p1 = freenod(p1, redid ? p2 : p1->next);
165 if (alout.next != &alout) {
166 p1->next->prev = alout.prev->prev;
167 alout.prev->prev->next = p1->next;
168 alout.next->prev = p1;
169 p1->next = alout.next;
170 xfree((ptr_t) alout.prev->word);
171 xfree((ptr_t) (alout.prev));
172 }
173 reset(); /* throw! */
174 }
175
176 static struct wordent *
freenod(p1,p2)177 freenod(p1, p2)
178 register struct wordent *p1, *p2;
179 {
180 register struct wordent *retp = p1->prev;
181
182 while (p1 != p2) {
183 xfree((ptr_t) p1->word);
184 p1 = p1->next;
185 xfree((ptr_t) (p1->prev));
186 }
187 retp->next = p2;
188 p2->prev = retp;
189 return (retp);
190 }
191
192 #define PHERE 1
193 #define PIN 2
194 #define POUT 4
195 #define PERR 8
196
197 /*
198 * syntax
199 * empty
200 * syn0
201 */
202 struct command *
syntax(p1,p2,flags)203 syntax(p1, p2, flags)
204 register struct wordent *p1, *p2;
205 int flags;
206 {
207
208 while (p1 != p2)
209 if (any(";&\n", p1->word[0]))
210 p1 = p1->next;
211 else
212 return (syn0(p1, p2, flags));
213 return (0);
214 }
215
216 /*
217 * syn0
218 * syn1
219 * syn1 & syntax
220 */
221 static struct command *
syn0(p1,p2,flags)222 syn0(p1, p2, flags)
223 struct wordent *p1, *p2;
224 int flags;
225 {
226 register struct wordent *p;
227 register struct command *t, *t1;
228 int l;
229
230 l = 0;
231 for (p = p1; p != p2; p = p->next)
232 switch (p->word[0]) {
233
234 case '(':
235 l++;
236 continue;
237
238 case ')':
239 l--;
240 if (l < 0)
241 seterror(ERR_TOOMANYRP);
242 continue;
243
244 case '|':
245 if (p->word[1] == '|')
246 continue;
247 /* fall into ... */
248
249 case '>':
250 if (p->next != p2 && eq(p->next->word, STRand))
251 p = p->next;
252 continue;
253
254 case '&':
255 if (l != 0)
256 break;
257 if (p->word[1] == '&')
258 continue;
259 t1 = syn1(p1, p, flags);
260 if (t1->t_dtyp == NODE_LIST ||
261 t1->t_dtyp == NODE_AND ||
262 t1->t_dtyp == NODE_OR) {
263 t = (struct command *) xcalloc(1, sizeof(*t));
264 t->t_dtyp = NODE_PAREN;
265 t->t_dflg = F_AMPERSAND | F_NOINTERRUPT;
266 t->t_dspr = t1;
267 t1 = t;
268 }
269 else
270 t1->t_dflg |= F_AMPERSAND | F_NOINTERRUPT;
271 t = (struct command *) xcalloc(1, sizeof(*t));
272 t->t_dtyp = NODE_LIST;
273 t->t_dflg = 0;
274 t->t_dcar = t1;
275 t->t_dcdr = syntax(p, p2, flags);
276 return (t);
277 }
278 if (l == 0)
279 return (syn1(p1, p2, flags));
280 seterror(ERR_TOOMANYLP);
281 return (0);
282 }
283
284 /*
285 * syn1
286 * syn1a
287 * syn1a ; syntax
288 */
289 static struct command *
syn1(p1,p2,flags)290 syn1(p1, p2, flags)
291 struct wordent *p1, *p2;
292 int flags;
293 {
294 register struct wordent *p;
295 register struct command *t;
296 int l;
297
298 l = 0;
299 for (p = p1; p != p2; p = p->next)
300 switch (p->word[0]) {
301
302 case '(':
303 l++;
304 continue;
305
306 case ')':
307 l--;
308 continue;
309
310 case ';':
311 case '\n':
312 if (l != 0)
313 break;
314 t = (struct command *) xcalloc(1, sizeof(*t));
315 t->t_dtyp = NODE_LIST;
316 t->t_dcar = syn1a(p1, p, flags);
317 t->t_dcdr = syntax(p->next, p2, flags);
318 if (t->t_dcdr == 0)
319 t->t_dcdr = t->t_dcar, t->t_dcar = 0;
320 return (t);
321 }
322 return (syn1a(p1, p2, flags));
323 }
324
325 /*
326 * syn1a
327 * syn1b
328 * syn1b || syn1a
329 */
330 static struct command *
syn1a(p1,p2,flags)331 syn1a(p1, p2, flags)
332 struct wordent *p1, *p2;
333 int flags;
334 {
335 register struct wordent *p;
336 register struct command *t;
337 register int l = 0;
338
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] != '|')
352 continue;
353 if (l == 0) {
354 t = (struct command *) xcalloc(1, sizeof(*t));
355 t->t_dtyp = NODE_OR;
356 t->t_dcar = syn1b(p1, p, flags);
357 t->t_dcdr = syn1a(p->next, p2, flags);
358 t->t_dflg = 0;
359 return (t);
360 }
361 continue;
362 }
363 return (syn1b(p1, p2, flags));
364 }
365
366 /*
367 * syn1b
368 * syn2
369 * syn2 && syn1b
370 */
371 static struct command *
syn1b(p1,p2,flags)372 syn1b(p1, p2, flags)
373 struct wordent *p1, *p2;
374 int flags;
375 {
376 register struct wordent *p;
377 register struct command *t;
378 register int l = 0;
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 (p->word[1] == '&' && l == 0) {
393 t = (struct command *) xcalloc(1, sizeof(*t));
394 t->t_dtyp = NODE_AND;
395 t->t_dcar = syn2(p1, p, flags);
396 t->t_dcdr = syn1b(p->next, p2, flags);
397 t->t_dflg = 0;
398 return (t);
399 }
400 continue;
401 }
402 return (syn2(p1, p2, flags));
403 }
404
405 /*
406 * syn2
407 * syn3
408 * syn3 | syn2
409 * syn3 |& syn2
410 */
411 static struct command *
syn2(p1,p2,flags)412 syn2(p1, p2, flags)
413 struct wordent *p1, *p2;
414 int flags;
415 {
416 register struct wordent *p, *pn;
417 register struct command *t;
418 register int l = 0;
419 int f;
420
421 for (p = p1; p != p2; p = p->next)
422 switch (p->word[0]) {
423
424 case '(':
425 l++;
426 continue;
427
428 case ')':
429 l--;
430 continue;
431
432 case '|':
433 if (l != 0)
434 continue;
435 t = (struct command *) xcalloc(1, sizeof(*t));
436 f = flags | POUT;
437 pn = p->next;
438 if (pn != p2 && pn->word[0] == '&') {
439 f |= PERR;
440 t->t_dflg |= F_STDERR;
441 }
442 t->t_dtyp = NODE_PIPE;
443 t->t_dcar = syn3(p1, p, f);
444 if (pn != p2 && pn->word[0] == '&')
445 p = pn;
446 t->t_dcdr = syn2(p->next, p2, flags | PIN);
447 return (t);
448 }
449 return (syn3(p1, p2, flags));
450 }
451
452 static char RELPAR[] = {'<', '>', '(', ')', '\0'};
453
454 /*
455 * syn3
456 * ( syn0 ) [ < in ] [ > out ]
457 * word word* [ < in ] [ > out ]
458 * KEYWORD ( word* ) word* [ < in ] [ > out ]
459 *
460 * KEYWORD = (@ exit foreach if set switch test while)
461 */
462 static struct command *
syn3(p1,p2,flags)463 syn3(p1, p2, flags)
464 struct wordent *p1, *p2;
465 int flags;
466 {
467 register struct wordent *p;
468 struct wordent *lp, *rp;
469 register struct command *t;
470 register int l;
471 Char **av;
472 int n, c;
473 bool specp = 0;
474
475 if (p1 != p2) {
476 p = p1;
477 again:
478 switch (srchx(p->word)) {
479
480 case T_ELSE:
481 p = p->next;
482 if (p != p2)
483 goto again;
484 break;
485
486 case T_EXIT:
487 case T_FOREACH:
488 case T_IF:
489 case T_LET:
490 case T_SET:
491 case T_SWITCH:
492 case T_WHILE:
493 specp = 1;
494 break;
495 }
496 }
497 n = 0;
498 l = 0;
499 for (p = p1; p != p2; p = p->next)
500 switch (p->word[0]) {
501
502 case '(':
503 if (specp)
504 n++;
505 l++;
506 continue;
507
508 case ')':
509 if (specp)
510 n++;
511 l--;
512 continue;
513
514 case '>':
515 case '<':
516 if (l != 0) {
517 if (specp)
518 n++;
519 continue;
520 }
521 if (p->next == p2)
522 continue;
523 if (any(RELPAR, p->next->word[0]))
524 continue;
525 n--;
526 continue;
527
528 default:
529 if (!specp && l != 0)
530 continue;
531 n++;
532 continue;
533 }
534 if (n < 0)
535 n = 0;
536 t = (struct command *) xcalloc(1, sizeof(*t));
537 av = (Char **) xcalloc((size_t) (n + 1), sizeof(Char **));
538 t->t_dcom = av;
539 n = 0;
540 if (p2->word[0] == ')')
541 t->t_dflg = F_NOFORK;
542 lp = 0;
543 rp = 0;
544 l = 0;
545 for (p = p1; p != p2; p = p->next) {
546 c = p->word[0];
547 switch (c) {
548
549 case '(':
550 if (l == 0) {
551 if (lp != 0 && !specp)
552 seterror(ERR_BADPLP);
553 lp = p->next;
554 }
555 l++;
556 goto savep;
557
558 case ')':
559 l--;
560 if (l == 0)
561 rp = p;
562 goto savep;
563
564 case '>':
565 if (l != 0)
566 goto savep;
567 if (p->word[1] == '>')
568 t->t_dflg |= F_APPEND;
569 if (p->next != p2 && eq(p->next->word, STRand)) {
570 t->t_dflg |= F_STDERR, p = p->next;
571 if (flags & (POUT | PERR)) {
572 seterror(ERR_OUTRED);
573 continue;
574 }
575 }
576 if (p->next != p2 && eq(p->next->word, STRbang))
577 t->t_dflg |= F_OVERWRITE, p = p->next;
578 if (p->next == p2) {
579 seterror(ERR_MISRED);
580 continue;
581 }
582 p = p->next;
583 if (any(RELPAR, p->word[0])) {
584 seterror(ERR_MISRED);
585 continue;
586 }
587 if ((flags & POUT) && ((flags & PERR) == 0 || t->t_drit))
588 seterror(ERR_OUTRED);
589 else
590 t->t_drit = Strsave(p->word);
591 continue;
592
593 case '<':
594 if (l != 0)
595 goto savep;
596 if (p->word[1] == '<')
597 t->t_dflg |= F_READ;
598 if (p->next == p2) {
599 seterror(ERR_MISRED);
600 continue;
601 }
602 p = p->next;
603 if (any(RELPAR, p->word[0])) {
604 seterror(ERR_MISRED);
605 continue;
606 }
607 if ((flags & PHERE) && (t->t_dflg & F_READ))
608 seterror(ERR_REDPAR);
609 else if ((flags & PIN) || t->t_dlef)
610 seterror(ERR_INRED);
611 else
612 t->t_dlef = Strsave(p->word);
613 continue;
614
615 savep:
616 if (!specp)
617 continue;
618 default:
619 if (l != 0 && !specp)
620 continue;
621 if (seterr == 0)
622 av[n] = Strsave(p->word);
623 n++;
624 continue;
625 }
626 }
627 if (lp != 0 && !specp) {
628 if (n != 0)
629 seterror(ERR_BADPLPS);
630 t->t_dtyp = NODE_PAREN;
631 t->t_dspr = syn0(lp, rp, PHERE);
632 }
633 else {
634 if (n == 0)
635 seterror(ERR_NULLCOM);
636 t->t_dtyp = NODE_COMMAND;
637 }
638 return (t);
639 }
640
641 void
freesyn(t)642 freesyn(t)
643 register struct command *t;
644 {
645 register Char **v;
646
647 if (t == 0)
648 return;
649 switch (t->t_dtyp) {
650
651 case NODE_COMMAND:
652 for (v = t->t_dcom; *v; v++)
653 xfree((ptr_t) * v);
654 xfree((ptr_t) (t->t_dcom));
655 xfree((ptr_t) t->t_dlef);
656 xfree((ptr_t) t->t_drit);
657 break;
658 case NODE_PAREN:
659 freesyn(t->t_dspr);
660 xfree((ptr_t) t->t_dlef);
661 xfree((ptr_t) t->t_drit);
662 break;
663
664 case NODE_AND:
665 case NODE_OR:
666 case NODE_PIPE:
667 case NODE_LIST:
668 freesyn(t->t_dcar), freesyn(t->t_dcdr);
669 break;
670 }
671 xfree((ptr_t) t);
672 }
673