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