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