1*7f63690aSdholland /* $NetBSD: parse.c,v 1.21 2020/08/09 00:34:21 dholland Exp $ */
249f0ad86Scgd
361f28255Scgd /*-
4cee2bad8Smycroft * Copyright (c) 1980, 1991, 1993
5cee2bad8Smycroft * The Regents of the University of California. All rights reserved.
661f28255Scgd *
761f28255Scgd * Redistribution and use in source and binary forms, with or without
861f28255Scgd * modification, are permitted provided that the following conditions
961f28255Scgd * are met:
1061f28255Scgd * 1. Redistributions of source code must retain the above copyright
1161f28255Scgd * notice, this list of conditions and the following disclaimer.
1261f28255Scgd * 2. Redistributions in binary form must reproduce the above copyright
1361f28255Scgd * notice, this list of conditions and the following disclaimer in the
1461f28255Scgd * documentation and/or other materials provided with the distribution.
15b5b29542Sagc * 3. Neither the name of the University nor the names of its contributors
1661f28255Scgd * may be used to endorse or promote products derived from this software
1761f28255Scgd * without specific prior written permission.
1861f28255Scgd *
1961f28255Scgd * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2061f28255Scgd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2161f28255Scgd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2261f28255Scgd * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2361f28255Scgd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2461f28255Scgd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2561f28255Scgd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2661f28255Scgd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2761f28255Scgd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2861f28255Scgd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2961f28255Scgd * SUCH DAMAGE.
3061f28255Scgd */
3161f28255Scgd
328ea378c6Schristos #include <sys/cdefs.h>
3361f28255Scgd #ifndef lint
3449f0ad86Scgd #if 0
3549f0ad86Scgd static char sccsid[] = "@(#)parse.c 8.1 (Berkeley) 5/31/93";
3649f0ad86Scgd #else
37*7f63690aSdholland __RCSID("$NetBSD: parse.c,v 1.21 2020/08/09 00:34:21 dholland Exp $");
3849f0ad86Scgd #endif
3961f28255Scgd #endif /* not lint */
4061f28255Scgd
4161f28255Scgd #include <sys/types.h>
42b771e65bSwiz
4318158540Swiz #include <stdarg.h>
4461f28255Scgd #include <stdlib.h>
4561f28255Scgd #include <string.h>
46b771e65bSwiz
4761f28255Scgd #include "csh.h"
4861f28255Scgd #include "extern.h"
4961f28255Scgd
50b771e65bSwiz static void asyntax(struct wordent *, struct wordent *);
51b771e65bSwiz static void asyn0(struct wordent *, struct wordent *);
52b771e65bSwiz static void asyn3(struct wordent *, struct wordent *);
53b771e65bSwiz static struct wordent *freenod(struct wordent *, struct wordent *);
54b771e65bSwiz static struct command *syn0(struct wordent *, struct wordent *, int);
55b771e65bSwiz static struct command *syn1(struct wordent *, struct wordent *, int);
56b771e65bSwiz static struct command *syn1a(struct wordent *, struct wordent *, int);
57b771e65bSwiz static struct command *syn1b(struct wordent *, struct wordent *, int);
58b771e65bSwiz static struct command *syn2(struct wordent *, struct wordent *, int);
59b771e65bSwiz static struct command *syn3(struct wordent *, struct wordent *, int);
6061f28255Scgd
6161f28255Scgd #define ALEFT 21 /* max of 20 alias expansions */
6261f28255Scgd #define HLEFT 11 /* max of 10 history expansions */
6361f28255Scgd /*
6461f28255Scgd * Perform aliasing on the word list lex
6561f28255Scgd * Do a (very rudimentary) parse to separate into commands.
6661f28255Scgd * If word 0 of a command has an alias, do it.
6761f28255Scgd * Repeat a maximum of 20 times.
6861f28255Scgd */
6961f28255Scgd static int aleft;
7061f28255Scgd extern int hleft;
71b771e65bSwiz
7261f28255Scgd void
alias(struct wordent * lexp)73537f55c6Slukem alias(struct wordent *lexp)
7461f28255Scgd {
7561f28255Scgd jmp_buf osetexit;
7661f28255Scgd
7761f28255Scgd aleft = ALEFT;
7861f28255Scgd hleft = HLEFT;
7961f28255Scgd getexit(osetexit);
8061f28255Scgd (void)setexit();
8161f28255Scgd if (haderr) {
8261f28255Scgd resexit(osetexit);
8361f28255Scgd reset();
8461f28255Scgd }
85ee9e50eaSmycroft if (--aleft == 0)
8661f28255Scgd stderror(ERR_ALIASLOOP);
87537f55c6Slukem asyntax(lexp->next, lexp);
8861f28255Scgd resexit(osetexit);
8961f28255Scgd }
9061f28255Scgd
9161f28255Scgd static void
asyntax(struct wordent * p1,struct wordent * p2)92b771e65bSwiz asyntax(struct wordent *p1, struct wordent *p2)
9361f28255Scgd {
9461f28255Scgd while (p1 != p2)
9561f28255Scgd if (any(";&\n", p1->word[0]))
9661f28255Scgd p1 = p1->next;
9761f28255Scgd else {
9861f28255Scgd asyn0(p1, p2);
9961f28255Scgd return;
10061f28255Scgd }
10161f28255Scgd }
10261f28255Scgd
10361f28255Scgd static void
asyn0(struct wordent * p1,struct wordent * p2)104b771e65bSwiz asyn0(struct wordent *p1, struct wordent *p2)
10561f28255Scgd {
10676adbe2bStls struct wordent *p;
107b771e65bSwiz int l;
10861f28255Scgd
109b771e65bSwiz l = 0;
11061f28255Scgd for (p = p1; p != p2; p = p->next)
11161f28255Scgd switch (p->word[0]) {
11261f28255Scgd case '(':
11361f28255Scgd l++;
11461f28255Scgd continue;
11561f28255Scgd case ')':
11661f28255Scgd l--;
117ee9e50eaSmycroft if (l < 0)
11861f28255Scgd stderror(ERR_TOOMANYRP);
11961f28255Scgd continue;
12061f28255Scgd case '>':
12161f28255Scgd if (p->next != p2 && eq(p->next->word, STRand))
12261f28255Scgd p = p->next;
12361f28255Scgd continue;
12461f28255Scgd case '&':
12561f28255Scgd case '|':
12661f28255Scgd case ';':
12761f28255Scgd case '\n':
12861f28255Scgd if (l != 0)
12961f28255Scgd continue;
13061f28255Scgd asyn3(p1, p);
13161f28255Scgd asyntax(p->next, p2);
13261f28255Scgd return;
13361f28255Scgd }
13461f28255Scgd if (l == 0)
13561f28255Scgd asyn3(p1, p2);
13661f28255Scgd }
13761f28255Scgd
13861f28255Scgd static void
asyn3(struct wordent * p1,struct wordent * p2)139b771e65bSwiz asyn3(struct wordent *p1, struct wordent *p2)
14061f28255Scgd {
14176adbe2bStls struct varent *ap;
14261f28255Scgd struct wordent alout;
143b79c2ef2Schristos int redid;
14461f28255Scgd
14561f28255Scgd if (p1 == p2)
14661f28255Scgd return;
14761f28255Scgd if (p1->word[0] == '(') {
14861f28255Scgd for (p2 = p2->prev; p2->word[0] != ')'; p2 = p2->prev)
14961f28255Scgd if (p2 == p1)
15061f28255Scgd return;
15161f28255Scgd if (p2 == p1->next)
15261f28255Scgd return;
15361f28255Scgd asyn0(p1->next, p2);
15461f28255Scgd return;
15561f28255Scgd }
15661f28255Scgd ap = adrof1(p1->word, &aliases);
15761f28255Scgd if (ap == 0)
15861f28255Scgd return;
15961f28255Scgd alhistp = p1->prev;
16061f28255Scgd alhistt = p2;
16161f28255Scgd alvec = ap->vec;
16261f28255Scgd redid = lex(&alout);
16361f28255Scgd alhistp = alhistt = 0;
16461f28255Scgd alvec = 0;
16561f28255Scgd if (seterr) {
16661f28255Scgd freelex(&alout);
16761f28255Scgd stderror(ERR_OLD);
16861f28255Scgd }
16961f28255Scgd if (p1->word[0] && eq(p1->word, alout.next->word)) {
170b771e65bSwiz Char *cp;
17161f28255Scgd
172b771e65bSwiz cp = alout.next->word;
17361f28255Scgd alout.next->word = Strspl(STRQNULL, cp);
1741767ce60Schristos free(cp);
17561f28255Scgd }
17661f28255Scgd p1 = freenod(p1, redid ? p2 : p1->next);
17761f28255Scgd if (alout.next != &alout) {
17861f28255Scgd p1->next->prev = alout.prev->prev;
17961f28255Scgd alout.prev->prev->next = p1->next;
18061f28255Scgd alout.next->prev = p1;
18161f28255Scgd p1->next = alout.next;
1821767ce60Schristos free(alout.prev->word);
1831767ce60Schristos free(alout.prev);
18461f28255Scgd }
18561f28255Scgd reset(); /* throw! */
18661f28255Scgd }
18761f28255Scgd
18861f28255Scgd static struct wordent *
freenod(struct wordent * p1,struct wordent * p2)189b771e65bSwiz freenod(struct wordent *p1, struct wordent *p2)
19061f28255Scgd {
191b771e65bSwiz struct wordent *retp;
19261f28255Scgd
193b771e65bSwiz retp = p1->prev;
19461f28255Scgd while (p1 != p2) {
1951767ce60Schristos free(p1->word);
19661f28255Scgd p1 = p1->next;
1971767ce60Schristos free(p1->prev);
19861f28255Scgd }
19961f28255Scgd retp->next = p2;
20061f28255Scgd p2->prev = retp;
20161f28255Scgd return (retp);
20261f28255Scgd }
20361f28255Scgd
20461f28255Scgd #define PHERE 1
20561f28255Scgd #define PIN 2
20661f28255Scgd #define POUT 4
207cee2bad8Smycroft #define PERR 8
20861f28255Scgd
20961f28255Scgd /*
21061f28255Scgd * syntax
21161f28255Scgd * empty
21261f28255Scgd * syn0
21361f28255Scgd */
21461f28255Scgd struct command *
syntax(struct wordent * p1,struct wordent * p2,int flags)215b771e65bSwiz syntax(struct wordent *p1, struct wordent *p2, int flags)
21661f28255Scgd {
21761f28255Scgd while (p1 != p2)
21861f28255Scgd if (any(";&\n", p1->word[0]))
21961f28255Scgd p1 = p1->next;
22061f28255Scgd else
22161f28255Scgd return (syn0(p1, p2, flags));
22261f28255Scgd return (0);
22361f28255Scgd }
22461f28255Scgd
22561f28255Scgd /*
22661f28255Scgd * syn0
22761f28255Scgd * syn1
22861f28255Scgd * syn1 & syntax
22961f28255Scgd */
23061f28255Scgd static struct command *
syn0(struct wordent * p1,struct wordent * p2,int flags)231b771e65bSwiz syn0(struct wordent *p1, struct wordent *p2, int flags)
23261f28255Scgd {
23376adbe2bStls struct wordent *p;
23476adbe2bStls struct command *t, *t1;
23561f28255Scgd int l;
23661f28255Scgd
23761f28255Scgd l = 0;
23861f28255Scgd for (p = p1; p != p2; p = p->next)
23961f28255Scgd switch (p->word[0]) {
24061f28255Scgd case '(':
24161f28255Scgd l++;
24261f28255Scgd continue;
24361f28255Scgd case ')':
24461f28255Scgd l--;
24561f28255Scgd if (l < 0)
24661f28255Scgd seterror(ERR_TOOMANYRP);
24761f28255Scgd continue;
24861f28255Scgd case '|':
24961f28255Scgd if (p->word[1] == '|')
25061f28255Scgd continue;
251cdbd74daSmycroft /* FALLTHROUGH */
25261f28255Scgd case '>':
25361f28255Scgd if (p->next != p2 && eq(p->next->word, STRand))
25461f28255Scgd p = p->next;
25561f28255Scgd continue;
25661f28255Scgd case '&':
25761f28255Scgd if (l != 0)
25861f28255Scgd break;
25961f28255Scgd if (p->word[1] == '&')
26061f28255Scgd continue;
26161f28255Scgd t1 = syn1(p1, p, flags);
26261f28255Scgd if (t1->t_dtyp == NODE_LIST ||
26361f28255Scgd t1->t_dtyp == NODE_AND ||
26461f28255Scgd t1->t_dtyp == NODE_OR) {
26585bd10cbSdholland t = xcalloc(1, sizeof(*t));
26661f28255Scgd t->t_dtyp = NODE_PAREN;
26761f28255Scgd t->t_dflg = F_AMPERSAND | F_NOINTERRUPT;
26861f28255Scgd t->t_dspr = t1;
26961f28255Scgd t1 = t;
27061f28255Scgd }
27161f28255Scgd else
27261f28255Scgd t1->t_dflg |= F_AMPERSAND | F_NOINTERRUPT;
27385bd10cbSdholland t = xcalloc(1, sizeof(*t));
27461f28255Scgd t->t_dtyp = NODE_LIST;
27561f28255Scgd t->t_dflg = 0;
27661f28255Scgd t->t_dcar = t1;
27761f28255Scgd t->t_dcdr = syntax(p, p2, flags);
27861f28255Scgd return (t);
27961f28255Scgd }
28061f28255Scgd if (l == 0)
28161f28255Scgd return (syn1(p1, p2, flags));
28261f28255Scgd seterror(ERR_TOOMANYLP);
28361f28255Scgd return (0);
28461f28255Scgd }
28561f28255Scgd
28661f28255Scgd /*
28761f28255Scgd * syn1
28861f28255Scgd * syn1a
28961f28255Scgd * syn1a ; syntax
29061f28255Scgd */
29161f28255Scgd static struct command *
syn1(struct wordent * p1,struct wordent * p2,int flags)292b771e65bSwiz syn1(struct wordent *p1, struct wordent *p2, int flags)
29361f28255Scgd {
29476adbe2bStls struct wordent *p;
29576adbe2bStls struct command *t;
29661f28255Scgd int l;
29761f28255Scgd
29861f28255Scgd l = 0;
29961f28255Scgd for (p = p1; p != p2; p = p->next)
30061f28255Scgd switch (p->word[0]) {
30161f28255Scgd case '(':
30261f28255Scgd l++;
30361f28255Scgd continue;
30461f28255Scgd case ')':
30561f28255Scgd l--;
30661f28255Scgd continue;
30761f28255Scgd case ';':
30861f28255Scgd case '\n':
30961f28255Scgd if (l != 0)
31061f28255Scgd break;
31185bd10cbSdholland t = xcalloc(1, sizeof(*t));
31261f28255Scgd t->t_dtyp = NODE_LIST;
31361f28255Scgd t->t_dcar = syn1a(p1, p, flags);
31461f28255Scgd t->t_dcdr = syntax(p->next, p2, flags);
31561f28255Scgd if (t->t_dcdr == 0)
31661f28255Scgd t->t_dcdr = t->t_dcar, t->t_dcar = 0;
31761f28255Scgd return (t);
31861f28255Scgd }
31961f28255Scgd return (syn1a(p1, p2, flags));
32061f28255Scgd }
32161f28255Scgd
32261f28255Scgd /*
32361f28255Scgd * syn1a
32461f28255Scgd * syn1b
32561f28255Scgd * syn1b || syn1a
32661f28255Scgd */
32761f28255Scgd static struct command *
syn1a(struct wordent * p1,struct wordent * p2,int flags)328b771e65bSwiz syn1a(struct wordent *p1, struct wordent *p2, int flags)
32961f28255Scgd {
33076adbe2bStls struct wordent *p;
33176adbe2bStls struct command *t;
332b771e65bSwiz int l;
33361f28255Scgd
334b771e65bSwiz l = 0;
33561f28255Scgd for (p = p1; p != p2; p = p->next)
33661f28255Scgd switch (p->word[0]) {
33761f28255Scgd case '(':
33861f28255Scgd l++;
33961f28255Scgd continue;
34061f28255Scgd case ')':
34161f28255Scgd l--;
34261f28255Scgd continue;
34361f28255Scgd case '|':
34461f28255Scgd if (p->word[1] != '|')
34561f28255Scgd continue;
34661f28255Scgd if (l == 0) {
34785bd10cbSdholland t = xcalloc(1, sizeof(*t));
34861f28255Scgd t->t_dtyp = NODE_OR;
34961f28255Scgd t->t_dcar = syn1b(p1, p, flags);
35061f28255Scgd t->t_dcdr = syn1a(p->next, p2, flags);
35161f28255Scgd t->t_dflg = 0;
35261f28255Scgd return (t);
35361f28255Scgd }
35461f28255Scgd continue;
35561f28255Scgd }
35661f28255Scgd return (syn1b(p1, p2, flags));
35761f28255Scgd }
35861f28255Scgd
35961f28255Scgd /*
36061f28255Scgd * syn1b
36161f28255Scgd * syn2
36261f28255Scgd * syn2 && syn1b
36361f28255Scgd */
36461f28255Scgd static struct command *
syn1b(struct wordent * p1,struct wordent * p2,int flags)365b771e65bSwiz syn1b(struct wordent *p1, struct wordent *p2, int flags)
36661f28255Scgd {
36776adbe2bStls struct wordent *p;
36876adbe2bStls struct command *t;
369b771e65bSwiz int l;
37061f28255Scgd
371b771e65bSwiz l = 0;
37261f28255Scgd for (p = p1; p != p2; p = p->next)
37361f28255Scgd switch (p->word[0]) {
37461f28255Scgd case '(':
37561f28255Scgd l++;
37661f28255Scgd continue;
37761f28255Scgd case ')':
37861f28255Scgd l--;
37961f28255Scgd continue;
38061f28255Scgd case '&':
38161f28255Scgd if (p->word[1] == '&' && l == 0) {
38285bd10cbSdholland t = xcalloc(1, sizeof(*t));
38361f28255Scgd t->t_dtyp = NODE_AND;
38461f28255Scgd t->t_dcar = syn2(p1, p, flags);
38561f28255Scgd t->t_dcdr = syn1b(p->next, p2, flags);
38661f28255Scgd t->t_dflg = 0;
38761f28255Scgd return (t);
38861f28255Scgd }
38961f28255Scgd continue;
39061f28255Scgd }
39161f28255Scgd return (syn2(p1, p2, flags));
39261f28255Scgd }
39361f28255Scgd
39461f28255Scgd /*
39561f28255Scgd * syn2
39661f28255Scgd * syn3
39761f28255Scgd * syn3 | syn2
39861f28255Scgd * syn3 |& syn2
39961f28255Scgd */
40061f28255Scgd static struct command *
syn2(struct wordent * p1,struct wordent * p2,int flags)401b771e65bSwiz syn2(struct wordent *p1, struct wordent *p2, int flags)
40261f28255Scgd {
40376adbe2bStls struct wordent *p, *pn;
40476adbe2bStls struct command *t;
405b771e65bSwiz int f, l;
40661f28255Scgd
407b771e65bSwiz l = 0;
40861f28255Scgd for (p = p1; p != p2; p = p->next)
40961f28255Scgd switch (p->word[0]) {
41061f28255Scgd case '(':
41161f28255Scgd l++;
41261f28255Scgd continue;
41361f28255Scgd case ')':
41461f28255Scgd l--;
41561f28255Scgd continue;
41661f28255Scgd case '|':
41761f28255Scgd if (l != 0)
41861f28255Scgd continue;
41985bd10cbSdholland t = xcalloc(1, sizeof(*t));
42061f28255Scgd f = flags | POUT;
42161f28255Scgd pn = p->next;
42261f28255Scgd if (pn != p2 && pn->word[0] == '&') {
423cee2bad8Smycroft f |= PERR;
42461f28255Scgd t->t_dflg |= F_STDERR;
42561f28255Scgd }
42661f28255Scgd t->t_dtyp = NODE_PIPE;
42761f28255Scgd t->t_dcar = syn3(p1, p, f);
42861f28255Scgd if (pn != p2 && pn->word[0] == '&')
42961f28255Scgd p = pn;
43061f28255Scgd t->t_dcdr = syn2(p->next, p2, flags | PIN);
43161f28255Scgd return (t);
43261f28255Scgd }
43361f28255Scgd return (syn3(p1, p2, flags));
43461f28255Scgd }
43561f28255Scgd
43661f28255Scgd static char RELPAR[] = {'<', '>', '(', ')', '\0'};
43761f28255Scgd
43861f28255Scgd /*
43961f28255Scgd * syn3
44061f28255Scgd * ( syn0 ) [ < in ] [ > out ]
44161f28255Scgd * word word* [ < in ] [ > out ]
44261f28255Scgd * KEYWORD ( word* ) word* [ < in ] [ > out ]
44361f28255Scgd *
44461f28255Scgd * KEYWORD = (@ exit foreach if set switch test while)
44561f28255Scgd */
44661f28255Scgd static struct command *
syn3(struct wordent * p1,struct wordent * p2,int flags)447b771e65bSwiz syn3(struct wordent *p1, struct wordent *p2, int flags)
44861f28255Scgd {
449b771e65bSwiz struct wordent *lp, *p, *rp;
45076adbe2bStls struct command *t;
45161f28255Scgd Char **av;
452b771e65bSwiz int c, l, n;
453b79c2ef2Schristos int specp;
45461f28255Scgd
455b771e65bSwiz specp = 0;
45661f28255Scgd if (p1 != p2) {
45761f28255Scgd p = p1;
45861f28255Scgd again:
45961f28255Scgd switch (srchx(p->word)) {
46061f28255Scgd case T_ELSE:
46161f28255Scgd p = p->next;
46261f28255Scgd if (p != p2)
46361f28255Scgd goto again;
46461f28255Scgd break;
46561f28255Scgd case T_EXIT:
46661f28255Scgd case T_FOREACH:
46761f28255Scgd case T_IF:
46861f28255Scgd case T_LET:
46961f28255Scgd case T_SET:
47061f28255Scgd case T_SWITCH:
47161f28255Scgd case T_WHILE:
47261f28255Scgd specp = 1;
47361f28255Scgd break;
47461f28255Scgd }
47561f28255Scgd }
47661f28255Scgd n = 0;
47761f28255Scgd l = 0;
47861f28255Scgd for (p = p1; p != p2; p = p->next)
47961f28255Scgd switch (p->word[0]) {
48061f28255Scgd case '(':
48161f28255Scgd if (specp)
48261f28255Scgd n++;
48361f28255Scgd l++;
48461f28255Scgd continue;
48561f28255Scgd case ')':
48661f28255Scgd if (specp)
48761f28255Scgd n++;
48861f28255Scgd l--;
48961f28255Scgd continue;
49061f28255Scgd case '>':
49161f28255Scgd case '<':
49261f28255Scgd if (l != 0) {
49361f28255Scgd if (specp)
49461f28255Scgd n++;
49561f28255Scgd continue;
49661f28255Scgd }
49761f28255Scgd if (p->next == p2)
49861f28255Scgd continue;
49961f28255Scgd if (any(RELPAR, p->next->word[0]))
50061f28255Scgd continue;
50161f28255Scgd n--;
50261f28255Scgd continue;
50361f28255Scgd default:
50461f28255Scgd if (!specp && l != 0)
50561f28255Scgd continue;
50661f28255Scgd n++;
50761f28255Scgd continue;
50861f28255Scgd }
50961f28255Scgd if (n < 0)
51061f28255Scgd n = 0;
51185bd10cbSdholland t = xcalloc(1, sizeof(*t));
512*7f63690aSdholland /* XXX the cast is needed because n is signed */
513*7f63690aSdholland av = xcalloc((size_t)(n + 1), sizeof(*av));
51461f28255Scgd t->t_dcom = av;
51561f28255Scgd n = 0;
51661f28255Scgd if (p2->word[0] == ')')
51761f28255Scgd t->t_dflg = F_NOFORK;
51861f28255Scgd lp = 0;
51961f28255Scgd rp = 0;
52061f28255Scgd l = 0;
52161f28255Scgd for (p = p1; p != p2; p = p->next) {
52261f28255Scgd c = p->word[0];
52361f28255Scgd switch (c) {
52461f28255Scgd case '(':
52561f28255Scgd if (l == 0) {
52661f28255Scgd if (lp != 0 && !specp)
52761f28255Scgd seterror(ERR_BADPLP);
52861f28255Scgd lp = p->next;
52961f28255Scgd }
53061f28255Scgd l++;
53161f28255Scgd goto savep;
53261f28255Scgd case ')':
53361f28255Scgd l--;
53461f28255Scgd if (l == 0)
53561f28255Scgd rp = p;
53661f28255Scgd goto savep;
53761f28255Scgd case '>':
53861f28255Scgd if (l != 0)
53961f28255Scgd goto savep;
54061f28255Scgd if (p->word[1] == '>')
54161f28255Scgd t->t_dflg |= F_APPEND;
54261f28255Scgd if (p->next != p2 && eq(p->next->word, STRand)) {
54361f28255Scgd t->t_dflg |= F_STDERR, p = p->next;
544cee2bad8Smycroft if (flags & (POUT | PERR)) {
54561f28255Scgd seterror(ERR_OUTRED);
54661f28255Scgd continue;
54761f28255Scgd }
54861f28255Scgd }
54961f28255Scgd if (p->next != p2 && eq(p->next->word, STRbang))
55061f28255Scgd t->t_dflg |= F_OVERWRITE, p = p->next;
55161f28255Scgd if (p->next == p2) {
55261f28255Scgd seterror(ERR_MISRED);
55361f28255Scgd continue;
55461f28255Scgd }
55561f28255Scgd p = p->next;
55661f28255Scgd if (any(RELPAR, p->word[0])) {
55761f28255Scgd seterror(ERR_MISRED);
55861f28255Scgd continue;
55961f28255Scgd }
560cee2bad8Smycroft if ((flags & POUT) && ((flags & PERR) == 0 || t->t_drit))
56161f28255Scgd seterror(ERR_OUTRED);
56261f28255Scgd else
56361f28255Scgd t->t_drit = Strsave(p->word);
56461f28255Scgd continue;
56561f28255Scgd case '<':
56661f28255Scgd if (l != 0)
56761f28255Scgd goto savep;
56861f28255Scgd if (p->word[1] == '<')
56961f28255Scgd t->t_dflg |= F_READ;
57061f28255Scgd if (p->next == p2) {
57161f28255Scgd seterror(ERR_MISRED);
57261f28255Scgd continue;
57361f28255Scgd }
57461f28255Scgd p = p->next;
57561f28255Scgd if (any(RELPAR, p->word[0])) {
57661f28255Scgd seterror(ERR_MISRED);
57761f28255Scgd continue;
57861f28255Scgd }
57961f28255Scgd if ((flags & PHERE) && (t->t_dflg & F_READ))
58061f28255Scgd seterror(ERR_REDPAR);
58161f28255Scgd else if ((flags & PIN) || t->t_dlef)
58261f28255Scgd seterror(ERR_INRED);
58361f28255Scgd else
58461f28255Scgd t->t_dlef = Strsave(p->word);
58561f28255Scgd continue;
58661f28255Scgd savep:
58761f28255Scgd if (!specp)
58861f28255Scgd continue;
589cdbd74daSmycroft /* FALLTHROUGH */
59061f28255Scgd default:
59161f28255Scgd if (l != 0 && !specp)
59261f28255Scgd continue;
59361f28255Scgd if (seterr == 0)
59461f28255Scgd av[n] = Strsave(p->word);
59561f28255Scgd n++;
59661f28255Scgd continue;
59761f28255Scgd }
59861f28255Scgd }
59961f28255Scgd if (lp != 0 && !specp) {
60061f28255Scgd if (n != 0)
60161f28255Scgd seterror(ERR_BADPLPS);
60261f28255Scgd t->t_dtyp = NODE_PAREN;
60361f28255Scgd t->t_dspr = syn0(lp, rp, PHERE);
60461f28255Scgd }
60561f28255Scgd else {
60661f28255Scgd if (n == 0)
60761f28255Scgd seterror(ERR_NULLCOM);
60861f28255Scgd t->t_dtyp = NODE_COMMAND;
60961f28255Scgd }
61061f28255Scgd return (t);
61161f28255Scgd }
61261f28255Scgd
61361f28255Scgd void
freesyn(struct command * t)614b771e65bSwiz freesyn(struct command *t)
61561f28255Scgd {
61676adbe2bStls Char **v;
61761f28255Scgd
61861f28255Scgd if (t == 0)
61961f28255Scgd return;
62061f28255Scgd switch (t->t_dtyp) {
62161f28255Scgd case NODE_COMMAND:
62261f28255Scgd for (v = t->t_dcom; *v; v++)
6231767ce60Schristos free(* v);
6241767ce60Schristos free(t->t_dcom);
6251767ce60Schristos free(t->t_dlef);
6261767ce60Schristos free(t->t_drit);
62761f28255Scgd break;
62861f28255Scgd case NODE_PAREN:
62961f28255Scgd freesyn(t->t_dspr);
6301767ce60Schristos free(t->t_dlef);
6311767ce60Schristos free(t->t_drit);
63261f28255Scgd break;
63361f28255Scgd case NODE_AND:
63461f28255Scgd case NODE_OR:
63561f28255Scgd case NODE_PIPE:
63661f28255Scgd case NODE_LIST:
63761f28255Scgd freesyn(t->t_dcar), freesyn(t->t_dcdr);
63861f28255Scgd break;
63961f28255Scgd }
6401767ce60Schristos free(t);
64161f28255Scgd }
642