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