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