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