xref: /freebsd/contrib/tcsh/sh.parse.c (revision 5521ff5a4d1929056e7ffc982fac3341ca54df7c)
1 /* $Header: /src/pub/tcsh/sh.parse.c,v 3.10 1996/04/26 19:20:04 christos Exp $ */
2 /*
3  * sh.parse.c: Interpret a list of tokens
4  */
5 /*-
6  * Copyright (c) 1980, 1991 The Regents of the University of California.
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  * 3. All advertising materials mentioning features or use of this software
18  *    must display the following acknowledgement:
19  *	This product includes software developed by the University of
20  *	California, Berkeley and its contributors.
21  * 4. Neither the name of the University nor the names of its contributors
22  *    may be used to endorse or promote products derived from this software
23  *    without specific prior written permission.
24  *
25  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35  * SUCH DAMAGE.
36  */
37 #include "sh.h"
38 
39 RCSID("$Id: sh.parse.c,v 3.10 1996/04/26 19:20:04 christos Exp $")
40 
41 /*
42  * C shell
43  */
44 static	void		 asyntax __P((struct wordent *, struct wordent *));
45 static	void		 asyn0 	 __P((struct wordent *, struct wordent *));
46 static	void		 asyn3	 __P((struct wordent *, struct wordent *));
47 static	struct wordent	*freenod __P((struct wordent *, struct wordent *));
48 static	struct command	*syn0	 __P((struct wordent *, struct wordent *, int));
49 static	struct command	*syn1	 __P((struct wordent *, struct wordent *, int));
50 static	struct command	*syn1a	 __P((struct wordent *, struct wordent *, int));
51 static	struct command	*syn1b	 __P((struct wordent *, struct wordent *, int));
52 static	struct command	*syn2	 __P((struct wordent *, struct wordent *, int));
53 static	struct command	*syn3	 __P((struct wordent *, struct wordent *, int));
54 
55 #define ALEFT	51		/* max of 50 alias expansions	 */
56 #define HLEFT	11		/* max of 10 history expansions */
57 /*
58  * Perform aliasing on the word list lexp
59  * Do a (very rudimentary) parse to separate into commands.
60  * If word 0 of a command has an alias, do it.
61  * Repeat a maximum of 50 times.
62  */
63 static int aleft;
64 extern int hleft;
65 void
66 alias(lexp)
67     register struct wordent *lexp;
68 {
69     jmp_buf_t osetexit;
70 
71     aleft = ALEFT;
72     hleft = HLEFT;
73     getexit(osetexit);
74     (void) setexit();
75     if (haderr) {
76 	resexit(osetexit);
77 	reset();
78     }
79     if (--aleft == 0)
80 	stderror(ERR_ALIASLOOP);
81     asyntax(lexp->next, lexp);
82     resexit(osetexit);
83 }
84 
85 static void
86 asyntax(p1, p2)
87     register struct wordent *p1, *p2;
88 {
89     while (p1 != p2)
90 	if (any(";&\n", p1->word[0]))
91 	    p1 = p1->next;
92 	else {
93 	    asyn0(p1, p2);
94 	    return;
95 	}
96 }
97 
98 static void
99 asyn0(p1, p2)
100     struct wordent *p1;
101     register struct wordent *p2;
102 {
103     register struct wordent *p;
104     register int l = 0;
105 
106     for (p = p1; p != p2; p = p->next)
107 	switch (p->word[0]) {
108 
109 	case '(':
110 	    l++;
111 	    continue;
112 
113 	case ')':
114 	    l--;
115 	    if (l < 0)
116 		stderror(ERR_TOOMANYRP);
117 	    continue;
118 
119 	case '>':
120 	    if (p->next != p2 && eq(p->next->word, STRand))
121 		p = p->next;
122 	    continue;
123 
124 	case '&':
125 	case '|':
126 	case ';':
127 	case '\n':
128 	    if (l != 0)
129 		continue;
130 	    asyn3(p1, p);
131 	    asyntax(p->next, p2);
132 	    return;
133 
134 	default:
135 	    break;
136 	}
137     if (l == 0)
138 	asyn3(p1, p2);
139 }
140 
141 static void
142 asyn3(p1, p2)
143     struct wordent *p1;
144     register struct wordent *p2;
145 {
146     register struct varent *ap;
147     struct wordent alout;
148     register bool redid;
149 
150     if (p1 == p2)
151 	return;
152     if (p1->word[0] == '(') {
153 	for (p2 = p2->prev; p2->word[0] != ')'; p2 = p2->prev)
154 	    if (p2 == p1)
155 		return;
156 	if (p2 == p1->next)
157 	    return;
158 	asyn0(p1->next, p2);
159 	return;
160     }
161     ap = adrof1(p1->word, &aliases);
162     if (ap == 0)
163 	return;
164     alhistp = p1->prev;
165     alhistt = p2;
166     alvec = ap->vec;
167     redid = lex(&alout);
168     alhistp = alhistt = 0;
169     alvec = 0;
170     if (seterr) {
171 	freelex(&alout);
172 	stderror(ERR_OLD);
173     }
174     if (p1->word[0] && eq(p1->word, alout.next->word)) {
175 	Char   *cp = alout.next->word;
176 
177 	alout.next->word = Strspl(STRQNULL, cp);
178 	xfree((ptr_t) cp);
179     }
180     p1 = freenod(p1, redid ? p2 : p1->next);
181     if (alout.next != &alout) {
182 	p1->next->prev = alout.prev->prev;
183 	alout.prev->prev->next = p1->next;
184 	alout.next->prev = p1;
185 	p1->next = alout.next;
186 	xfree((ptr_t) alout.prev->word);
187 	xfree((ptr_t) (alout.prev));
188     }
189     reset();			/* throw! */
190 }
191 
192 static struct wordent *
193 freenod(p1, p2)
194     register struct wordent *p1, *p2;
195 {
196     register struct wordent *retp = p1->prev;
197 
198     while (p1 != p2) {
199 	xfree((ptr_t) p1->word);
200 	p1 = p1->next;
201 	xfree((ptr_t) (p1->prev));
202     }
203     retp->next = p2;
204     p2->prev = retp;
205     return (retp);
206 }
207 
208 #define	P_HERE	1
209 #define	P_IN	2
210 #define	P_OUT	4
211 #define	P_DIAG	8
212 
213 /*
214  * syntax
215  *	empty
216  *	syn0
217  */
218 struct command *
219 syntax(p1, p2, flags)
220     register struct wordent *p1, *p2;
221     int     flags;
222 {
223 
224     while (p1 != p2)
225 	if (any(";&\n", p1->word[0]))
226 	    p1 = p1->next;
227 	else
228 	    return (syn0(p1, p2, flags));
229     return (0);
230 }
231 
232 /*
233  * syn0
234  *	syn1
235  *	syn1 & syntax
236  */
237 static struct command *
238 syn0(p1, p2, flags)
239     struct wordent *p1, *p2;
240     int     flags;
241 {
242     register struct wordent *p;
243     register struct command *t, *t1;
244     int     l;
245 
246     l = 0;
247     for (p = p1; p != p2; p = p->next)
248 	switch (p->word[0]) {
249 
250 	case '(':
251 	    l++;
252 	    continue;
253 
254 	case ')':
255 	    l--;
256 	    if (l < 0)
257 		seterror(ERR_TOOMANYRP);
258 	    continue;
259 
260 	case '|':
261 	    if (p->word[1] == '|')
262 		continue;
263 	    /*FALLTHROUGH*/
264 
265 	case '>':
266 	    if (p->next != p2 && eq(p->next->word, STRand))
267 		p = p->next;
268 	    continue;
269 
270 	case '&':
271 	    if (l != 0)
272 		break;
273 	    if (p->word[1] == '&')
274 		continue;
275 	    t1 = syn1(p1, p, flags);
276 	    if (t1->t_dtyp == NODE_LIST ||
277 		t1->t_dtyp == NODE_AND ||
278 		t1->t_dtyp == NODE_OR) {
279 		t = (struct command *) xcalloc(1, sizeof(*t));
280 		t->t_dtyp = NODE_PAREN;
281 		t->t_dflg = F_AMPERSAND | F_NOINTERRUPT;
282 		t->t_dspr = t1;
283 		t1 = t;
284 	    }
285 	    else
286 		t1->t_dflg |= F_AMPERSAND | F_NOINTERRUPT;
287 	    t = (struct command *) xcalloc(1, sizeof(*t));
288 	    t->t_dtyp = NODE_LIST;
289 	    t->t_dflg = 0;
290 	    t->t_dcar = t1;
291 	    t->t_dcdr = syntax(p, p2, flags);
292 	    return (t);
293 	default:
294 	    break;
295 	}
296     if (l == 0)
297 	return (syn1(p1, p2, flags));
298     seterror(ERR_TOOMANYLP);
299     return (0);
300 }
301 
302 /*
303  * syn1
304  *	syn1a
305  *	syn1a ; syntax
306  */
307 static struct command *
308 syn1(p1, p2, flags)
309     struct wordent *p1, *p2;
310     int     flags;
311 {
312     register struct wordent *p;
313     register struct command *t;
314     int     l;
315 
316     l = 0;
317     for (p = p1; p != p2; p = p->next)
318 	switch (p->word[0]) {
319 
320 	case '(':
321 	    l++;
322 	    continue;
323 
324 	case ')':
325 	    l--;
326 	    continue;
327 
328 	case ';':
329 	case '\n':
330 	    if (l != 0)
331 		break;
332 	    t = (struct command *) xcalloc(1, sizeof(*t));
333 	    t->t_dtyp = NODE_LIST;
334 	    t->t_dcar = syn1a(p1, p, flags);
335 	    t->t_dcdr = syntax(p->next, p2, flags);
336 	    if (t->t_dcdr == 0)
337 		t->t_dcdr = t->t_dcar, t->t_dcar = 0;
338 	    return (t);
339 
340 	default:
341 	    break;
342 	}
343     return (syn1a(p1, p2, flags));
344 }
345 
346 /*
347  * syn1a
348  *	syn1b
349  *	syn1b || syn1a
350  */
351 static struct command *
352 syn1a(p1, p2, flags)
353     struct wordent *p1, *p2;
354     int     flags;
355 {
356     register struct wordent *p;
357     register struct command *t;
358     register int l = 0;
359 
360     for (p = p1; p != p2; p = p->next)
361 	switch (p->word[0]) {
362 
363 	case '(':
364 	    l++;
365 	    continue;
366 
367 	case ')':
368 	    l--;
369 	    continue;
370 
371 	case '|':
372 	    if (p->word[1] != '|')
373 		continue;
374 	    if (l == 0) {
375 		t = (struct command *) xcalloc(1, sizeof(*t));
376 		t->t_dtyp = NODE_OR;
377 		t->t_dcar = syn1b(p1, p, flags);
378 		t->t_dcdr = syn1a(p->next, p2, flags);
379 		t->t_dflg = 0;
380 		return (t);
381 	    }
382 	    continue;
383 
384 	default:
385 	    break;
386 	}
387     return (syn1b(p1, p2, flags));
388 }
389 
390 /*
391  * syn1b
392  *	syn2
393  *	syn2 && syn1b
394  */
395 static struct command *
396 syn1b(p1, p2, flags)
397     struct wordent *p1, *p2;
398     int     flags;
399 {
400     register struct wordent *p;
401     register struct command *t;
402     register int l = 0;
403 
404     for (p = p1; p != p2; p = p->next)
405 	switch (p->word[0]) {
406 
407 	case '(':
408 	    l++;
409 	    continue;
410 
411 	case ')':
412 	    l--;
413 	    continue;
414 
415 	case '&':
416 	    if (p->word[1] == '&' && l == 0) {
417 		t = (struct command *) xcalloc(1, sizeof(*t));
418 		t->t_dtyp = NODE_AND;
419 		t->t_dcar = syn2(p1, p, flags);
420 		t->t_dcdr = syn1b(p->next, p2, flags);
421 		t->t_dflg = 0;
422 		return (t);
423 	    }
424 	    continue;
425 
426 	default:
427 	    break;
428 	}
429     return (syn2(p1, p2, flags));
430 }
431 
432 /*
433  * syn2
434  *	syn3
435  *	syn3 | syn2
436  *	syn3 |& syn2
437  */
438 static struct command *
439 syn2(p1, p2, flags)
440     struct wordent *p1, *p2;
441     int     flags;
442 {
443     register struct wordent *p, *pn;
444     register struct command *t;
445     register int l = 0;
446     int     f;
447 
448     for (p = p1; p != p2; p = p->next)
449 	switch (p->word[0]) {
450 
451 	case '(':
452 	    l++;
453 	    continue;
454 
455 	case ')':
456 	    l--;
457 	    continue;
458 
459 	case '|':
460 	    if (l != 0)
461 		continue;
462 	    t = (struct command *) xcalloc(1, sizeof(*t));
463 	    f = flags | P_OUT;
464 	    pn = p->next;
465 	    if (pn != p2 && pn->word[0] == '&') {
466 		f |= P_DIAG;
467 		t->t_dflg |= F_STDERR;
468 	    }
469 	    t->t_dtyp = NODE_PIPE;
470 	    t->t_dcar = syn3(p1, p, f);
471 	    if (pn != p2 && pn->word[0] == '&')
472 		p = pn;
473 	    t->t_dcdr = syn2(p->next, p2, flags | P_IN);
474 	    return (t);
475 
476 	default:
477 	    break;
478 	}
479     return (syn3(p1, p2, flags));
480 }
481 
482 static char RELPAR[] = {'<', '>', '(', ')', '\0'};
483 
484 /*
485  * syn3
486  *	( syn0 ) [ < in  ] [ > out ]
487  *	word word* [ < in ] [ > out ]
488  *	KEYWORD ( word* ) word* [ < in ] [ > out ]
489  *
490  *	KEYWORD = (@ exit foreach if set switch test while)
491  */
492 static struct command *
493 syn3(p1, p2, flags)
494     struct wordent *p1, *p2;
495     int     flags;
496 {
497     register struct wordent *p;
498     struct wordent *lp, *rp;
499     register struct command *t;
500     register int l;
501     Char  **av;
502     int     n, c;
503     bool    specp = 0;
504 
505     if (p1 != p2) {
506 	p = p1;
507 again:
508 	switch (srchx(p->word)) {
509 
510 	case TC_ELSE:
511 	    p = p->next;
512 	    if (p != p2)
513 		goto again;
514 	    break;
515 
516 	case TC_EXIT:
517 	case TC_FOREACH:
518 	case TC_IF:
519 	case TC_LET:
520 	case TC_SET:
521 	case TC_SWITCH:
522 	case TC_WHILE:
523 	    specp = 1;
524 	    break;
525 	default:
526 	    break;
527 	}
528     }
529     n = 0;
530     l = 0;
531     for (p = p1; p != p2; p = p->next)
532 	switch (p->word[0]) {
533 
534 	case '(':
535 	    if (specp)
536 		n++;
537 	    l++;
538 	    continue;
539 
540 	case ')':
541 	    if (specp)
542 		n++;
543 	    l--;
544 	    continue;
545 
546 	case '>':
547 	case '<':
548 	    if (l != 0) {
549 		if (specp)
550 		    n++;
551 		continue;
552 	    }
553 	    if (p->next == p2)
554 		continue;
555 	    if (any(RELPAR, p->next->word[0]))
556 		continue;
557 	    n--;
558 	    continue;
559 
560 	default:
561 	    if (!specp && l != 0)
562 		continue;
563 	    n++;
564 	    continue;
565 	}
566     if (n < 0)
567 	n = 0;
568     t = (struct command *) xcalloc(1, sizeof(*t));
569     av = (Char **) xcalloc((size_t) (n + 1), sizeof(Char **));
570     t->t_dcom = av;
571     n = 0;
572     if (p2->word[0] == ')')
573 	t->t_dflg = F_NOFORK;
574     lp = 0;
575     rp = 0;
576     l = 0;
577     for (p = p1; p != p2; p = p->next) {
578 	c = p->word[0];
579 	switch (c) {
580 
581 	case '(':
582 	    if (l == 0) {
583 		if (lp != 0 && !specp)
584 		    seterror(ERR_BADPLP);
585 		lp = p->next;
586 	    }
587 	    l++;
588 	    goto savep;
589 
590 	case ')':
591 	    l--;
592 	    if (l == 0)
593 		rp = p;
594 	    goto savep;
595 
596 	case '>':
597 	    if (l != 0)
598 		goto savep;
599 	    if (p->word[1] == '>')
600 		t->t_dflg |= F_APPEND;
601 	    if (p->next != p2 && eq(p->next->word, STRand)) {
602 		t->t_dflg |= F_STDERR, p = p->next;
603 		if (flags & (P_OUT | P_DIAG)) {
604 		    seterror(ERR_OUTRED);
605 		    continue;
606 		}
607 	    }
608 	    if (p->next != p2 && eq(p->next->word, STRbang))
609 		t->t_dflg |= F_OVERWRITE, p = p->next;
610 	    if (p->next == p2) {
611 		seterror(ERR_MISRED);
612 		continue;
613 	    }
614 	    p = p->next;
615 	    if (any(RELPAR, p->word[0])) {
616 		seterror(ERR_MISRED);
617 		continue;
618 	    }
619 	    if (((flags & P_OUT) && (flags & P_DIAG) == 0) || t->t_drit)
620 		seterror(ERR_OUTRED);
621 	    else
622 		t->t_drit = Strsave(p->word);
623 	    continue;
624 
625 	case '<':
626 	    if (l != 0)
627 		goto savep;
628 	    if (p->word[1] == '<')
629 		t->t_dflg |= F_READ;
630 	    if (p->next == p2) {
631 		seterror(ERR_MISRED);
632 		continue;
633 	    }
634 	    p = p->next;
635 	    if (any(RELPAR, p->word[0])) {
636 		seterror(ERR_MISRED);
637 		continue;
638 	    }
639 	    if ((flags & P_HERE) && (t->t_dflg & F_READ))
640 		seterror(ERR_REDPAR);
641 	    else if ((flags & P_IN) || t->t_dlef)
642 		seterror(ERR_INRED);
643 	    else
644 		t->t_dlef = Strsave(p->word);
645 	    continue;
646 
647     savep:
648 	    if (!specp)
649 		continue;
650 	default:
651 	    if (l != 0 && !specp)
652 		continue;
653 	    if (seterr == 0)
654 		av[n] = Strsave(p->word);
655 	    n++;
656 	    continue;
657 	}
658     }
659     if (lp != 0 && !specp) {
660 	if (n != 0)
661 	    seterror(ERR_BADPLPS);
662 	t->t_dtyp = NODE_PAREN;
663 	t->t_dspr = syn0(lp, rp, P_HERE);
664     }
665     else {
666 	if (n == 0)
667 	    seterror(ERR_NULLCOM);
668 	t->t_dtyp = NODE_COMMAND;
669     }
670     return (t);
671 }
672 
673 void
674 freesyn(t)
675     register struct command *t;
676 {
677     register Char **v;
678 
679     if (t == 0)
680 	return;
681     switch (t->t_dtyp) {
682 
683     case NODE_COMMAND:
684 	for (v = t->t_dcom; *v; v++)
685 	    xfree((ptr_t) * v);
686 	xfree((ptr_t) (t->t_dcom));
687 	xfree((ptr_t) t->t_dlef);
688 	xfree((ptr_t) t->t_drit);
689 	break;
690     case NODE_PAREN:
691 	freesyn(t->t_dspr);
692 	xfree((ptr_t) t->t_dlef);
693 	xfree((ptr_t) t->t_drit);
694 	break;
695 
696     case NODE_AND:
697     case NODE_OR:
698     case NODE_PIPE:
699     case NODE_LIST:
700 	freesyn(t->t_dcar), freesyn(t->t_dcdr);
701 	break;
702     default:
703 	break;
704     }
705     xfree((ptr_t) t);
706 }
707