xref: /netbsd-src/bin/csh/parse.c (revision 1f2744e6e4915c9da2a3f980279398c4cf7d5e6d)
1 /*	$NetBSD: parse.c,v 1.6 1995/03/21 09:03:10 cgd Exp $	*/
2 
3 /*-
4  * Copyright (c) 1980, 1991, 1993
5  *	The Regents of the University of California.  All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. All advertising materials mentioning features or use of this software
16  *    must display the following acknowledgement:
17  *	This product includes software developed by the University of
18  *	California, Berkeley and its contributors.
19  * 4. Neither the name of the University nor the names of its contributors
20  *    may be used to endorse or promote products derived from this software
21  *    without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33  * SUCH DAMAGE.
34  */
35 
36 #ifndef lint
37 #if 0
38 static char sccsid[] = "@(#)parse.c	8.1 (Berkeley) 5/31/93";
39 #else
40 static char rcsid[] = "$NetBSD: parse.c,v 1.6 1995/03/21 09:03:10 cgd Exp $";
41 #endif
42 #endif /* not lint */
43 
44 #include <sys/types.h>
45 #include <stdlib.h>
46 #include <string.h>
47 #if __STDC__
48 # include <stdarg.h>
49 #else
50 # include <varargs.h>
51 #endif
52 
53 #include "csh.h"
54 #include "extern.h"
55 
56 static void	 asyntax __P((struct wordent *, struct wordent *));
57 static void	 asyn0 __P((struct wordent *, struct wordent *));
58 static void	 asyn3 __P((struct wordent *, struct wordent *));
59 static struct wordent
60 		*freenod __P((struct wordent *, struct wordent *));
61 static struct command
62 		*syn0 __P((struct wordent *, struct wordent *, int));
63 static struct command
64 		*syn1 __P((struct wordent *, struct wordent *, int));
65 static struct command
66 		*syn1a __P((struct wordent *, struct wordent *, int));
67 static struct command
68 		*syn1b __P((struct wordent *, struct wordent *, int));
69 static struct command
70 		*syn2 __P((struct wordent *, struct wordent *, int));
71 static struct command
72 		*syn3 __P((struct wordent *, struct wordent *, int));
73 
74 #define ALEFT	21		/* max of 20 alias expansions	 */
75 #define HLEFT	11		/* max of 10 history expansions	 */
76 /*
77  * Perform aliasing on the word list lex
78  * Do a (very rudimentary) parse to separate into commands.
79  * If word 0 of a command has an alias, do it.
80  * Repeat a maximum of 20 times.
81  */
82 static int aleft;
83 extern int hleft;
84 void
85 alias(lex)
86     register struct wordent *lex;
87 {
88     jmp_buf osetexit;
89 
90     aleft = ALEFT;
91     hleft = HLEFT;
92     getexit(osetexit);
93     (void) setexit();
94     if (haderr) {
95 	resexit(osetexit);
96 	reset();
97     }
98     if (--aleft == 0)
99 	stderror(ERR_ALIASLOOP);
100     asyntax(lex->next, lex);
101     resexit(osetexit);
102 }
103 
104 static void
105 asyntax(p1, p2)
106     register struct wordent *p1, *p2;
107 {
108     while (p1 != p2)
109 	if (any(";&\n", p1->word[0]))
110 	    p1 = p1->next;
111 	else {
112 	    asyn0(p1, p2);
113 	    return;
114 	}
115 }
116 
117 static void
118 asyn0(p1, p2)
119     struct wordent *p1;
120     register struct wordent *p2;
121 {
122     register struct wordent *p;
123     register int l = 0;
124 
125     for (p = p1; p != p2; p = p->next)
126 	switch (p->word[0]) {
127 
128 	case '(':
129 	    l++;
130 	    continue;
131 
132 	case ')':
133 	    l--;
134 	    if (l < 0)
135 		stderror(ERR_TOOMANYRP);
136 	    continue;
137 
138 	case '>':
139 	    if (p->next != p2 && eq(p->next->word, STRand))
140 		p = p->next;
141 	    continue;
142 
143 	case '&':
144 	case '|':
145 	case ';':
146 	case '\n':
147 	    if (l != 0)
148 		continue;
149 	    asyn3(p1, p);
150 	    asyntax(p->next, p2);
151 	    return;
152 	}
153     if (l == 0)
154 	asyn3(p1, p2);
155 }
156 
157 static void
158 asyn3(p1, p2)
159     struct wordent *p1;
160     register struct wordent *p2;
161 {
162     register struct varent *ap;
163     struct wordent alout;
164     register bool redid;
165 
166     if (p1 == p2)
167 	return;
168     if (p1->word[0] == '(') {
169 	for (p2 = p2->prev; p2->word[0] != ')'; p2 = p2->prev)
170 	    if (p2 == p1)
171 		return;
172 	if (p2 == p1->next)
173 	    return;
174 	asyn0(p1->next, p2);
175 	return;
176     }
177     ap = adrof1(p1->word, &aliases);
178     if (ap == 0)
179 	return;
180     alhistp = p1->prev;
181     alhistt = p2;
182     alvec = ap->vec;
183     redid = lex(&alout);
184     alhistp = alhistt = 0;
185     alvec = 0;
186     if (seterr) {
187 	freelex(&alout);
188 	stderror(ERR_OLD);
189     }
190     if (p1->word[0] && eq(p1->word, alout.next->word)) {
191 	Char   *cp = alout.next->word;
192 
193 	alout.next->word = Strspl(STRQNULL, cp);
194 	xfree((ptr_t) cp);
195     }
196     p1 = freenod(p1, redid ? p2 : p1->next);
197     if (alout.next != &alout) {
198 	p1->next->prev = alout.prev->prev;
199 	alout.prev->prev->next = p1->next;
200 	alout.next->prev = p1;
201 	p1->next = alout.next;
202 	xfree((ptr_t) alout.prev->word);
203 	xfree((ptr_t) (alout.prev));
204     }
205     reset();			/* throw! */
206 }
207 
208 static struct wordent *
209 freenod(p1, p2)
210     register struct wordent *p1, *p2;
211 {
212     register struct wordent *retp = p1->prev;
213 
214     while (p1 != p2) {
215 	xfree((ptr_t) p1->word);
216 	p1 = p1->next;
217 	xfree((ptr_t) (p1->prev));
218     }
219     retp->next = p2;
220     p2->prev = retp;
221     return (retp);
222 }
223 
224 #define	PHERE	1
225 #define	PIN	2
226 #define	POUT	4
227 #define	PERR	8
228 
229 /*
230  * syntax
231  *	empty
232  *	syn0
233  */
234 struct command *
235 syntax(p1, p2, flags)
236     register struct wordent *p1, *p2;
237     int     flags;
238 {
239 
240     while (p1 != p2)
241 	if (any(";&\n", p1->word[0]))
242 	    p1 = p1->next;
243 	else
244 	    return (syn0(p1, p2, flags));
245     return (0);
246 }
247 
248 /*
249  * syn0
250  *	syn1
251  *	syn1 & syntax
252  */
253 static struct command *
254 syn0(p1, p2, flags)
255     struct wordent *p1, *p2;
256     int     flags;
257 {
258     register struct wordent *p;
259     register struct command *t, *t1;
260     int     l;
261 
262     l = 0;
263     for (p = p1; p != p2; p = p->next)
264 	switch (p->word[0]) {
265 
266 	case '(':
267 	    l++;
268 	    continue;
269 
270 	case ')':
271 	    l--;
272 	    if (l < 0)
273 		seterror(ERR_TOOMANYRP);
274 	    continue;
275 
276 	case '|':
277 	    if (p->word[1] == '|')
278 		continue;
279 	    /* fall into ... */
280 
281 	case '>':
282 	    if (p->next != p2 && eq(p->next->word, STRand))
283 		p = p->next;
284 	    continue;
285 
286 	case '&':
287 	    if (l != 0)
288 		break;
289 	    if (p->word[1] == '&')
290 		continue;
291 	    t1 = syn1(p1, p, flags);
292 	    if (t1->t_dtyp == NODE_LIST ||
293 		t1->t_dtyp == NODE_AND ||
294 		t1->t_dtyp == NODE_OR) {
295 		t = (struct command *) xcalloc(1, sizeof(*t));
296 		t->t_dtyp = NODE_PAREN;
297 		t->t_dflg = F_AMPERSAND | F_NOINTERRUPT;
298 		t->t_dspr = t1;
299 		t1 = t;
300 	    }
301 	    else
302 		t1->t_dflg |= F_AMPERSAND | F_NOINTERRUPT;
303 	    t = (struct command *) xcalloc(1, sizeof(*t));
304 	    t->t_dtyp = NODE_LIST;
305 	    t->t_dflg = 0;
306 	    t->t_dcar = t1;
307 	    t->t_dcdr = syntax(p, p2, flags);
308 	    return (t);
309 	}
310     if (l == 0)
311 	return (syn1(p1, p2, flags));
312     seterror(ERR_TOOMANYLP);
313     return (0);
314 }
315 
316 /*
317  * syn1
318  *	syn1a
319  *	syn1a ; syntax
320  */
321 static struct command *
322 syn1(p1, p2, flags)
323     struct wordent *p1, *p2;
324     int     flags;
325 {
326     register struct wordent *p;
327     register struct command *t;
328     int     l;
329 
330     l = 0;
331     for (p = p1; p != p2; p = p->next)
332 	switch (p->word[0]) {
333 
334 	case '(':
335 	    l++;
336 	    continue;
337 
338 	case ')':
339 	    l--;
340 	    continue;
341 
342 	case ';':
343 	case '\n':
344 	    if (l != 0)
345 		break;
346 	    t = (struct command *) xcalloc(1, sizeof(*t));
347 	    t->t_dtyp = NODE_LIST;
348 	    t->t_dcar = syn1a(p1, p, flags);
349 	    t->t_dcdr = syntax(p->next, p2, flags);
350 	    if (t->t_dcdr == 0)
351 		t->t_dcdr = t->t_dcar, t->t_dcar = 0;
352 	    return (t);
353 	}
354     return (syn1a(p1, p2, flags));
355 }
356 
357 /*
358  * syn1a
359  *	syn1b
360  *	syn1b || syn1a
361  */
362 static struct command *
363 syn1a(p1, p2, flags)
364     struct wordent *p1, *p2;
365     int     flags;
366 {
367     register struct wordent *p;
368     register struct command *t;
369     register int l = 0;
370 
371     for (p = p1; p != p2; p = p->next)
372 	switch (p->word[0]) {
373 
374 	case '(':
375 	    l++;
376 	    continue;
377 
378 	case ')':
379 	    l--;
380 	    continue;
381 
382 	case '|':
383 	    if (p->word[1] != '|')
384 		continue;
385 	    if (l == 0) {
386 		t = (struct command *) xcalloc(1, sizeof(*t));
387 		t->t_dtyp = NODE_OR;
388 		t->t_dcar = syn1b(p1, p, flags);
389 		t->t_dcdr = syn1a(p->next, p2, flags);
390 		t->t_dflg = 0;
391 		return (t);
392 	    }
393 	    continue;
394 	}
395     return (syn1b(p1, p2, flags));
396 }
397 
398 /*
399  * syn1b
400  *	syn2
401  *	syn2 && syn1b
402  */
403 static struct command *
404 syn1b(p1, p2, flags)
405     struct wordent *p1, *p2;
406     int     flags;
407 {
408     register struct wordent *p;
409     register struct command *t;
410     register int l = 0;
411 
412     for (p = p1; p != p2; p = p->next)
413 	switch (p->word[0]) {
414 
415 	case '(':
416 	    l++;
417 	    continue;
418 
419 	case ')':
420 	    l--;
421 	    continue;
422 
423 	case '&':
424 	    if (p->word[1] == '&' && l == 0) {
425 		t = (struct command *) xcalloc(1, sizeof(*t));
426 		t->t_dtyp = NODE_AND;
427 		t->t_dcar = syn2(p1, p, flags);
428 		t->t_dcdr = syn1b(p->next, p2, flags);
429 		t->t_dflg = 0;
430 		return (t);
431 	    }
432 	    continue;
433 	}
434     return (syn2(p1, p2, flags));
435 }
436 
437 /*
438  * syn2
439  *	syn3
440  *	syn3 | syn2
441  *	syn3 |& syn2
442  */
443 static struct command *
444 syn2(p1, p2, flags)
445     struct wordent *p1, *p2;
446     int     flags;
447 {
448     register struct wordent *p, *pn;
449     register struct command *t;
450     register int l = 0;
451     int     f;
452 
453     for (p = p1; p != p2; p = p->next)
454 	switch (p->word[0]) {
455 
456 	case '(':
457 	    l++;
458 	    continue;
459 
460 	case ')':
461 	    l--;
462 	    continue;
463 
464 	case '|':
465 	    if (l != 0)
466 		continue;
467 	    t = (struct command *) xcalloc(1, sizeof(*t));
468 	    f = flags | POUT;
469 	    pn = p->next;
470 	    if (pn != p2 && pn->word[0] == '&') {
471 		f |= PERR;
472 		t->t_dflg |= F_STDERR;
473 	    }
474 	    t->t_dtyp = NODE_PIPE;
475 	    t->t_dcar = syn3(p1, p, f);
476 	    if (pn != p2 && pn->word[0] == '&')
477 		p = pn;
478 	    t->t_dcdr = syn2(p->next, p2, flags | PIN);
479 	    return (t);
480 	}
481     return (syn3(p1, p2, flags));
482 }
483 
484 static char RELPAR[] = {'<', '>', '(', ')', '\0'};
485 
486 /*
487  * syn3
488  *	( syn0 ) [ < in  ] [ > out ]
489  *	word word* [ < in ] [ > out ]
490  *	KEYWORD ( word* ) word* [ < in ] [ > out ]
491  *
492  *	KEYWORD = (@ exit foreach if set switch test while)
493  */
494 static struct command *
495 syn3(p1, p2, flags)
496     struct wordent *p1, *p2;
497     int     flags;
498 {
499     register struct wordent *p;
500     struct wordent *lp, *rp;
501     register struct command *t;
502     register int l;
503     Char  **av;
504     int     n, c;
505     bool    specp = 0;
506 
507     if (p1 != p2) {
508 	p = p1;
509 again:
510 	switch (srchx(p->word)) {
511 
512 	case T_ELSE:
513 	    p = p->next;
514 	    if (p != p2)
515 		goto again;
516 	    break;
517 
518 	case T_EXIT:
519 	case T_FOREACH:
520 	case T_IF:
521 	case T_LET:
522 	case T_SET:
523 	case T_SWITCH:
524 	case T_WHILE:
525 	    specp = 1;
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 & (POUT | PERR)) {
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 & POUT) && ((flags & PERR) == 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 & PHERE) && (t->t_dflg & F_READ))
640 		seterror(ERR_REDPAR);
641 	    else if ((flags & PIN) || 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, PHERE);
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     }
703     xfree((ptr_t) t);
704 }
705