xref: /csrg-svn/bin/csh/parse.c (revision 47823)
1*47823Sbostic /*-
2*47823Sbostic  * Copyright (c) 1980, 1991 The Regents of the University of California.
3*47823Sbostic  * All rights reserved.
4*47823Sbostic  *
5*47823Sbostic  * %sccs.include.redist.c%
621939Sdist  */
721939Sdist 
817511Sedward #ifndef lint
9*47823Sbostic static char sccsid[] = "@(#)parse.c	5.6 (Berkeley) 04/04/91";
10*47823Sbostic #endif /* not lint */
111301Sbill 
121301Sbill #include "sh.h"
131301Sbill 
141301Sbill /*
151301Sbill  * C shell
161301Sbill  */
171301Sbill 
181301Sbill /*
191301Sbill  * Perform aliasing on the word list lex
201301Sbill  * Do a (very rudimentary) parse to separate into commands.
211301Sbill  * If word 0 of a command has an alias, do it.
221301Sbill  * Repeat a maximum of 20 times.
231301Sbill  */
241301Sbill alias(lex)
251301Sbill 	register struct wordent *lex;
261301Sbill {
271301Sbill 	int aleft = 21;
281301Sbill 	jmp_buf osetexit;
291301Sbill 
301301Sbill 	getexit(osetexit);
3147724Sbostic 	(void)setjmp(reslab);
321301Sbill 	if (haderr) {
331301Sbill 		resexit(osetexit);
3447724Sbostic 		longjmp(reslab, 0);
351301Sbill 	}
361301Sbill 	if (--aleft == 0)
371301Sbill 		error("Alias loop");
381301Sbill 	asyntax(lex->next, lex);
391301Sbill 	resexit(osetexit);
401301Sbill }
411301Sbill 
421301Sbill asyntax(p1, p2)
431301Sbill 	register struct wordent *p1, *p2;
441301Sbill {
451301Sbill 
461301Sbill 	while (p1 != p2)
4747419Sbostic 		if (index(";&\n", p1->word[0]))
481301Sbill 			p1 = p1->next;
491301Sbill 		else {
501301Sbill 			asyn0(p1, p2);
511301Sbill 			return;
521301Sbill 		}
531301Sbill }
541301Sbill 
551301Sbill asyn0(p1, p2)
561301Sbill 	struct wordent *p1;
571301Sbill 	register struct wordent *p2;
581301Sbill {
591301Sbill 	register struct wordent *p;
601301Sbill 	register int l = 0;
611301Sbill 
621301Sbill 	for (p = p1; p != p2; p = p->next)
631301Sbill 		switch (p->word[0]) {
641301Sbill 
651301Sbill 		case '(':
661301Sbill 			l++;
671301Sbill 			continue;
681301Sbill 
691301Sbill 		case ')':
701301Sbill 			l--;
711301Sbill 			if (l < 0)
721301Sbill 				error("Too many )'s");
731301Sbill 			continue;
741301Sbill 
751301Sbill 		case '>':
761301Sbill 			if (p->next != p2 && eq(p->next->word, "&"))
771301Sbill 				p = p->next;
781301Sbill 			continue;
791301Sbill 
801301Sbill 		case '&':
811301Sbill 		case '|':
821301Sbill 		case ';':
831301Sbill 		case '\n':
841301Sbill 			if (l != 0)
851301Sbill 				continue;
861301Sbill 			asyn3(p1, p);
871301Sbill 			asyntax(p->next, p2);
881301Sbill 			return;
891301Sbill 		}
901301Sbill 	if (l == 0)
911301Sbill 		asyn3(p1, p2);
921301Sbill }
931301Sbill 
941301Sbill asyn3(p1, p2)
951301Sbill 	struct wordent *p1;
961301Sbill 	register struct wordent *p2;
971301Sbill {
981301Sbill 	register struct varent *ap;
991301Sbill 	struct wordent alout;
1001301Sbill 	register bool redid;
1011301Sbill 
1021301Sbill 	if (p1 == p2)
1031301Sbill 		return;
1041301Sbill 	if (p1->word[0] == '(') {
1051301Sbill 		for (p2 = p2->prev; p2->word[0] != ')'; p2 = p2->prev)
1061301Sbill 			if (p2 == p1)
1071301Sbill 				return;
1081301Sbill 		if (p2 == p1->next)
1091301Sbill 			return;
1101301Sbill 		asyn0(p1->next, p2);
1111301Sbill 		return;
1121301Sbill 	}
1131301Sbill 	ap = adrof1(p1->word, &aliases);
1141301Sbill 	if (ap == 0)
1151301Sbill 		return;
1161301Sbill 	alhistp = p1->prev;
1171301Sbill 	alhistt = p2;
1181301Sbill 	alvec = ap->vec;
1191301Sbill 	redid = lex(&alout);
1201301Sbill 	alhistp = alhistt = 0;
1211301Sbill 	alvec = 0;
1221301Sbill 	if (err) {
1231301Sbill 		freelex(&alout);
1241301Sbill 		error(err);
1251301Sbill 	}
1261301Sbill 	if (p1->word[0] && eq(p1->word, alout.next->word)) {
1271301Sbill 		char *cp = alout.next->word;
1281301Sbill 
1291301Sbill 		alout.next->word = strspl("\200", cp);
13017511Sedward 		XFREE(cp)
1311301Sbill 	}
1321301Sbill 	p1 = freenod(p1, redid ? p2 : p1->next);
1331301Sbill 	if (alout.next != &alout) {
1341301Sbill 		p1->next->prev = alout.prev->prev;
1351301Sbill 		alout.prev->prev->next = p1->next;
1361301Sbill 		alout.next->prev = p1;
1371301Sbill 		p1->next = alout.next;
13817511Sedward 		XFREE(alout.prev->word)
13917511Sedward 		XFREE((char *)alout.prev)
1401301Sbill 	}
14147724Sbostic 	longjmp(reslab, 0);		/* throw! */
1421301Sbill }
1431301Sbill 
1441301Sbill struct wordent *
1451301Sbill freenod(p1, p2)
1461301Sbill 	register struct wordent *p1, *p2;
1471301Sbill {
1481301Sbill 	register struct wordent *retp = p1->prev;
1491301Sbill 
1501301Sbill 	while (p1 != p2) {
15117511Sedward 		XFREE(p1->word)
1521301Sbill 		p1 = p1->next;
15317511Sedward 		XFREE((char *)p1->prev)
1541301Sbill 	}
1551301Sbill 	retp->next = p2;
1561301Sbill 	p2->prev = retp;
1571301Sbill 	return (retp);
1581301Sbill }
1591301Sbill 
1601301Sbill #define	PHERE	1
1611301Sbill #define	PIN	2
1621301Sbill #define	POUT	4
1631301Sbill #define	PDIAG	8
1641301Sbill 
1651301Sbill /*
1661301Sbill  * syntax
1671301Sbill  *	empty
1681301Sbill  *	syn0
1691301Sbill  */
1701301Sbill struct command *
1711301Sbill syntax(p1, p2, flags)
1721301Sbill 	register struct wordent *p1, *p2;
1731301Sbill 	int flags;
1741301Sbill {
1751301Sbill 
1761301Sbill 	while (p1 != p2)
17747419Sbostic 		if (index(";&\n", p1->word[0]))
1781301Sbill 			p1 = p1->next;
1791301Sbill 		else
1801301Sbill 			return (syn0(p1, p2, flags));
1811301Sbill 	return (0);
1821301Sbill }
1831301Sbill 
1841301Sbill /*
1851301Sbill  * syn0
1861301Sbill  *	syn1
1871301Sbill  *	syn1 & syntax
1881301Sbill  */
1891301Sbill struct command *
1901301Sbill syn0(p1, p2, flags)
1911301Sbill 	struct wordent *p1, *p2;
1921301Sbill 	int flags;
1931301Sbill {
1941301Sbill 	register struct wordent *p;
1951301Sbill 	register struct command *t, *t1;
1961301Sbill 	int l;
1971301Sbill 
1981301Sbill 	l = 0;
1991301Sbill 	for (p = p1; p != p2; p = p->next)
2001301Sbill 		switch (p->word[0]) {
2011301Sbill 
2021301Sbill 		case '(':
2031301Sbill 			l++;
2041301Sbill 			continue;
2051301Sbill 
2061301Sbill 		case ')':
2071301Sbill 			l--;
2081301Sbill 			if (l < 0)
2091301Sbill 				seterr("Too many )'s");
2101301Sbill 			continue;
2111301Sbill 
2121301Sbill 		case '|':
2131301Sbill 			if (p->word[1] == '|')
2141301Sbill 				continue;
2151301Sbill 			/* fall into ... */
2161301Sbill 
2171301Sbill 		case '>':
2181301Sbill 			if (p->next != p2 && eq(p->next->word, "&"))
2191301Sbill 				p = p->next;
2201301Sbill 			continue;
2211301Sbill 
2221301Sbill 		case '&':
2231301Sbill 			if (l != 0)
2241301Sbill 				break;
2251301Sbill 			if (p->word[1] == '&')
2261301Sbill 				continue;
2271301Sbill 			t1 = syn1(p1, p, flags);
22847724Sbostic     			if (t1->t_dtyp == NODE_LIST ||
22947724Sbostic     			    t1->t_dtyp == NODE_AND ||
23047724Sbostic     			    t1->t_dtyp == NODE_OR) {
2311301Sbill 				t = (struct command *) calloc(1, sizeof (*t));
23247724Sbostic 				t->t_dtyp = NODE_PAREN;
23347724Sbostic 				t->t_dflg = F_AMPERSAND|F_NOINTERRUPT;
2341301Sbill 				t->t_dspr = t1;
2351301Sbill 				t1 = t;
2361301Sbill 			} else
23747724Sbostic 				t1->t_dflg |= F_AMPERSAND|F_NOINTERRUPT;
2381301Sbill 			t = (struct command *) calloc(1, sizeof (*t));
23947724Sbostic 			t->t_dtyp = NODE_LIST;
2401301Sbill 			t->t_dflg = 0;
2411301Sbill 			t->t_dcar = t1;
2421301Sbill 			t->t_dcdr = syntax(p, p2, flags);
2431301Sbill 			return(t);
2441301Sbill 		}
2451301Sbill 	if (l == 0)
2461301Sbill 		return (syn1(p1, p2, flags));
2471301Sbill 	seterr("Too many ('s");
2481301Sbill 	return (0);
2491301Sbill }
2501301Sbill 
2511301Sbill /*
2521301Sbill  * syn1
2531301Sbill  *	syn1a
2541301Sbill  *	syn1a ; syntax
2551301Sbill  */
2561301Sbill struct command *
2571301Sbill syn1(p1, p2, flags)
2581301Sbill 	struct wordent *p1, *p2;
2591301Sbill 	int flags;
2601301Sbill {
2611301Sbill 	register struct wordent *p;
2621301Sbill 	register struct command *t;
2631301Sbill 	int l;
2641301Sbill 
2651301Sbill 	l = 0;
2661301Sbill 	for (p = p1; p != p2; p = p->next)
2671301Sbill 		switch (p->word[0]) {
2681301Sbill 
2691301Sbill 		case '(':
2701301Sbill 			l++;
2711301Sbill 			continue;
2721301Sbill 
2731301Sbill 		case ')':
2741301Sbill 			l--;
2751301Sbill 			continue;
2761301Sbill 
2771301Sbill 		case ';':
2781301Sbill 		case '\n':
2791301Sbill 			if (l != 0)
2801301Sbill 				break;
2811301Sbill 			t = (struct command *) calloc(1, sizeof (*t));
28247724Sbostic 			t->t_dtyp = NODE_LIST;
2831301Sbill 			t->t_dcar = syn1a(p1, p, flags);
2841301Sbill 			t->t_dcdr = syntax(p->next, p2, flags);
2851301Sbill 			if (t->t_dcdr == 0)
2861301Sbill 				t->t_dcdr = t->t_dcar, t->t_dcar = 0;
2871301Sbill 			return (t);
2881301Sbill 		}
2891301Sbill 	return (syn1a(p1, p2, flags));
2901301Sbill }
2911301Sbill 
2921301Sbill /*
2931301Sbill  * syn1a
2941301Sbill  *	syn1b
2951301Sbill  *	syn1b || syn1a
2961301Sbill  */
2971301Sbill struct command *
2981301Sbill syn1a(p1, p2, flags)
2991301Sbill 	struct wordent *p1, *p2;
3001301Sbill 	int flags;
3011301Sbill {
3021301Sbill 	register struct wordent *p;
3031301Sbill 	register struct command *t;
3041301Sbill 	register int l = 0;
3051301Sbill 
3061301Sbill 	for (p = p1; p != p2; p = p->next)
3071301Sbill 		switch (p->word[0]) {
3081301Sbill 
3091301Sbill 		case '(':
3101301Sbill 			l++;
3111301Sbill 			continue;
3121301Sbill 
3131301Sbill 		case ')':
3141301Sbill 			l--;
3151301Sbill 			continue;
3161301Sbill 
3171301Sbill 		case '|':
3181301Sbill 			if (p->word[1] != '|')
3191301Sbill 				continue;
3201301Sbill 			if (l == 0) {
3211301Sbill 				t = (struct command *) calloc(1, sizeof (*t));
32247724Sbostic 				t->t_dtyp = NODE_OR;
3231301Sbill 				t->t_dcar = syn1b(p1, p, flags);
3241301Sbill 				t->t_dcdr = syn1a(p->next, p2, flags);
3251301Sbill 				t->t_dflg = 0;
3261301Sbill 				return (t);
3271301Sbill 			}
3281301Sbill 			continue;
3291301Sbill 		}
3301301Sbill 	return (syn1b(p1, p2, flags));
3311301Sbill }
3321301Sbill 
3331301Sbill /*
3341301Sbill  * syn1b
3351301Sbill  *	syn2
3361301Sbill  *	syn2 && syn1b
3371301Sbill  */
3381301Sbill struct command *
3391301Sbill syn1b(p1, p2, flags)
3401301Sbill 	struct wordent *p1, *p2;
3411301Sbill 	int flags;
3421301Sbill {
3431301Sbill 	register struct wordent *p;
3441301Sbill 	register struct command *t;
3451301Sbill 	register int l = 0;
3461301Sbill 
3471301Sbill 	l = 0;
3481301Sbill 	for (p = p1; p != p2; p = p->next)
3491301Sbill 		switch (p->word[0]) {
3501301Sbill 
3511301Sbill 		case '(':
3521301Sbill 			l++;
3531301Sbill 			continue;
3541301Sbill 
3551301Sbill 		case ')':
3561301Sbill 			l--;
3571301Sbill 			continue;
3581301Sbill 
3591301Sbill 		case '&':
3601301Sbill 			if (p->word[1] == '&' && l == 0) {
3611301Sbill 				t = (struct command *) calloc(1, sizeof (*t));
36247724Sbostic 				t->t_dtyp = NODE_AND;
3631301Sbill 				t->t_dcar = syn2(p1, p, flags);
3641301Sbill 				t->t_dcdr = syn1b(p->next, p2, flags);
3651301Sbill 				t->t_dflg = 0;
3661301Sbill 				return (t);
3671301Sbill 			}
3681301Sbill 			continue;
3691301Sbill 		}
3701301Sbill 	return (syn2(p1, p2, flags));
3711301Sbill }
3721301Sbill 
3731301Sbill /*
3741301Sbill  * syn2
3751301Sbill  *	syn3
3761301Sbill  *	syn3 | syn2
3771301Sbill  *	syn3 |& syn2
3781301Sbill  */
3791301Sbill struct command *
3801301Sbill syn2(p1, p2, flags)
3811301Sbill 	struct wordent *p1, *p2;
3821301Sbill 	int flags;
3831301Sbill {
3841301Sbill 	register struct wordent *p, *pn;
3851301Sbill 	register struct command *t;
3861301Sbill 	register int l = 0;
3871301Sbill 	int f;
3881301Sbill 
3891301Sbill 	for (p = p1; p != p2; p = p->next)
3901301Sbill 		switch (p->word[0]) {
3911301Sbill 
3921301Sbill 		case '(':
3931301Sbill 			l++;
3941301Sbill 			continue;
3951301Sbill 
3961301Sbill 		case ')':
3971301Sbill 			l--;
3981301Sbill 			continue;
3991301Sbill 
4001301Sbill 		case '|':
4011301Sbill 			if (l != 0)
4021301Sbill 				continue;
4031301Sbill 			t = (struct command *) calloc(1, sizeof (*t));
4041301Sbill 			f = flags | POUT;
4051301Sbill 			pn = p->next;
4061301Sbill 			if (pn != p2 && pn->word[0] == '&') {
4071301Sbill 				f |= PDIAG;
40847724Sbostic 				t->t_dflg |= F_STDERR;
4091301Sbill 			}
41047724Sbostic 			t->t_dtyp = NODE_PIPE;
4111301Sbill 			t->t_dcar = syn3(p1, p, f);
4121301Sbill 			if (pn != p2 && pn->word[0] == '&')
4131301Sbill 				p = pn;
4141301Sbill 			t->t_dcdr = syn2(p->next, p2, flags | PIN);
4151301Sbill 			return (t);
4161301Sbill 		}
4171301Sbill 	return (syn3(p1, p2, flags));
4181301Sbill }
4191301Sbill 
4201301Sbill char	*RELPAR =	"<>()";
4211301Sbill 
4221301Sbill /*
4231301Sbill  * syn3
4241301Sbill  *	( syn0 ) [ < in  ] [ > out ]
4251301Sbill  *	word word* [ < in ] [ > out ]
4261301Sbill  *	KEYWORD ( word* ) word* [ < in ] [ > out ]
4271301Sbill  *
4281301Sbill  *	KEYWORD = (@ exit foreach if set switch test while)
4291301Sbill  */
4301301Sbill struct command *
4311301Sbill syn3(p1, p2, flags)
4321301Sbill 	struct wordent *p1, *p2;
4331301Sbill 	int flags;
4341301Sbill {
4351301Sbill 	register struct wordent *p;
4361301Sbill 	struct wordent *lp, *rp;
4371301Sbill 	register struct command *t;
4381301Sbill 	register int l;
4391301Sbill 	char **av;
4401301Sbill 	int n, c;
4411301Sbill 	bool specp = 0;
4421301Sbill 
4431301Sbill 	if (p1 != p2) {
4441301Sbill 		p = p1;
4451301Sbill again:
4461301Sbill 		switch (srchx(p->word)) {
4471301Sbill 
44847724Sbostic 		case T_ELSE:
4491301Sbill 			p = p->next;
4501301Sbill 			if (p != p2)
4511301Sbill 				goto again;
4521301Sbill 			break;
4531301Sbill 
45447724Sbostic 		case T_EXIT:
45547724Sbostic 		case T_FOREACH:
45647724Sbostic 		case T_IF:
45747724Sbostic 		case T_LET:
45847724Sbostic 		case T_SET:
45947724Sbostic 		case T_SWITCH:
46047724Sbostic 		case T_WHILE:
4611301Sbill 			specp = 1;
4621301Sbill 			break;
4631301Sbill 		}
4641301Sbill 	}
4651301Sbill 	n = 0;
4661301Sbill 	l = 0;
4671301Sbill 	for (p = p1; p != p2; p = p->next)
4681301Sbill 		switch (p->word[0]) {
4691301Sbill 
4701301Sbill 		case '(':
4711301Sbill 			if (specp)
4721301Sbill 				n++;
4731301Sbill 			l++;
4741301Sbill 			continue;
4751301Sbill 
4761301Sbill 		case ')':
4771301Sbill 			if (specp)
4781301Sbill 				n++;
4791301Sbill 			l--;
4801301Sbill 			continue;
4811301Sbill 
4821301Sbill 		case '>':
4831301Sbill 		case '<':
4841301Sbill 			if (l != 0) {
4851301Sbill 				if (specp)
4861301Sbill 					n++;
4871301Sbill 				continue;
4881301Sbill 			}
4891301Sbill 			if (p->next == p2)
4901301Sbill 				continue;
49147419Sbostic 			if (index(RELPAR, p->next->word[0]))
4921301Sbill 				continue;
4931301Sbill 			n--;
4941301Sbill 			continue;
4951301Sbill 
4961301Sbill 		default:
4971301Sbill 			if (!specp && l != 0)
4981301Sbill 				continue;
4991301Sbill 			n++;
5001301Sbill 			continue;
5011301Sbill 		}
5021301Sbill 	if (n < 0)
5031301Sbill 		n = 0;
5041301Sbill 	t = (struct command *) calloc(1, sizeof (*t));
50517511Sedward 	av = (char **) calloc((unsigned) (n + 1), sizeof (char **));
5061301Sbill 	t->t_dcom = av;
5071301Sbill 	n = 0;
5081301Sbill 	if (p2->word[0] == ')')
50947724Sbostic 		t->t_dflg = F_NOFORK;
5101301Sbill 	lp = 0;
5111301Sbill 	rp = 0;
5121301Sbill 	l = 0;
5131301Sbill 	for (p = p1; p != p2; p = p->next) {
5141301Sbill 		c = p->word[0];
5151301Sbill 		switch (c) {
5161301Sbill 
5171301Sbill 		case '(':
5181301Sbill 			if (l == 0) {
5191301Sbill 				if (lp != 0 && !specp)
5201301Sbill 					seterr("Badly placed (");
5211301Sbill 				lp = p->next;
5221301Sbill 			}
5231301Sbill 			l++;
5241301Sbill 			goto savep;
5251301Sbill 
5261301Sbill 		case ')':
5271301Sbill 			l--;
5281301Sbill 			if (l == 0)
5291301Sbill 				rp = p;
5301301Sbill 			goto savep;
5311301Sbill 
5321301Sbill 		case '>':
5331301Sbill 			if (l != 0)
5341301Sbill 				goto savep;
5351301Sbill 			if (p->word[1] == '>')
53647724Sbostic 				t->t_dflg |= F_APPEND;
5371301Sbill 			if (p->next != p2 && eq(p->next->word, "&")) {
53847724Sbostic 				t->t_dflg |= F_STDERR;
53947724Sbostic 				p = p->next;
5401301Sbill 				if (flags & (POUT|PDIAG))
5411301Sbill 					goto badout;
5421301Sbill 			}
54347724Sbostic 			if (p->next != p2 && eq(p->next->word, "!")) {
54447724Sbostic 				t->t_dflg |= F_OVERWRITE;
54547724Sbostic 				p = p->next;
54647724Sbostic 			}
5471301Sbill 			if (p->next == p2) {
5481301Sbill missfile:
5491301Sbill 				seterr("Missing name for redirect");
5501301Sbill 				continue;
5511301Sbill 			}
5521301Sbill 			p = p->next;
55347419Sbostic 			if (index(RELPAR, p->word[0]))
5541301Sbill 				goto missfile;
5551301Sbill 			if ((flags & POUT) && (flags & PDIAG) == 0 || t->t_drit)
5561301Sbill badout:
5571301Sbill 				seterr("Ambiguous output redirect");
5581301Sbill 			else
5591301Sbill 				t->t_drit = savestr(p->word);
5601301Sbill 			continue;
5611301Sbill 
5621301Sbill 		case '<':
5631301Sbill 			if (l != 0)
5641301Sbill 				goto savep;
5651301Sbill 			if (p->word[1] == '<')
56647724Sbostic 				t->t_dflg |= F_READ;
5671301Sbill 			if (p->next == p2)
5681301Sbill 				goto missfile;
5691301Sbill 			p = p->next;
57047419Sbostic 			if (index(RELPAR, p->word[0]))
5711301Sbill 				goto missfile;
57247724Sbostic 			if ((flags & PHERE) && (t->t_dflg & F_READ))
5731301Sbill 				seterr("Can't << within ()'s");
5741301Sbill 			else if ((flags & PIN) || t->t_dlef)
5751301Sbill 				seterr("Ambiguous input redirect");
5761301Sbill 			else
5771301Sbill 				t->t_dlef = savestr(p->word);
5781301Sbill 			continue;
5791301Sbill 
5801301Sbill savep:
5811301Sbill 			if (!specp)
5821301Sbill 				continue;
5831301Sbill 		default:
5841301Sbill 			if (l != 0 && !specp)
5851301Sbill 				continue;
5861301Sbill 			if (err == 0)
5871301Sbill 				av[n] = savestr(p->word);
5881301Sbill 			n++;
5891301Sbill 			continue;
5901301Sbill 		}
5911301Sbill 	}
5921301Sbill 	if (lp != 0 && !specp) {
5931301Sbill 		if (n != 0)
5941301Sbill 			seterr("Badly placed ()'s");
59547724Sbostic 		t->t_dtyp = NODE_PAREN;
5961301Sbill 		t->t_dspr = syn0(lp, rp, PHERE);
5971301Sbill 	} else {
5981301Sbill 		if (n == 0)
5991301Sbill 			seterr("Invalid null command");
60047724Sbostic 		t->t_dtyp = NODE_COMMAND;
6011301Sbill 	}
6021301Sbill 	return (t);
6031301Sbill }
6041301Sbill 
6051301Sbill freesyn(t)
6061301Sbill 	register struct command *t;
6071301Sbill {
6081301Sbill 	register char **v;
6091301Sbill 
6101301Sbill 	if (t == 0)
6111301Sbill 		return;
6121301Sbill 	switch (t->t_dtyp) {
6131301Sbill 
61447724Sbostic 	case NODE_COMMAND:
6151301Sbill 		for (v = t->t_dcom; *v; v++)
61617511Sedward 			XFREE(*v)
61717511Sedward 		XFREE((char *)t->t_dcom)
6181301Sbill 		goto lr;
6191301Sbill 
62047724Sbostic 	case NODE_PAREN:
6211301Sbill 		freesyn(t->t_dspr);
6221301Sbill 		/* fall into ... */
6231301Sbill 
6241301Sbill lr:
62517511Sedward 		XFREE(t->t_dlef)
62617511Sedward 		XFREE(t->t_drit)
6271301Sbill 		break;
6281301Sbill 
62947724Sbostic 	case NODE_AND:
63047724Sbostic 	case NODE_OR:
63147724Sbostic 	case NODE_PIPE:
63247724Sbostic 	case NODE_LIST:
63347724Sbostic 		freesyn(t->t_dcar);
63447724Sbostic 		freesyn(t->t_dcdr);
6351301Sbill 		break;
6361301Sbill 	}
63717511Sedward 	XFREE((char *)t)
6381301Sbill }
639