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