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