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