xref: /minix3/bin/csh/parse.c (revision d1e4d7ce7de96b58a7e34cb41f3fd9aa036d9692)
1*d1e4d7ceSDavid van Moolenbroek /* $NetBSD: parse.c,v 1.17 2007/07/16 18:26:10 christos Exp $ */
2*d1e4d7ceSDavid van Moolenbroek 
3*d1e4d7ceSDavid van Moolenbroek /*-
4*d1e4d7ceSDavid van Moolenbroek  * Copyright (c) 1980, 1991, 1993
5*d1e4d7ceSDavid van Moolenbroek  *	The Regents of the University of California.  All rights reserved.
6*d1e4d7ceSDavid van Moolenbroek  *
7*d1e4d7ceSDavid van Moolenbroek  * Redistribution and use in source and binary forms, with or without
8*d1e4d7ceSDavid van Moolenbroek  * modification, are permitted provided that the following conditions
9*d1e4d7ceSDavid van Moolenbroek  * are met:
10*d1e4d7ceSDavid van Moolenbroek  * 1. Redistributions of source code must retain the above copyright
11*d1e4d7ceSDavid van Moolenbroek  *    notice, this list of conditions and the following disclaimer.
12*d1e4d7ceSDavid van Moolenbroek  * 2. Redistributions in binary form must reproduce the above copyright
13*d1e4d7ceSDavid van Moolenbroek  *    notice, this list of conditions and the following disclaimer in the
14*d1e4d7ceSDavid van Moolenbroek  *    documentation and/or other materials provided with the distribution.
15*d1e4d7ceSDavid van Moolenbroek  * 3. Neither the name of the University nor the names of its contributors
16*d1e4d7ceSDavid van Moolenbroek  *    may be used to endorse or promote products derived from this software
17*d1e4d7ceSDavid van Moolenbroek  *    without specific prior written permission.
18*d1e4d7ceSDavid van Moolenbroek  *
19*d1e4d7ceSDavid van Moolenbroek  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20*d1e4d7ceSDavid van Moolenbroek  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21*d1e4d7ceSDavid van Moolenbroek  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22*d1e4d7ceSDavid van Moolenbroek  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23*d1e4d7ceSDavid van Moolenbroek  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24*d1e4d7ceSDavid van Moolenbroek  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25*d1e4d7ceSDavid van Moolenbroek  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26*d1e4d7ceSDavid van Moolenbroek  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27*d1e4d7ceSDavid van Moolenbroek  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28*d1e4d7ceSDavid van Moolenbroek  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29*d1e4d7ceSDavid van Moolenbroek  * SUCH DAMAGE.
30*d1e4d7ceSDavid van Moolenbroek  */
31*d1e4d7ceSDavid van Moolenbroek 
32*d1e4d7ceSDavid van Moolenbroek #include <sys/cdefs.h>
33*d1e4d7ceSDavid van Moolenbroek #ifndef lint
34*d1e4d7ceSDavid van Moolenbroek #if 0
35*d1e4d7ceSDavid van Moolenbroek static char sccsid[] = "@(#)parse.c	8.1 (Berkeley) 5/31/93";
36*d1e4d7ceSDavid van Moolenbroek #else
37*d1e4d7ceSDavid van Moolenbroek __RCSID("$NetBSD: parse.c,v 1.17 2007/07/16 18:26:10 christos Exp $");
38*d1e4d7ceSDavid van Moolenbroek #endif
39*d1e4d7ceSDavid van Moolenbroek #endif /* not lint */
40*d1e4d7ceSDavid van Moolenbroek 
41*d1e4d7ceSDavid van Moolenbroek #include <sys/types.h>
42*d1e4d7ceSDavid van Moolenbroek 
43*d1e4d7ceSDavid van Moolenbroek #include <stdarg.h>
44*d1e4d7ceSDavid van Moolenbroek #include <stdlib.h>
45*d1e4d7ceSDavid van Moolenbroek #include <string.h>
46*d1e4d7ceSDavid van Moolenbroek 
47*d1e4d7ceSDavid van Moolenbroek #include "csh.h"
48*d1e4d7ceSDavid van Moolenbroek #include "extern.h"
49*d1e4d7ceSDavid van Moolenbroek 
50*d1e4d7ceSDavid van Moolenbroek static void asyntax(struct wordent *, struct wordent *);
51*d1e4d7ceSDavid van Moolenbroek static void asyn0(struct wordent *, struct wordent *);
52*d1e4d7ceSDavid van Moolenbroek static void asyn3(struct wordent *, struct wordent *);
53*d1e4d7ceSDavid van Moolenbroek static struct wordent *freenod(struct wordent *, struct wordent *);
54*d1e4d7ceSDavid van Moolenbroek static struct command *syn0(struct wordent *, struct wordent *, int);
55*d1e4d7ceSDavid van Moolenbroek static struct command *syn1(struct wordent *, struct wordent *, int);
56*d1e4d7ceSDavid van Moolenbroek static struct command *syn1a(struct wordent *, struct wordent *, int);
57*d1e4d7ceSDavid van Moolenbroek static struct command *syn1b(struct wordent *, struct wordent *, int);
58*d1e4d7ceSDavid van Moolenbroek static struct command *syn2(struct wordent *, struct wordent *, int);
59*d1e4d7ceSDavid van Moolenbroek static struct command *syn3(struct wordent *, struct wordent *, int);
60*d1e4d7ceSDavid van Moolenbroek 
61*d1e4d7ceSDavid van Moolenbroek #define ALEFT 21		/* max of 20 alias expansions	 */
62*d1e4d7ceSDavid van Moolenbroek #define HLEFT 11		/* max of 10 history expansions	 */
63*d1e4d7ceSDavid van Moolenbroek /*
64*d1e4d7ceSDavid van Moolenbroek  * Perform aliasing on the word list lex
65*d1e4d7ceSDavid van Moolenbroek  * Do a (very rudimentary) parse to separate into commands.
66*d1e4d7ceSDavid van Moolenbroek  * If word 0 of a command has an alias, do it.
67*d1e4d7ceSDavid van Moolenbroek  * Repeat a maximum of 20 times.
68*d1e4d7ceSDavid van Moolenbroek  */
69*d1e4d7ceSDavid van Moolenbroek static int aleft;
70*d1e4d7ceSDavid van Moolenbroek extern int hleft;
71*d1e4d7ceSDavid van Moolenbroek 
72*d1e4d7ceSDavid van Moolenbroek void
alias(struct wordent * lexp)73*d1e4d7ceSDavid van Moolenbroek alias(struct wordent *lexp)
74*d1e4d7ceSDavid van Moolenbroek {
75*d1e4d7ceSDavid van Moolenbroek     jmp_buf osetexit;
76*d1e4d7ceSDavid van Moolenbroek 
77*d1e4d7ceSDavid van Moolenbroek     aleft = ALEFT;
78*d1e4d7ceSDavid van Moolenbroek     hleft = HLEFT;
79*d1e4d7ceSDavid van Moolenbroek     getexit(osetexit);
80*d1e4d7ceSDavid van Moolenbroek     (void)setexit();
81*d1e4d7ceSDavid van Moolenbroek     if (haderr) {
82*d1e4d7ceSDavid van Moolenbroek 	resexit(osetexit);
83*d1e4d7ceSDavid van Moolenbroek 	reset();
84*d1e4d7ceSDavid van Moolenbroek     }
85*d1e4d7ceSDavid van Moolenbroek     if (--aleft == 0)
86*d1e4d7ceSDavid van Moolenbroek 	stderror(ERR_ALIASLOOP);
87*d1e4d7ceSDavid van Moolenbroek     asyntax(lexp->next, lexp);
88*d1e4d7ceSDavid van Moolenbroek     resexit(osetexit);
89*d1e4d7ceSDavid van Moolenbroek }
90*d1e4d7ceSDavid van Moolenbroek 
91*d1e4d7ceSDavid van Moolenbroek static void
asyntax(struct wordent * p1,struct wordent * p2)92*d1e4d7ceSDavid van Moolenbroek asyntax(struct wordent *p1, struct wordent *p2)
93*d1e4d7ceSDavid van Moolenbroek {
94*d1e4d7ceSDavid van Moolenbroek     while (p1 != p2)
95*d1e4d7ceSDavid van Moolenbroek 	if (any(";&\n", p1->word[0]))
96*d1e4d7ceSDavid van Moolenbroek 	    p1 = p1->next;
97*d1e4d7ceSDavid van Moolenbroek 	else {
98*d1e4d7ceSDavid van Moolenbroek 	    asyn0(p1, p2);
99*d1e4d7ceSDavid van Moolenbroek 	    return;
100*d1e4d7ceSDavid van Moolenbroek 	}
101*d1e4d7ceSDavid van Moolenbroek }
102*d1e4d7ceSDavid van Moolenbroek 
103*d1e4d7ceSDavid van Moolenbroek static void
asyn0(struct wordent * p1,struct wordent * p2)104*d1e4d7ceSDavid van Moolenbroek asyn0(struct wordent *p1, struct wordent *p2)
105*d1e4d7ceSDavid van Moolenbroek {
106*d1e4d7ceSDavid van Moolenbroek     struct wordent *p;
107*d1e4d7ceSDavid van Moolenbroek     int l;
108*d1e4d7ceSDavid van Moolenbroek 
109*d1e4d7ceSDavid van Moolenbroek     l = 0;
110*d1e4d7ceSDavid van Moolenbroek     for (p = p1; p != p2; p = p->next)
111*d1e4d7ceSDavid van Moolenbroek 	switch (p->word[0]) {
112*d1e4d7ceSDavid van Moolenbroek 	case '(':
113*d1e4d7ceSDavid van Moolenbroek 	    l++;
114*d1e4d7ceSDavid van Moolenbroek 	    continue;
115*d1e4d7ceSDavid van Moolenbroek 	case ')':
116*d1e4d7ceSDavid van Moolenbroek 	    l--;
117*d1e4d7ceSDavid van Moolenbroek 	    if (l < 0)
118*d1e4d7ceSDavid van Moolenbroek 		stderror(ERR_TOOMANYRP);
119*d1e4d7ceSDavid van Moolenbroek 	    continue;
120*d1e4d7ceSDavid van Moolenbroek 	case '>':
121*d1e4d7ceSDavid van Moolenbroek 	    if (p->next != p2 && eq(p->next->word, STRand))
122*d1e4d7ceSDavid van Moolenbroek 		p = p->next;
123*d1e4d7ceSDavid van Moolenbroek 	    continue;
124*d1e4d7ceSDavid van Moolenbroek 	case '&':
125*d1e4d7ceSDavid van Moolenbroek 	case '|':
126*d1e4d7ceSDavid van Moolenbroek 	case ';':
127*d1e4d7ceSDavid van Moolenbroek 	case '\n':
128*d1e4d7ceSDavid van Moolenbroek 	    if (l != 0)
129*d1e4d7ceSDavid van Moolenbroek 		continue;
130*d1e4d7ceSDavid van Moolenbroek 	    asyn3(p1, p);
131*d1e4d7ceSDavid van Moolenbroek 	    asyntax(p->next, p2);
132*d1e4d7ceSDavid van Moolenbroek 	    return;
133*d1e4d7ceSDavid van Moolenbroek 	}
134*d1e4d7ceSDavid van Moolenbroek     if (l == 0)
135*d1e4d7ceSDavid van Moolenbroek 	asyn3(p1, p2);
136*d1e4d7ceSDavid van Moolenbroek }
137*d1e4d7ceSDavid van Moolenbroek 
138*d1e4d7ceSDavid van Moolenbroek static void
asyn3(struct wordent * p1,struct wordent * p2)139*d1e4d7ceSDavid van Moolenbroek asyn3(struct wordent *p1, struct wordent *p2)
140*d1e4d7ceSDavid van Moolenbroek {
141*d1e4d7ceSDavid van Moolenbroek     struct varent *ap;
142*d1e4d7ceSDavid van Moolenbroek     struct wordent alout;
143*d1e4d7ceSDavid van Moolenbroek     int redid;
144*d1e4d7ceSDavid van Moolenbroek 
145*d1e4d7ceSDavid van Moolenbroek     if (p1 == p2)
146*d1e4d7ceSDavid van Moolenbroek 	return;
147*d1e4d7ceSDavid van Moolenbroek     if (p1->word[0] == '(') {
148*d1e4d7ceSDavid van Moolenbroek 	for (p2 = p2->prev; p2->word[0] != ')'; p2 = p2->prev)
149*d1e4d7ceSDavid van Moolenbroek 	    if (p2 == p1)
150*d1e4d7ceSDavid van Moolenbroek 		return;
151*d1e4d7ceSDavid van Moolenbroek 	if (p2 == p1->next)
152*d1e4d7ceSDavid van Moolenbroek 	    return;
153*d1e4d7ceSDavid van Moolenbroek 	asyn0(p1->next, p2);
154*d1e4d7ceSDavid van Moolenbroek 	return;
155*d1e4d7ceSDavid van Moolenbroek     }
156*d1e4d7ceSDavid van Moolenbroek     ap = adrof1(p1->word, &aliases);
157*d1e4d7ceSDavid van Moolenbroek     if (ap == 0)
158*d1e4d7ceSDavid van Moolenbroek 	return;
159*d1e4d7ceSDavid van Moolenbroek     alhistp = p1->prev;
160*d1e4d7ceSDavid van Moolenbroek     alhistt = p2;
161*d1e4d7ceSDavid van Moolenbroek     alvec = ap->vec;
162*d1e4d7ceSDavid van Moolenbroek     redid = lex(&alout);
163*d1e4d7ceSDavid van Moolenbroek     alhistp = alhistt = 0;
164*d1e4d7ceSDavid van Moolenbroek     alvec = 0;
165*d1e4d7ceSDavid van Moolenbroek     if (seterr) {
166*d1e4d7ceSDavid van Moolenbroek 	freelex(&alout);
167*d1e4d7ceSDavid van Moolenbroek 	stderror(ERR_OLD);
168*d1e4d7ceSDavid van Moolenbroek     }
169*d1e4d7ceSDavid van Moolenbroek     if (p1->word[0] && eq(p1->word, alout.next->word)) {
170*d1e4d7ceSDavid van Moolenbroek 	Char *cp;
171*d1e4d7ceSDavid van Moolenbroek 
172*d1e4d7ceSDavid van Moolenbroek 	cp = alout.next->word;
173*d1e4d7ceSDavid van Moolenbroek 	alout.next->word = Strspl(STRQNULL, cp);
174*d1e4d7ceSDavid van Moolenbroek 	xfree((ptr_t) cp);
175*d1e4d7ceSDavid van Moolenbroek     }
176*d1e4d7ceSDavid van Moolenbroek     p1 = freenod(p1, redid ? p2 : p1->next);
177*d1e4d7ceSDavid van Moolenbroek     if (alout.next != &alout) {
178*d1e4d7ceSDavid van Moolenbroek 	p1->next->prev = alout.prev->prev;
179*d1e4d7ceSDavid van Moolenbroek 	alout.prev->prev->next = p1->next;
180*d1e4d7ceSDavid van Moolenbroek 	alout.next->prev = p1;
181*d1e4d7ceSDavid van Moolenbroek 	p1->next = alout.next;
182*d1e4d7ceSDavid van Moolenbroek 	xfree((ptr_t)alout.prev->word);
183*d1e4d7ceSDavid van Moolenbroek 	xfree((ptr_t)(alout.prev));
184*d1e4d7ceSDavid van Moolenbroek     }
185*d1e4d7ceSDavid van Moolenbroek     reset();			/* throw! */
186*d1e4d7ceSDavid van Moolenbroek }
187*d1e4d7ceSDavid van Moolenbroek 
188*d1e4d7ceSDavid van Moolenbroek static struct wordent *
freenod(struct wordent * p1,struct wordent * p2)189*d1e4d7ceSDavid van Moolenbroek freenod(struct wordent *p1, struct wordent *p2)
190*d1e4d7ceSDavid van Moolenbroek {
191*d1e4d7ceSDavid van Moolenbroek     struct wordent *retp;
192*d1e4d7ceSDavid van Moolenbroek 
193*d1e4d7ceSDavid van Moolenbroek     retp = p1->prev;
194*d1e4d7ceSDavid van Moolenbroek     while (p1 != p2) {
195*d1e4d7ceSDavid van Moolenbroek 	xfree((ptr_t)p1->word);
196*d1e4d7ceSDavid van Moolenbroek 	p1 = p1->next;
197*d1e4d7ceSDavid van Moolenbroek 	xfree((ptr_t) (p1->prev));
198*d1e4d7ceSDavid van Moolenbroek     }
199*d1e4d7ceSDavid van Moolenbroek     retp->next = p2;
200*d1e4d7ceSDavid van Moolenbroek     p2->prev = retp;
201*d1e4d7ceSDavid van Moolenbroek     return (retp);
202*d1e4d7ceSDavid van Moolenbroek }
203*d1e4d7ceSDavid van Moolenbroek 
204*d1e4d7ceSDavid van Moolenbroek #define	PHERE	1
205*d1e4d7ceSDavid van Moolenbroek #define	PIN	2
206*d1e4d7ceSDavid van Moolenbroek #define	POUT	4
207*d1e4d7ceSDavid van Moolenbroek #define	PERR	8
208*d1e4d7ceSDavid van Moolenbroek 
209*d1e4d7ceSDavid van Moolenbroek /*
210*d1e4d7ceSDavid van Moolenbroek  * syntax
211*d1e4d7ceSDavid van Moolenbroek  *	empty
212*d1e4d7ceSDavid van Moolenbroek  *	syn0
213*d1e4d7ceSDavid van Moolenbroek  */
214*d1e4d7ceSDavid van Moolenbroek struct command *
syntax(struct wordent * p1,struct wordent * p2,int flags)215*d1e4d7ceSDavid van Moolenbroek syntax(struct wordent *p1, struct wordent *p2, int flags)
216*d1e4d7ceSDavid van Moolenbroek {
217*d1e4d7ceSDavid van Moolenbroek     while (p1 != p2)
218*d1e4d7ceSDavid van Moolenbroek 	if (any(";&\n", p1->word[0]))
219*d1e4d7ceSDavid van Moolenbroek 	    p1 = p1->next;
220*d1e4d7ceSDavid van Moolenbroek 	else
221*d1e4d7ceSDavid van Moolenbroek 	    return (syn0(p1, p2, flags));
222*d1e4d7ceSDavid van Moolenbroek     return (0);
223*d1e4d7ceSDavid van Moolenbroek }
224*d1e4d7ceSDavid van Moolenbroek 
225*d1e4d7ceSDavid van Moolenbroek /*
226*d1e4d7ceSDavid van Moolenbroek  * syn0
227*d1e4d7ceSDavid van Moolenbroek  *	syn1
228*d1e4d7ceSDavid van Moolenbroek  *	syn1 & syntax
229*d1e4d7ceSDavid van Moolenbroek  */
230*d1e4d7ceSDavid van Moolenbroek static struct command *
syn0(struct wordent * p1,struct wordent * p2,int flags)231*d1e4d7ceSDavid van Moolenbroek syn0(struct wordent *p1, struct wordent *p2, int flags)
232*d1e4d7ceSDavid van Moolenbroek {
233*d1e4d7ceSDavid van Moolenbroek     struct wordent *p;
234*d1e4d7ceSDavid van Moolenbroek     struct command *t, *t1;
235*d1e4d7ceSDavid van Moolenbroek     int l;
236*d1e4d7ceSDavid van Moolenbroek 
237*d1e4d7ceSDavid van Moolenbroek     l = 0;
238*d1e4d7ceSDavid van Moolenbroek     for (p = p1; p != p2; p = p->next)
239*d1e4d7ceSDavid van Moolenbroek 	switch (p->word[0]) {
240*d1e4d7ceSDavid van Moolenbroek 	case '(':
241*d1e4d7ceSDavid van Moolenbroek 	    l++;
242*d1e4d7ceSDavid van Moolenbroek 	    continue;
243*d1e4d7ceSDavid van Moolenbroek 	case ')':
244*d1e4d7ceSDavid van Moolenbroek 	    l--;
245*d1e4d7ceSDavid van Moolenbroek 	    if (l < 0)
246*d1e4d7ceSDavid van Moolenbroek 		seterror(ERR_TOOMANYRP);
247*d1e4d7ceSDavid van Moolenbroek 	    continue;
248*d1e4d7ceSDavid van Moolenbroek 	case '|':
249*d1e4d7ceSDavid van Moolenbroek 	    if (p->word[1] == '|')
250*d1e4d7ceSDavid van Moolenbroek 		continue;
251*d1e4d7ceSDavid van Moolenbroek 	    /* FALLTHROUGH */
252*d1e4d7ceSDavid van Moolenbroek 	case '>':
253*d1e4d7ceSDavid van Moolenbroek 	    if (p->next != p2 && eq(p->next->word, STRand))
254*d1e4d7ceSDavid van Moolenbroek 		p = p->next;
255*d1e4d7ceSDavid van Moolenbroek 	    continue;
256*d1e4d7ceSDavid van Moolenbroek 	case '&':
257*d1e4d7ceSDavid van Moolenbroek 	    if (l != 0)
258*d1e4d7ceSDavid van Moolenbroek 		break;
259*d1e4d7ceSDavid van Moolenbroek 	    if (p->word[1] == '&')
260*d1e4d7ceSDavid van Moolenbroek 		continue;
261*d1e4d7ceSDavid van Moolenbroek 	    t1 = syn1(p1, p, flags);
262*d1e4d7ceSDavid van Moolenbroek 	    if (t1->t_dtyp == NODE_LIST ||
263*d1e4d7ceSDavid van Moolenbroek 		t1->t_dtyp == NODE_AND ||
264*d1e4d7ceSDavid van Moolenbroek 		t1->t_dtyp == NODE_OR) {
265*d1e4d7ceSDavid van Moolenbroek 		t = (struct command *)xcalloc(1, sizeof(*t));
266*d1e4d7ceSDavid van Moolenbroek 		t->t_dtyp = NODE_PAREN;
267*d1e4d7ceSDavid van Moolenbroek 		t->t_dflg = F_AMPERSAND | F_NOINTERRUPT;
268*d1e4d7ceSDavid van Moolenbroek 		t->t_dspr = t1;
269*d1e4d7ceSDavid van Moolenbroek 		t1 = t;
270*d1e4d7ceSDavid van Moolenbroek 	    }
271*d1e4d7ceSDavid van Moolenbroek 	    else
272*d1e4d7ceSDavid van Moolenbroek 		t1->t_dflg |= F_AMPERSAND | F_NOINTERRUPT;
273*d1e4d7ceSDavid van Moolenbroek 	    t = (struct command *)xcalloc(1, sizeof(*t));
274*d1e4d7ceSDavid van Moolenbroek 	    t->t_dtyp = NODE_LIST;
275*d1e4d7ceSDavid van Moolenbroek 	    t->t_dflg = 0;
276*d1e4d7ceSDavid van Moolenbroek 	    t->t_dcar = t1;
277*d1e4d7ceSDavid van Moolenbroek 	    t->t_dcdr = syntax(p, p2, flags);
278*d1e4d7ceSDavid van Moolenbroek 	    return (t);
279*d1e4d7ceSDavid van Moolenbroek 	}
280*d1e4d7ceSDavid van Moolenbroek     if (l == 0)
281*d1e4d7ceSDavid van Moolenbroek 	return (syn1(p1, p2, flags));
282*d1e4d7ceSDavid van Moolenbroek     seterror(ERR_TOOMANYLP);
283*d1e4d7ceSDavid van Moolenbroek     return (0);
284*d1e4d7ceSDavid van Moolenbroek }
285*d1e4d7ceSDavid van Moolenbroek 
286*d1e4d7ceSDavid van Moolenbroek /*
287*d1e4d7ceSDavid van Moolenbroek  * syn1
288*d1e4d7ceSDavid van Moolenbroek  *	syn1a
289*d1e4d7ceSDavid van Moolenbroek  *	syn1a ; syntax
290*d1e4d7ceSDavid van Moolenbroek  */
291*d1e4d7ceSDavid van Moolenbroek static struct command *
syn1(struct wordent * p1,struct wordent * p2,int flags)292*d1e4d7ceSDavid van Moolenbroek syn1(struct wordent *p1, struct wordent *p2, int flags)
293*d1e4d7ceSDavid van Moolenbroek {
294*d1e4d7ceSDavid van Moolenbroek     struct wordent *p;
295*d1e4d7ceSDavid van Moolenbroek     struct command *t;
296*d1e4d7ceSDavid van Moolenbroek     int l;
297*d1e4d7ceSDavid van Moolenbroek 
298*d1e4d7ceSDavid van Moolenbroek     l = 0;
299*d1e4d7ceSDavid van Moolenbroek     for (p = p1; p != p2; p = p->next)
300*d1e4d7ceSDavid van Moolenbroek 	switch (p->word[0]) {
301*d1e4d7ceSDavid van Moolenbroek 	case '(':
302*d1e4d7ceSDavid van Moolenbroek 	    l++;
303*d1e4d7ceSDavid van Moolenbroek 	    continue;
304*d1e4d7ceSDavid van Moolenbroek 	case ')':
305*d1e4d7ceSDavid van Moolenbroek 	    l--;
306*d1e4d7ceSDavid van Moolenbroek 	    continue;
307*d1e4d7ceSDavid van Moolenbroek 	case ';':
308*d1e4d7ceSDavid van Moolenbroek 	case '\n':
309*d1e4d7ceSDavid van Moolenbroek 	    if (l != 0)
310*d1e4d7ceSDavid van Moolenbroek 		break;
311*d1e4d7ceSDavid van Moolenbroek 	    t = (struct command *) xcalloc(1, sizeof(*t));
312*d1e4d7ceSDavid van Moolenbroek 	    t->t_dtyp = NODE_LIST;
313*d1e4d7ceSDavid van Moolenbroek 	    t->t_dcar = syn1a(p1, p, flags);
314*d1e4d7ceSDavid van Moolenbroek 	    t->t_dcdr = syntax(p->next, p2, flags);
315*d1e4d7ceSDavid van Moolenbroek 	    if (t->t_dcdr == 0)
316*d1e4d7ceSDavid van Moolenbroek 		t->t_dcdr = t->t_dcar, t->t_dcar = 0;
317*d1e4d7ceSDavid van Moolenbroek 	    return (t);
318*d1e4d7ceSDavid van Moolenbroek 	}
319*d1e4d7ceSDavid van Moolenbroek     return (syn1a(p1, p2, flags));
320*d1e4d7ceSDavid van Moolenbroek }
321*d1e4d7ceSDavid van Moolenbroek 
322*d1e4d7ceSDavid van Moolenbroek /*
323*d1e4d7ceSDavid van Moolenbroek  * syn1a
324*d1e4d7ceSDavid van Moolenbroek  *	syn1b
325*d1e4d7ceSDavid van Moolenbroek  *	syn1b || syn1a
326*d1e4d7ceSDavid van Moolenbroek  */
327*d1e4d7ceSDavid van Moolenbroek static struct command *
syn1a(struct wordent * p1,struct wordent * p2,int flags)328*d1e4d7ceSDavid van Moolenbroek syn1a(struct wordent *p1, struct wordent *p2, int flags)
329*d1e4d7ceSDavid van Moolenbroek {
330*d1e4d7ceSDavid van Moolenbroek     struct wordent *p;
331*d1e4d7ceSDavid van Moolenbroek     struct command *t;
332*d1e4d7ceSDavid van Moolenbroek     int l;
333*d1e4d7ceSDavid van Moolenbroek 
334*d1e4d7ceSDavid van Moolenbroek     l = 0;
335*d1e4d7ceSDavid van Moolenbroek     for (p = p1; p != p2; p = p->next)
336*d1e4d7ceSDavid van Moolenbroek 	switch (p->word[0]) {
337*d1e4d7ceSDavid van Moolenbroek 	case '(':
338*d1e4d7ceSDavid van Moolenbroek 	    l++;
339*d1e4d7ceSDavid van Moolenbroek 	    continue;
340*d1e4d7ceSDavid van Moolenbroek 	case ')':
341*d1e4d7ceSDavid van Moolenbroek 	    l--;
342*d1e4d7ceSDavid van Moolenbroek 	    continue;
343*d1e4d7ceSDavid van Moolenbroek 	case '|':
344*d1e4d7ceSDavid van Moolenbroek 	    if (p->word[1] != '|')
345*d1e4d7ceSDavid van Moolenbroek 		continue;
346*d1e4d7ceSDavid van Moolenbroek 	    if (l == 0) {
347*d1e4d7ceSDavid van Moolenbroek 		t = (struct command *)xcalloc(1, sizeof(*t));
348*d1e4d7ceSDavid van Moolenbroek 		t->t_dtyp = NODE_OR;
349*d1e4d7ceSDavid van Moolenbroek 		t->t_dcar = syn1b(p1, p, flags);
350*d1e4d7ceSDavid van Moolenbroek 		t->t_dcdr = syn1a(p->next, p2, flags);
351*d1e4d7ceSDavid van Moolenbroek 		t->t_dflg = 0;
352*d1e4d7ceSDavid van Moolenbroek 		return (t);
353*d1e4d7ceSDavid van Moolenbroek 	    }
354*d1e4d7ceSDavid van Moolenbroek 	    continue;
355*d1e4d7ceSDavid van Moolenbroek 	}
356*d1e4d7ceSDavid van Moolenbroek     return (syn1b(p1, p2, flags));
357*d1e4d7ceSDavid van Moolenbroek }
358*d1e4d7ceSDavid van Moolenbroek 
359*d1e4d7ceSDavid van Moolenbroek /*
360*d1e4d7ceSDavid van Moolenbroek  * syn1b
361*d1e4d7ceSDavid van Moolenbroek  *	syn2
362*d1e4d7ceSDavid van Moolenbroek  *	syn2 && syn1b
363*d1e4d7ceSDavid van Moolenbroek  */
364*d1e4d7ceSDavid van Moolenbroek static struct command *
syn1b(struct wordent * p1,struct wordent * p2,int flags)365*d1e4d7ceSDavid van Moolenbroek syn1b(struct wordent *p1, struct wordent *p2, int flags)
366*d1e4d7ceSDavid van Moolenbroek {
367*d1e4d7ceSDavid van Moolenbroek     struct wordent *p;
368*d1e4d7ceSDavid van Moolenbroek     struct command *t;
369*d1e4d7ceSDavid van Moolenbroek     int l;
370*d1e4d7ceSDavid van Moolenbroek 
371*d1e4d7ceSDavid van Moolenbroek     l = 0;
372*d1e4d7ceSDavid van Moolenbroek     for (p = p1; p != p2; p = p->next)
373*d1e4d7ceSDavid van Moolenbroek 	switch (p->word[0]) {
374*d1e4d7ceSDavid van Moolenbroek 	case '(':
375*d1e4d7ceSDavid van Moolenbroek 	    l++;
376*d1e4d7ceSDavid van Moolenbroek 	    continue;
377*d1e4d7ceSDavid van Moolenbroek 	case ')':
378*d1e4d7ceSDavid van Moolenbroek 	    l--;
379*d1e4d7ceSDavid van Moolenbroek 	    continue;
380*d1e4d7ceSDavid van Moolenbroek 	case '&':
381*d1e4d7ceSDavid van Moolenbroek 	    if (p->word[1] == '&' && l == 0) {
382*d1e4d7ceSDavid van Moolenbroek 		t = (struct command *)xcalloc(1, sizeof(*t));
383*d1e4d7ceSDavid van Moolenbroek 		t->t_dtyp = NODE_AND;
384*d1e4d7ceSDavid van Moolenbroek 		t->t_dcar = syn2(p1, p, flags);
385*d1e4d7ceSDavid van Moolenbroek 		t->t_dcdr = syn1b(p->next, p2, flags);
386*d1e4d7ceSDavid van Moolenbroek 		t->t_dflg = 0;
387*d1e4d7ceSDavid van Moolenbroek 		return (t);
388*d1e4d7ceSDavid van Moolenbroek 	    }
389*d1e4d7ceSDavid van Moolenbroek 	    continue;
390*d1e4d7ceSDavid van Moolenbroek 	}
391*d1e4d7ceSDavid van Moolenbroek     return (syn2(p1, p2, flags));
392*d1e4d7ceSDavid van Moolenbroek }
393*d1e4d7ceSDavid van Moolenbroek 
394*d1e4d7ceSDavid van Moolenbroek /*
395*d1e4d7ceSDavid van Moolenbroek  * syn2
396*d1e4d7ceSDavid van Moolenbroek  *	syn3
397*d1e4d7ceSDavid van Moolenbroek  *	syn3 | syn2
398*d1e4d7ceSDavid van Moolenbroek  *	syn3 |& syn2
399*d1e4d7ceSDavid van Moolenbroek  */
400*d1e4d7ceSDavid van Moolenbroek static struct command *
syn2(struct wordent * p1,struct wordent * p2,int flags)401*d1e4d7ceSDavid van Moolenbroek syn2(struct wordent *p1, struct wordent *p2, int flags)
402*d1e4d7ceSDavid van Moolenbroek {
403*d1e4d7ceSDavid van Moolenbroek     struct wordent *p, *pn;
404*d1e4d7ceSDavid van Moolenbroek     struct command *t;
405*d1e4d7ceSDavid van Moolenbroek     int f, l;
406*d1e4d7ceSDavid van Moolenbroek 
407*d1e4d7ceSDavid van Moolenbroek     l = 0;
408*d1e4d7ceSDavid van Moolenbroek     for (p = p1; p != p2; p = p->next)
409*d1e4d7ceSDavid van Moolenbroek 	switch (p->word[0]) {
410*d1e4d7ceSDavid van Moolenbroek 	case '(':
411*d1e4d7ceSDavid van Moolenbroek 	    l++;
412*d1e4d7ceSDavid van Moolenbroek 	    continue;
413*d1e4d7ceSDavid van Moolenbroek 	case ')':
414*d1e4d7ceSDavid van Moolenbroek 	    l--;
415*d1e4d7ceSDavid van Moolenbroek 	    continue;
416*d1e4d7ceSDavid van Moolenbroek 	case '|':
417*d1e4d7ceSDavid van Moolenbroek 	    if (l != 0)
418*d1e4d7ceSDavid van Moolenbroek 		continue;
419*d1e4d7ceSDavid van Moolenbroek 	    t = (struct command *)xcalloc(1, sizeof(*t));
420*d1e4d7ceSDavid van Moolenbroek 	    f = flags | POUT;
421*d1e4d7ceSDavid van Moolenbroek 	    pn = p->next;
422*d1e4d7ceSDavid van Moolenbroek 	    if (pn != p2 && pn->word[0] == '&') {
423*d1e4d7ceSDavid van Moolenbroek 		f |= PERR;
424*d1e4d7ceSDavid van Moolenbroek 		t->t_dflg |= F_STDERR;
425*d1e4d7ceSDavid van Moolenbroek 	    }
426*d1e4d7ceSDavid van Moolenbroek 	    t->t_dtyp = NODE_PIPE;
427*d1e4d7ceSDavid van Moolenbroek 	    t->t_dcar = syn3(p1, p, f);
428*d1e4d7ceSDavid van Moolenbroek 	    if (pn != p2 && pn->word[0] == '&')
429*d1e4d7ceSDavid van Moolenbroek 		p = pn;
430*d1e4d7ceSDavid van Moolenbroek 	    t->t_dcdr = syn2(p->next, p2, flags | PIN);
431*d1e4d7ceSDavid van Moolenbroek 	    return (t);
432*d1e4d7ceSDavid van Moolenbroek 	}
433*d1e4d7ceSDavid van Moolenbroek     return (syn3(p1, p2, flags));
434*d1e4d7ceSDavid van Moolenbroek }
435*d1e4d7ceSDavid van Moolenbroek 
436*d1e4d7ceSDavid van Moolenbroek static char RELPAR[] = {'<', '>', '(', ')', '\0'};
437*d1e4d7ceSDavid van Moolenbroek 
438*d1e4d7ceSDavid van Moolenbroek /*
439*d1e4d7ceSDavid van Moolenbroek  * syn3
440*d1e4d7ceSDavid van Moolenbroek  *	( syn0 ) [ < in  ] [ > out ]
441*d1e4d7ceSDavid van Moolenbroek  *	word word* [ < in ] [ > out ]
442*d1e4d7ceSDavid van Moolenbroek  *	KEYWORD ( word* ) word* [ < in ] [ > out ]
443*d1e4d7ceSDavid van Moolenbroek  *
444*d1e4d7ceSDavid van Moolenbroek  *	KEYWORD = (@ exit foreach if set switch test while)
445*d1e4d7ceSDavid van Moolenbroek  */
446*d1e4d7ceSDavid van Moolenbroek static struct command *
syn3(struct wordent * p1,struct wordent * p2,int flags)447*d1e4d7ceSDavid van Moolenbroek syn3(struct wordent *p1, struct wordent *p2, int flags)
448*d1e4d7ceSDavid van Moolenbroek {
449*d1e4d7ceSDavid van Moolenbroek     struct wordent *lp, *p, *rp;
450*d1e4d7ceSDavid van Moolenbroek     struct command *t;
451*d1e4d7ceSDavid van Moolenbroek     Char **av;
452*d1e4d7ceSDavid van Moolenbroek     int c, l, n;
453*d1e4d7ceSDavid van Moolenbroek     int specp;
454*d1e4d7ceSDavid van Moolenbroek 
455*d1e4d7ceSDavid van Moolenbroek     specp = 0;
456*d1e4d7ceSDavid van Moolenbroek     if (p1 != p2) {
457*d1e4d7ceSDavid van Moolenbroek 	p = p1;
458*d1e4d7ceSDavid van Moolenbroek again:
459*d1e4d7ceSDavid van Moolenbroek 	switch (srchx(p->word)) {
460*d1e4d7ceSDavid van Moolenbroek 	case T_ELSE:
461*d1e4d7ceSDavid van Moolenbroek 	    p = p->next;
462*d1e4d7ceSDavid van Moolenbroek 	    if (p != p2)
463*d1e4d7ceSDavid van Moolenbroek 		goto again;
464*d1e4d7ceSDavid van Moolenbroek 	    break;
465*d1e4d7ceSDavid van Moolenbroek 	case T_EXIT:
466*d1e4d7ceSDavid van Moolenbroek 	case T_FOREACH:
467*d1e4d7ceSDavid van Moolenbroek 	case T_IF:
468*d1e4d7ceSDavid van Moolenbroek 	case T_LET:
469*d1e4d7ceSDavid van Moolenbroek 	case T_SET:
470*d1e4d7ceSDavid van Moolenbroek 	case T_SWITCH:
471*d1e4d7ceSDavid van Moolenbroek 	case T_WHILE:
472*d1e4d7ceSDavid van Moolenbroek 	    specp = 1;
473*d1e4d7ceSDavid van Moolenbroek 	    break;
474*d1e4d7ceSDavid van Moolenbroek 	}
475*d1e4d7ceSDavid van Moolenbroek     }
476*d1e4d7ceSDavid van Moolenbroek     n = 0;
477*d1e4d7ceSDavid van Moolenbroek     l = 0;
478*d1e4d7ceSDavid van Moolenbroek     for (p = p1; p != p2; p = p->next)
479*d1e4d7ceSDavid van Moolenbroek 	switch (p->word[0]) {
480*d1e4d7ceSDavid van Moolenbroek 	case '(':
481*d1e4d7ceSDavid van Moolenbroek 	    if (specp)
482*d1e4d7ceSDavid van Moolenbroek 		n++;
483*d1e4d7ceSDavid van Moolenbroek 	    l++;
484*d1e4d7ceSDavid van Moolenbroek 	    continue;
485*d1e4d7ceSDavid van Moolenbroek 	case ')':
486*d1e4d7ceSDavid van Moolenbroek 	    if (specp)
487*d1e4d7ceSDavid van Moolenbroek 		n++;
488*d1e4d7ceSDavid van Moolenbroek 	    l--;
489*d1e4d7ceSDavid van Moolenbroek 	    continue;
490*d1e4d7ceSDavid van Moolenbroek 	case '>':
491*d1e4d7ceSDavid van Moolenbroek 	case '<':
492*d1e4d7ceSDavid van Moolenbroek 	    if (l != 0) {
493*d1e4d7ceSDavid van Moolenbroek 		if (specp)
494*d1e4d7ceSDavid van Moolenbroek 		    n++;
495*d1e4d7ceSDavid van Moolenbroek 		continue;
496*d1e4d7ceSDavid van Moolenbroek 	    }
497*d1e4d7ceSDavid van Moolenbroek 	    if (p->next == p2)
498*d1e4d7ceSDavid van Moolenbroek 		continue;
499*d1e4d7ceSDavid van Moolenbroek 	    if (any(RELPAR, p->next->word[0]))
500*d1e4d7ceSDavid van Moolenbroek 		continue;
501*d1e4d7ceSDavid van Moolenbroek 	    n--;
502*d1e4d7ceSDavid van Moolenbroek 	    continue;
503*d1e4d7ceSDavid van Moolenbroek 	default:
504*d1e4d7ceSDavid van Moolenbroek 	    if (!specp && l != 0)
505*d1e4d7ceSDavid van Moolenbroek 		continue;
506*d1e4d7ceSDavid van Moolenbroek 	    n++;
507*d1e4d7ceSDavid van Moolenbroek 	    continue;
508*d1e4d7ceSDavid van Moolenbroek 	}
509*d1e4d7ceSDavid van Moolenbroek     if (n < 0)
510*d1e4d7ceSDavid van Moolenbroek 	n = 0;
511*d1e4d7ceSDavid van Moolenbroek     t = (struct command *)xcalloc(1, sizeof(*t));
512*d1e4d7ceSDavid van Moolenbroek     av = (Char **)xcalloc((size_t)(n + 1), sizeof(Char **));
513*d1e4d7ceSDavid van Moolenbroek     t->t_dcom = av;
514*d1e4d7ceSDavid van Moolenbroek     n = 0;
515*d1e4d7ceSDavid van Moolenbroek     if (p2->word[0] == ')')
516*d1e4d7ceSDavid van Moolenbroek 	t->t_dflg = F_NOFORK;
517*d1e4d7ceSDavid van Moolenbroek     lp = 0;
518*d1e4d7ceSDavid van Moolenbroek     rp = 0;
519*d1e4d7ceSDavid van Moolenbroek     l = 0;
520*d1e4d7ceSDavid van Moolenbroek     for (p = p1; p != p2; p = p->next) {
521*d1e4d7ceSDavid van Moolenbroek 	c = p->word[0];
522*d1e4d7ceSDavid van Moolenbroek 	switch (c) {
523*d1e4d7ceSDavid van Moolenbroek 	case '(':
524*d1e4d7ceSDavid van Moolenbroek 	    if (l == 0) {
525*d1e4d7ceSDavid van Moolenbroek 		if (lp != 0 && !specp)
526*d1e4d7ceSDavid van Moolenbroek 		    seterror(ERR_BADPLP);
527*d1e4d7ceSDavid van Moolenbroek 		lp = p->next;
528*d1e4d7ceSDavid van Moolenbroek 	    }
529*d1e4d7ceSDavid van Moolenbroek 	    l++;
530*d1e4d7ceSDavid van Moolenbroek 	    goto savep;
531*d1e4d7ceSDavid van Moolenbroek 	case ')':
532*d1e4d7ceSDavid van Moolenbroek 	    l--;
533*d1e4d7ceSDavid van Moolenbroek 	    if (l == 0)
534*d1e4d7ceSDavid van Moolenbroek 		rp = p;
535*d1e4d7ceSDavid van Moolenbroek 	    goto savep;
536*d1e4d7ceSDavid van Moolenbroek 	case '>':
537*d1e4d7ceSDavid van Moolenbroek 	    if (l != 0)
538*d1e4d7ceSDavid van Moolenbroek 		goto savep;
539*d1e4d7ceSDavid van Moolenbroek 	    if (p->word[1] == '>')
540*d1e4d7ceSDavid van Moolenbroek 		t->t_dflg |= F_APPEND;
541*d1e4d7ceSDavid van Moolenbroek 	    if (p->next != p2 && eq(p->next->word, STRand)) {
542*d1e4d7ceSDavid van Moolenbroek 		t->t_dflg |= F_STDERR, p = p->next;
543*d1e4d7ceSDavid van Moolenbroek 		if (flags & (POUT | PERR)) {
544*d1e4d7ceSDavid van Moolenbroek 		    seterror(ERR_OUTRED);
545*d1e4d7ceSDavid van Moolenbroek 		    continue;
546*d1e4d7ceSDavid van Moolenbroek 		}
547*d1e4d7ceSDavid van Moolenbroek 	    }
548*d1e4d7ceSDavid van Moolenbroek 	    if (p->next != p2 && eq(p->next->word, STRbang))
549*d1e4d7ceSDavid van Moolenbroek 		t->t_dflg |= F_OVERWRITE, p = p->next;
550*d1e4d7ceSDavid van Moolenbroek 	    if (p->next == p2) {
551*d1e4d7ceSDavid van Moolenbroek 		seterror(ERR_MISRED);
552*d1e4d7ceSDavid van Moolenbroek 		continue;
553*d1e4d7ceSDavid van Moolenbroek 	    }
554*d1e4d7ceSDavid van Moolenbroek 	    p = p->next;
555*d1e4d7ceSDavid van Moolenbroek 	    if (any(RELPAR, p->word[0])) {
556*d1e4d7ceSDavid van Moolenbroek 		seterror(ERR_MISRED);
557*d1e4d7ceSDavid van Moolenbroek 		continue;
558*d1e4d7ceSDavid van Moolenbroek 	    }
559*d1e4d7ceSDavid van Moolenbroek 	    if ((flags & POUT) && ((flags & PERR) == 0 || t->t_drit))
560*d1e4d7ceSDavid van Moolenbroek 		seterror(ERR_OUTRED);
561*d1e4d7ceSDavid van Moolenbroek 	    else
562*d1e4d7ceSDavid van Moolenbroek 		t->t_drit = Strsave(p->word);
563*d1e4d7ceSDavid van Moolenbroek 	    continue;
564*d1e4d7ceSDavid van Moolenbroek 	case '<':
565*d1e4d7ceSDavid van Moolenbroek 	    if (l != 0)
566*d1e4d7ceSDavid van Moolenbroek 		goto savep;
567*d1e4d7ceSDavid van Moolenbroek 	    if (p->word[1] == '<')
568*d1e4d7ceSDavid van Moolenbroek 		t->t_dflg |= F_READ;
569*d1e4d7ceSDavid van Moolenbroek 	    if (p->next == p2) {
570*d1e4d7ceSDavid van Moolenbroek 		seterror(ERR_MISRED);
571*d1e4d7ceSDavid van Moolenbroek 		continue;
572*d1e4d7ceSDavid van Moolenbroek 	    }
573*d1e4d7ceSDavid van Moolenbroek 	    p = p->next;
574*d1e4d7ceSDavid van Moolenbroek 	    if (any(RELPAR, p->word[0])) {
575*d1e4d7ceSDavid van Moolenbroek 		seterror(ERR_MISRED);
576*d1e4d7ceSDavid van Moolenbroek 		continue;
577*d1e4d7ceSDavid van Moolenbroek 	    }
578*d1e4d7ceSDavid van Moolenbroek 	    if ((flags & PHERE) && (t->t_dflg & F_READ))
579*d1e4d7ceSDavid van Moolenbroek 		seterror(ERR_REDPAR);
580*d1e4d7ceSDavid van Moolenbroek 	    else if ((flags & PIN) || t->t_dlef)
581*d1e4d7ceSDavid van Moolenbroek 		seterror(ERR_INRED);
582*d1e4d7ceSDavid van Moolenbroek 	    else
583*d1e4d7ceSDavid van Moolenbroek 		t->t_dlef = Strsave(p->word);
584*d1e4d7ceSDavid van Moolenbroek 	    continue;
585*d1e4d7ceSDavid van Moolenbroek 	savep:
586*d1e4d7ceSDavid van Moolenbroek 	    if (!specp)
587*d1e4d7ceSDavid van Moolenbroek 		continue;
588*d1e4d7ceSDavid van Moolenbroek 	    /* FALLTHROUGH */
589*d1e4d7ceSDavid van Moolenbroek 	default:
590*d1e4d7ceSDavid van Moolenbroek 	    if (l != 0 && !specp)
591*d1e4d7ceSDavid van Moolenbroek 		continue;
592*d1e4d7ceSDavid van Moolenbroek 	    if (seterr == 0)
593*d1e4d7ceSDavid van Moolenbroek 		av[n] = Strsave(p->word);
594*d1e4d7ceSDavid van Moolenbroek 	    n++;
595*d1e4d7ceSDavid van Moolenbroek 	    continue;
596*d1e4d7ceSDavid van Moolenbroek 	}
597*d1e4d7ceSDavid van Moolenbroek     }
598*d1e4d7ceSDavid van Moolenbroek     if (lp != 0 && !specp) {
599*d1e4d7ceSDavid van Moolenbroek 	if (n != 0)
600*d1e4d7ceSDavid van Moolenbroek 	    seterror(ERR_BADPLPS);
601*d1e4d7ceSDavid van Moolenbroek 	t->t_dtyp = NODE_PAREN;
602*d1e4d7ceSDavid van Moolenbroek 	t->t_dspr = syn0(lp, rp, PHERE);
603*d1e4d7ceSDavid van Moolenbroek     }
604*d1e4d7ceSDavid van Moolenbroek     else {
605*d1e4d7ceSDavid van Moolenbroek 	if (n == 0)
606*d1e4d7ceSDavid van Moolenbroek 	    seterror(ERR_NULLCOM);
607*d1e4d7ceSDavid van Moolenbroek 	t->t_dtyp = NODE_COMMAND;
608*d1e4d7ceSDavid van Moolenbroek     }
609*d1e4d7ceSDavid van Moolenbroek     return (t);
610*d1e4d7ceSDavid van Moolenbroek }
611*d1e4d7ceSDavid van Moolenbroek 
612*d1e4d7ceSDavid van Moolenbroek void
freesyn(struct command * t)613*d1e4d7ceSDavid van Moolenbroek freesyn(struct command *t)
614*d1e4d7ceSDavid van Moolenbroek {
615*d1e4d7ceSDavid van Moolenbroek     Char **v;
616*d1e4d7ceSDavid van Moolenbroek 
617*d1e4d7ceSDavid van Moolenbroek     if (t == 0)
618*d1e4d7ceSDavid van Moolenbroek 	return;
619*d1e4d7ceSDavid van Moolenbroek     switch (t->t_dtyp) {
620*d1e4d7ceSDavid van Moolenbroek     case NODE_COMMAND:
621*d1e4d7ceSDavid van Moolenbroek 	for (v = t->t_dcom; *v; v++)
622*d1e4d7ceSDavid van Moolenbroek 	    xfree((ptr_t) * v);
623*d1e4d7ceSDavid van Moolenbroek 	xfree((ptr_t)(t->t_dcom));
624*d1e4d7ceSDavid van Moolenbroek 	xfree((ptr_t)t->t_dlef);
625*d1e4d7ceSDavid van Moolenbroek 	xfree((ptr_t)t->t_drit);
626*d1e4d7ceSDavid van Moolenbroek 	break;
627*d1e4d7ceSDavid van Moolenbroek     case NODE_PAREN:
628*d1e4d7ceSDavid van Moolenbroek 	freesyn(t->t_dspr);
629*d1e4d7ceSDavid van Moolenbroek 	xfree((ptr_t)t->t_dlef);
630*d1e4d7ceSDavid van Moolenbroek 	xfree((ptr_t)t->t_drit);
631*d1e4d7ceSDavid van Moolenbroek 	break;
632*d1e4d7ceSDavid van Moolenbroek     case NODE_AND:
633*d1e4d7ceSDavid van Moolenbroek     case NODE_OR:
634*d1e4d7ceSDavid van Moolenbroek     case NODE_PIPE:
635*d1e4d7ceSDavid van Moolenbroek     case NODE_LIST:
636*d1e4d7ceSDavid van Moolenbroek 	freesyn(t->t_dcar), freesyn(t->t_dcdr);
637*d1e4d7ceSDavid van Moolenbroek 	break;
638*d1e4d7ceSDavid van Moolenbroek     }
639*d1e4d7ceSDavid van Moolenbroek     xfree((ptr_t)t);
640*d1e4d7ceSDavid van Moolenbroek }
641