xref: /original-bsd/bin/csh/parse.c (revision 36940495)
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
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
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
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
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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 *
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
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