xref: /csrg-svn/bin/csh/parse.c (revision 47724)
121939Sdist /*
221939Sdist  * Copyright (c) 1980 Regents of the University of California.
322538Sedward  * All rights reserved.  The Berkeley Software License Agreement
421939Sdist  * specifies the terms and conditions for redistribution.
521939Sdist  */
621939Sdist 
717511Sedward #ifndef lint
8*47724Sbostic static char *sccsid = "@(#)parse.c	5.5 (Berkeley) 04/01/91";
922538Sedward #endif
101301Sbill 
111301Sbill #include "sh.h"
121301Sbill 
131301Sbill /*
141301Sbill  * C shell
151301Sbill  */
161301Sbill 
171301Sbill /*
181301Sbill  * Perform aliasing on the word list lex
191301Sbill  * Do a (very rudimentary) parse to separate into commands.
201301Sbill  * If word 0 of a command has an alias, do it.
211301Sbill  * Repeat a maximum of 20 times.
221301Sbill  */
231301Sbill alias(lex)
241301Sbill 	register struct wordent *lex;
251301Sbill {
261301Sbill 	int aleft = 21;
271301Sbill 	jmp_buf osetexit;
281301Sbill 
291301Sbill 	getexit(osetexit);
30*47724Sbostic 	(void)setjmp(reslab);
311301Sbill 	if (haderr) {
321301Sbill 		resexit(osetexit);
33*47724Sbostic 		longjmp(reslab, 0);
341301Sbill 	}
351301Sbill 	if (--aleft == 0)
361301Sbill 		error("Alias loop");
371301Sbill 	asyntax(lex->next, lex);
381301Sbill 	resexit(osetexit);
391301Sbill }
401301Sbill 
411301Sbill asyntax(p1, p2)
421301Sbill 	register struct wordent *p1, *p2;
431301Sbill {
441301Sbill 
451301Sbill 	while (p1 != p2)
4647419Sbostic 		if (index(";&\n", p1->word[0]))
471301Sbill 			p1 = p1->next;
481301Sbill 		else {
491301Sbill 			asyn0(p1, p2);
501301Sbill 			return;
511301Sbill 		}
521301Sbill }
531301Sbill 
541301Sbill asyn0(p1, p2)
551301Sbill 	struct wordent *p1;
561301Sbill 	register struct wordent *p2;
571301Sbill {
581301Sbill 	register struct wordent *p;
591301Sbill 	register int l = 0;
601301Sbill 
611301Sbill 	for (p = p1; p != p2; p = p->next)
621301Sbill 		switch (p->word[0]) {
631301Sbill 
641301Sbill 		case '(':
651301Sbill 			l++;
661301Sbill 			continue;
671301Sbill 
681301Sbill 		case ')':
691301Sbill 			l--;
701301Sbill 			if (l < 0)
711301Sbill 				error("Too many )'s");
721301Sbill 			continue;
731301Sbill 
741301Sbill 		case '>':
751301Sbill 			if (p->next != p2 && eq(p->next->word, "&"))
761301Sbill 				p = p->next;
771301Sbill 			continue;
781301Sbill 
791301Sbill 		case '&':
801301Sbill 		case '|':
811301Sbill 		case ';':
821301Sbill 		case '\n':
831301Sbill 			if (l != 0)
841301Sbill 				continue;
851301Sbill 			asyn3(p1, p);
861301Sbill 			asyntax(p->next, p2);
871301Sbill 			return;
881301Sbill 		}
891301Sbill 	if (l == 0)
901301Sbill 		asyn3(p1, p2);
911301Sbill }
921301Sbill 
931301Sbill asyn3(p1, p2)
941301Sbill 	struct wordent *p1;
951301Sbill 	register struct wordent *p2;
961301Sbill {
971301Sbill 	register struct varent *ap;
981301Sbill 	struct wordent alout;
991301Sbill 	register bool redid;
1001301Sbill 
1011301Sbill 	if (p1 == p2)
1021301Sbill 		return;
1031301Sbill 	if (p1->word[0] == '(') {
1041301Sbill 		for (p2 = p2->prev; p2->word[0] != ')'; p2 = p2->prev)
1051301Sbill 			if (p2 == p1)
1061301Sbill 				return;
1071301Sbill 		if (p2 == p1->next)
1081301Sbill 			return;
1091301Sbill 		asyn0(p1->next, p2);
1101301Sbill 		return;
1111301Sbill 	}
1121301Sbill 	ap = adrof1(p1->word, &aliases);
1131301Sbill 	if (ap == 0)
1141301Sbill 		return;
1151301Sbill 	alhistp = p1->prev;
1161301Sbill 	alhistt = p2;
1171301Sbill 	alvec = ap->vec;
1181301Sbill 	redid = lex(&alout);
1191301Sbill 	alhistp = alhistt = 0;
1201301Sbill 	alvec = 0;
1211301Sbill 	if (err) {
1221301Sbill 		freelex(&alout);
1231301Sbill 		error(err);
1241301Sbill 	}
1251301Sbill 	if (p1->word[0] && eq(p1->word, alout.next->word)) {
1261301Sbill 		char *cp = alout.next->word;
1271301Sbill 
1281301Sbill 		alout.next->word = strspl("\200", cp);
12917511Sedward 		XFREE(cp)
1301301Sbill 	}
1311301Sbill 	p1 = freenod(p1, redid ? p2 : p1->next);
1321301Sbill 	if (alout.next != &alout) {
1331301Sbill 		p1->next->prev = alout.prev->prev;
1341301Sbill 		alout.prev->prev->next = p1->next;
1351301Sbill 		alout.next->prev = p1;
1361301Sbill 		p1->next = alout.next;
13717511Sedward 		XFREE(alout.prev->word)
13817511Sedward 		XFREE((char *)alout.prev)
1391301Sbill 	}
140*47724Sbostic 	longjmp(reslab, 0);		/* throw! */
1411301Sbill }
1421301Sbill 
1431301Sbill struct wordent *
1441301Sbill freenod(p1, p2)
1451301Sbill 	register struct wordent *p1, *p2;
1461301Sbill {
1471301Sbill 	register struct wordent *retp = p1->prev;
1481301Sbill 
1491301Sbill 	while (p1 != p2) {
15017511Sedward 		XFREE(p1->word)
1511301Sbill 		p1 = p1->next;
15217511Sedward 		XFREE((char *)p1->prev)
1531301Sbill 	}
1541301Sbill 	retp->next = p2;
1551301Sbill 	p2->prev = retp;
1561301Sbill 	return (retp);
1571301Sbill }
1581301Sbill 
1591301Sbill #define	PHERE	1
1601301Sbill #define	PIN	2
1611301Sbill #define	POUT	4
1621301Sbill #define	PDIAG	8
1631301Sbill 
1641301Sbill /*
1651301Sbill  * syntax
1661301Sbill  *	empty
1671301Sbill  *	syn0
1681301Sbill  */
1691301Sbill struct command *
1701301Sbill syntax(p1, p2, flags)
1711301Sbill 	register struct wordent *p1, *p2;
1721301Sbill 	int flags;
1731301Sbill {
1741301Sbill 
1751301Sbill 	while (p1 != p2)
17647419Sbostic 		if (index(";&\n", p1->word[0]))
1771301Sbill 			p1 = p1->next;
1781301Sbill 		else
1791301Sbill 			return (syn0(p1, p2, flags));
1801301Sbill 	return (0);
1811301Sbill }
1821301Sbill 
1831301Sbill /*
1841301Sbill  * syn0
1851301Sbill  *	syn1
1861301Sbill  *	syn1 & syntax
1871301Sbill  */
1881301Sbill struct command *
1891301Sbill syn0(p1, p2, flags)
1901301Sbill 	struct wordent *p1, *p2;
1911301Sbill 	int flags;
1921301Sbill {
1931301Sbill 	register struct wordent *p;
1941301Sbill 	register struct command *t, *t1;
1951301Sbill 	int l;
1961301Sbill 
1971301Sbill 	l = 0;
1981301Sbill 	for (p = p1; p != p2; p = p->next)
1991301Sbill 		switch (p->word[0]) {
2001301Sbill 
2011301Sbill 		case '(':
2021301Sbill 			l++;
2031301Sbill 			continue;
2041301Sbill 
2051301Sbill 		case ')':
2061301Sbill 			l--;
2071301Sbill 			if (l < 0)
2081301Sbill 				seterr("Too many )'s");
2091301Sbill 			continue;
2101301Sbill 
2111301Sbill 		case '|':
2121301Sbill 			if (p->word[1] == '|')
2131301Sbill 				continue;
2141301Sbill 			/* fall into ... */
2151301Sbill 
2161301Sbill 		case '>':
2171301Sbill 			if (p->next != p2 && eq(p->next->word, "&"))
2181301Sbill 				p = p->next;
2191301Sbill 			continue;
2201301Sbill 
2211301Sbill 		case '&':
2221301Sbill 			if (l != 0)
2231301Sbill 				break;
2241301Sbill 			if (p->word[1] == '&')
2251301Sbill 				continue;
2261301Sbill 			t1 = syn1(p1, p, flags);
227*47724Sbostic     			if (t1->t_dtyp == NODE_LIST ||
228*47724Sbostic     			    t1->t_dtyp == NODE_AND ||
229*47724Sbostic     			    t1->t_dtyp == NODE_OR) {
2301301Sbill 				t = (struct command *) calloc(1, sizeof (*t));
231*47724Sbostic 				t->t_dtyp = NODE_PAREN;
232*47724Sbostic 				t->t_dflg = F_AMPERSAND|F_NOINTERRUPT;
2331301Sbill 				t->t_dspr = t1;
2341301Sbill 				t1 = t;
2351301Sbill 			} else
236*47724Sbostic 				t1->t_dflg |= F_AMPERSAND|F_NOINTERRUPT;
2371301Sbill 			t = (struct command *) calloc(1, sizeof (*t));
238*47724Sbostic 			t->t_dtyp = NODE_LIST;
2391301Sbill 			t->t_dflg = 0;
2401301Sbill 			t->t_dcar = t1;
2411301Sbill 			t->t_dcdr = syntax(p, p2, flags);
2421301Sbill 			return(t);
2431301Sbill 		}
2441301Sbill 	if (l == 0)
2451301Sbill 		return (syn1(p1, p2, flags));
2461301Sbill 	seterr("Too many ('s");
2471301Sbill 	return (0);
2481301Sbill }
2491301Sbill 
2501301Sbill /*
2511301Sbill  * syn1
2521301Sbill  *	syn1a
2531301Sbill  *	syn1a ; syntax
2541301Sbill  */
2551301Sbill struct command *
2561301Sbill syn1(p1, p2, flags)
2571301Sbill 	struct wordent *p1, *p2;
2581301Sbill 	int flags;
2591301Sbill {
2601301Sbill 	register struct wordent *p;
2611301Sbill 	register struct command *t;
2621301Sbill 	int l;
2631301Sbill 
2641301Sbill 	l = 0;
2651301Sbill 	for (p = p1; p != p2; p = p->next)
2661301Sbill 		switch (p->word[0]) {
2671301Sbill 
2681301Sbill 		case '(':
2691301Sbill 			l++;
2701301Sbill 			continue;
2711301Sbill 
2721301Sbill 		case ')':
2731301Sbill 			l--;
2741301Sbill 			continue;
2751301Sbill 
2761301Sbill 		case ';':
2771301Sbill 		case '\n':
2781301Sbill 			if (l != 0)
2791301Sbill 				break;
2801301Sbill 			t = (struct command *) calloc(1, sizeof (*t));
281*47724Sbostic 			t->t_dtyp = NODE_LIST;
2821301Sbill 			t->t_dcar = syn1a(p1, p, flags);
2831301Sbill 			t->t_dcdr = syntax(p->next, p2, flags);
2841301Sbill 			if (t->t_dcdr == 0)
2851301Sbill 				t->t_dcdr = t->t_dcar, t->t_dcar = 0;
2861301Sbill 			return (t);
2871301Sbill 		}
2881301Sbill 	return (syn1a(p1, p2, flags));
2891301Sbill }
2901301Sbill 
2911301Sbill /*
2921301Sbill  * syn1a
2931301Sbill  *	syn1b
2941301Sbill  *	syn1b || syn1a
2951301Sbill  */
2961301Sbill struct command *
2971301Sbill syn1a(p1, p2, flags)
2981301Sbill 	struct wordent *p1, *p2;
2991301Sbill 	int flags;
3001301Sbill {
3011301Sbill 	register struct wordent *p;
3021301Sbill 	register struct command *t;
3031301Sbill 	register int l = 0;
3041301Sbill 
3051301Sbill 	for (p = p1; p != p2; p = p->next)
3061301Sbill 		switch (p->word[0]) {
3071301Sbill 
3081301Sbill 		case '(':
3091301Sbill 			l++;
3101301Sbill 			continue;
3111301Sbill 
3121301Sbill 		case ')':
3131301Sbill 			l--;
3141301Sbill 			continue;
3151301Sbill 
3161301Sbill 		case '|':
3171301Sbill 			if (p->word[1] != '|')
3181301Sbill 				continue;
3191301Sbill 			if (l == 0) {
3201301Sbill 				t = (struct command *) calloc(1, sizeof (*t));
321*47724Sbostic 				t->t_dtyp = NODE_OR;
3221301Sbill 				t->t_dcar = syn1b(p1, p, flags);
3231301Sbill 				t->t_dcdr = syn1a(p->next, p2, flags);
3241301Sbill 				t->t_dflg = 0;
3251301Sbill 				return (t);
3261301Sbill 			}
3271301Sbill 			continue;
3281301Sbill 		}
3291301Sbill 	return (syn1b(p1, p2, flags));
3301301Sbill }
3311301Sbill 
3321301Sbill /*
3331301Sbill  * syn1b
3341301Sbill  *	syn2
3351301Sbill  *	syn2 && syn1b
3361301Sbill  */
3371301Sbill struct command *
3381301Sbill syn1b(p1, p2, flags)
3391301Sbill 	struct wordent *p1, *p2;
3401301Sbill 	int flags;
3411301Sbill {
3421301Sbill 	register struct wordent *p;
3431301Sbill 	register struct command *t;
3441301Sbill 	register int l = 0;
3451301Sbill 
3461301Sbill 	l = 0;
3471301Sbill 	for (p = p1; p != p2; p = p->next)
3481301Sbill 		switch (p->word[0]) {
3491301Sbill 
3501301Sbill 		case '(':
3511301Sbill 			l++;
3521301Sbill 			continue;
3531301Sbill 
3541301Sbill 		case ')':
3551301Sbill 			l--;
3561301Sbill 			continue;
3571301Sbill 
3581301Sbill 		case '&':
3591301Sbill 			if (p->word[1] == '&' && l == 0) {
3601301Sbill 				t = (struct command *) calloc(1, sizeof (*t));
361*47724Sbostic 				t->t_dtyp = NODE_AND;
3621301Sbill 				t->t_dcar = syn2(p1, p, flags);
3631301Sbill 				t->t_dcdr = syn1b(p->next, p2, flags);
3641301Sbill 				t->t_dflg = 0;
3651301Sbill 				return (t);
3661301Sbill 			}
3671301Sbill 			continue;
3681301Sbill 		}
3691301Sbill 	return (syn2(p1, p2, flags));
3701301Sbill }
3711301Sbill 
3721301Sbill /*
3731301Sbill  * syn2
3741301Sbill  *	syn3
3751301Sbill  *	syn3 | syn2
3761301Sbill  *	syn3 |& syn2
3771301Sbill  */
3781301Sbill struct command *
3791301Sbill syn2(p1, p2, flags)
3801301Sbill 	struct wordent *p1, *p2;
3811301Sbill 	int flags;
3821301Sbill {
3831301Sbill 	register struct wordent *p, *pn;
3841301Sbill 	register struct command *t;
3851301Sbill 	register int l = 0;
3861301Sbill 	int f;
3871301Sbill 
3881301Sbill 	for (p = p1; p != p2; p = p->next)
3891301Sbill 		switch (p->word[0]) {
3901301Sbill 
3911301Sbill 		case '(':
3921301Sbill 			l++;
3931301Sbill 			continue;
3941301Sbill 
3951301Sbill 		case ')':
3961301Sbill 			l--;
3971301Sbill 			continue;
3981301Sbill 
3991301Sbill 		case '|':
4001301Sbill 			if (l != 0)
4011301Sbill 				continue;
4021301Sbill 			t = (struct command *) calloc(1, sizeof (*t));
4031301Sbill 			f = flags | POUT;
4041301Sbill 			pn = p->next;
4051301Sbill 			if (pn != p2 && pn->word[0] == '&') {
4061301Sbill 				f |= PDIAG;
407*47724Sbostic 				t->t_dflg |= F_STDERR;
4081301Sbill 			}
409*47724Sbostic 			t->t_dtyp = NODE_PIPE;
4101301Sbill 			t->t_dcar = syn3(p1, p, f);
4111301Sbill 			if (pn != p2 && pn->word[0] == '&')
4121301Sbill 				p = pn;
4131301Sbill 			t->t_dcdr = syn2(p->next, p2, flags | PIN);
4141301Sbill 			return (t);
4151301Sbill 		}
4161301Sbill 	return (syn3(p1, p2, flags));
4171301Sbill }
4181301Sbill 
4191301Sbill char	*RELPAR =	"<>()";
4201301Sbill 
4211301Sbill /*
4221301Sbill  * syn3
4231301Sbill  *	( syn0 ) [ < in  ] [ > out ]
4241301Sbill  *	word word* [ < in ] [ > out ]
4251301Sbill  *	KEYWORD ( word* ) word* [ < in ] [ > out ]
4261301Sbill  *
4271301Sbill  *	KEYWORD = (@ exit foreach if set switch test while)
4281301Sbill  */
4291301Sbill struct command *
4301301Sbill syn3(p1, p2, flags)
4311301Sbill 	struct wordent *p1, *p2;
4321301Sbill 	int flags;
4331301Sbill {
4341301Sbill 	register struct wordent *p;
4351301Sbill 	struct wordent *lp, *rp;
4361301Sbill 	register struct command *t;
4371301Sbill 	register int l;
4381301Sbill 	char **av;
4391301Sbill 	int n, c;
4401301Sbill 	bool specp = 0;
4411301Sbill 
4421301Sbill 	if (p1 != p2) {
4431301Sbill 		p = p1;
4441301Sbill again:
4451301Sbill 		switch (srchx(p->word)) {
4461301Sbill 
447*47724Sbostic 		case T_ELSE:
4481301Sbill 			p = p->next;
4491301Sbill 			if (p != p2)
4501301Sbill 				goto again;
4511301Sbill 			break;
4521301Sbill 
453*47724Sbostic 		case T_EXIT:
454*47724Sbostic 		case T_FOREACH:
455*47724Sbostic 		case T_IF:
456*47724Sbostic 		case T_LET:
457*47724Sbostic 		case T_SET:
458*47724Sbostic 		case T_SWITCH:
459*47724Sbostic 		case T_WHILE:
4601301Sbill 			specp = 1;
4611301Sbill 			break;
4621301Sbill 		}
4631301Sbill 	}
4641301Sbill 	n = 0;
4651301Sbill 	l = 0;
4661301Sbill 	for (p = p1; p != p2; p = p->next)
4671301Sbill 		switch (p->word[0]) {
4681301Sbill 
4691301Sbill 		case '(':
4701301Sbill 			if (specp)
4711301Sbill 				n++;
4721301Sbill 			l++;
4731301Sbill 			continue;
4741301Sbill 
4751301Sbill 		case ')':
4761301Sbill 			if (specp)
4771301Sbill 				n++;
4781301Sbill 			l--;
4791301Sbill 			continue;
4801301Sbill 
4811301Sbill 		case '>':
4821301Sbill 		case '<':
4831301Sbill 			if (l != 0) {
4841301Sbill 				if (specp)
4851301Sbill 					n++;
4861301Sbill 				continue;
4871301Sbill 			}
4881301Sbill 			if (p->next == p2)
4891301Sbill 				continue;
49047419Sbostic 			if (index(RELPAR, p->next->word[0]))
4911301Sbill 				continue;
4921301Sbill 			n--;
4931301Sbill 			continue;
4941301Sbill 
4951301Sbill 		default:
4961301Sbill 			if (!specp && l != 0)
4971301Sbill 				continue;
4981301Sbill 			n++;
4991301Sbill 			continue;
5001301Sbill 		}
5011301Sbill 	if (n < 0)
5021301Sbill 		n = 0;
5031301Sbill 	t = (struct command *) calloc(1, sizeof (*t));
50417511Sedward 	av = (char **) calloc((unsigned) (n + 1), sizeof (char **));
5051301Sbill 	t->t_dcom = av;
5061301Sbill 	n = 0;
5071301Sbill 	if (p2->word[0] == ')')
508*47724Sbostic 		t->t_dflg = F_NOFORK;
5091301Sbill 	lp = 0;
5101301Sbill 	rp = 0;
5111301Sbill 	l = 0;
5121301Sbill 	for (p = p1; p != p2; p = p->next) {
5131301Sbill 		c = p->word[0];
5141301Sbill 		switch (c) {
5151301Sbill 
5161301Sbill 		case '(':
5171301Sbill 			if (l == 0) {
5181301Sbill 				if (lp != 0 && !specp)
5191301Sbill 					seterr("Badly placed (");
5201301Sbill 				lp = p->next;
5211301Sbill 			}
5221301Sbill 			l++;
5231301Sbill 			goto savep;
5241301Sbill 
5251301Sbill 		case ')':
5261301Sbill 			l--;
5271301Sbill 			if (l == 0)
5281301Sbill 				rp = p;
5291301Sbill 			goto savep;
5301301Sbill 
5311301Sbill 		case '>':
5321301Sbill 			if (l != 0)
5331301Sbill 				goto savep;
5341301Sbill 			if (p->word[1] == '>')
535*47724Sbostic 				t->t_dflg |= F_APPEND;
5361301Sbill 			if (p->next != p2 && eq(p->next->word, "&")) {
537*47724Sbostic 				t->t_dflg |= F_STDERR;
538*47724Sbostic 				p = p->next;
5391301Sbill 				if (flags & (POUT|PDIAG))
5401301Sbill 					goto badout;
5411301Sbill 			}
542*47724Sbostic 			if (p->next != p2 && eq(p->next->word, "!")) {
543*47724Sbostic 				t->t_dflg |= F_OVERWRITE;
544*47724Sbostic 				p = p->next;
545*47724Sbostic 			}
5461301Sbill 			if (p->next == p2) {
5471301Sbill missfile:
5481301Sbill 				seterr("Missing name for redirect");
5491301Sbill 				continue;
5501301Sbill 			}
5511301Sbill 			p = p->next;
55247419Sbostic 			if (index(RELPAR, p->word[0]))
5531301Sbill 				goto missfile;
5541301Sbill 			if ((flags & POUT) && (flags & PDIAG) == 0 || t->t_drit)
5551301Sbill badout:
5561301Sbill 				seterr("Ambiguous output redirect");
5571301Sbill 			else
5581301Sbill 				t->t_drit = savestr(p->word);
5591301Sbill 			continue;
5601301Sbill 
5611301Sbill 		case '<':
5621301Sbill 			if (l != 0)
5631301Sbill 				goto savep;
5641301Sbill 			if (p->word[1] == '<')
565*47724Sbostic 				t->t_dflg |= F_READ;
5661301Sbill 			if (p->next == p2)
5671301Sbill 				goto missfile;
5681301Sbill 			p = p->next;
56947419Sbostic 			if (index(RELPAR, p->word[0]))
5701301Sbill 				goto missfile;
571*47724Sbostic 			if ((flags & PHERE) && (t->t_dflg & F_READ))
5721301Sbill 				seterr("Can't << within ()'s");
5731301Sbill 			else if ((flags & PIN) || t->t_dlef)
5741301Sbill 				seterr("Ambiguous input redirect");
5751301Sbill 			else
5761301Sbill 				t->t_dlef = savestr(p->word);
5771301Sbill 			continue;
5781301Sbill 
5791301Sbill savep:
5801301Sbill 			if (!specp)
5811301Sbill 				continue;
5821301Sbill 		default:
5831301Sbill 			if (l != 0 && !specp)
5841301Sbill 				continue;
5851301Sbill 			if (err == 0)
5861301Sbill 				av[n] = savestr(p->word);
5871301Sbill 			n++;
5881301Sbill 			continue;
5891301Sbill 		}
5901301Sbill 	}
5911301Sbill 	if (lp != 0 && !specp) {
5921301Sbill 		if (n != 0)
5931301Sbill 			seterr("Badly placed ()'s");
594*47724Sbostic 		t->t_dtyp = NODE_PAREN;
5951301Sbill 		t->t_dspr = syn0(lp, rp, PHERE);
5961301Sbill 	} else {
5971301Sbill 		if (n == 0)
5981301Sbill 			seterr("Invalid null command");
599*47724Sbostic 		t->t_dtyp = NODE_COMMAND;
6001301Sbill 	}
6011301Sbill 	return (t);
6021301Sbill }
6031301Sbill 
6041301Sbill freesyn(t)
6051301Sbill 	register struct command *t;
6061301Sbill {
6071301Sbill 	register char **v;
6081301Sbill 
6091301Sbill 	if (t == 0)
6101301Sbill 		return;
6111301Sbill 	switch (t->t_dtyp) {
6121301Sbill 
613*47724Sbostic 	case NODE_COMMAND:
6141301Sbill 		for (v = t->t_dcom; *v; v++)
61517511Sedward 			XFREE(*v)
61617511Sedward 		XFREE((char *)t->t_dcom)
6171301Sbill 		goto lr;
6181301Sbill 
619*47724Sbostic 	case NODE_PAREN:
6201301Sbill 		freesyn(t->t_dspr);
6211301Sbill 		/* fall into ... */
6221301Sbill 
6231301Sbill lr:
62417511Sedward 		XFREE(t->t_dlef)
62517511Sedward 		XFREE(t->t_drit)
6261301Sbill 		break;
6271301Sbill 
628*47724Sbostic 	case NODE_AND:
629*47724Sbostic 	case NODE_OR:
630*47724Sbostic 	case NODE_PIPE:
631*47724Sbostic 	case NODE_LIST:
632*47724Sbostic 		freesyn(t->t_dcar);
633*47724Sbostic 		freesyn(t->t_dcdr);
6341301Sbill 		break;
6351301Sbill 	}
63617511Sedward 	XFREE((char *)t)
6371301Sbill }
638