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