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