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