147823Sbostic /*-
2*60765Sbostic * Copyright (c) 1980, 1991, 1993
3*60765Sbostic * The Regents of the University of California. All rights reserved.
447823Sbostic *
547823Sbostic * %sccs.include.redist.c%
621939Sdist */
721939Sdist
817511Sedward #ifndef lint
9*60765Sbostic static char sccsid[] = "@(#)parse.c 8.1 (Berkeley) 05/31/93";
1047823Sbostic #endif /* not lint */
111301Sbill
1250028Sbostic #include <sys/types.h>
1350028Sbostic #include <stdlib.h>
1450028Sbostic #include <string.h>
1550033Schristos #if __STDC__
1650033Schristos # include <stdarg.h>
1750033Schristos #else
1850033Schristos # include <varargs.h>
1950033Schristos #endif
2050033Schristos
2150023Sbostic #include "csh.h"
2250023Sbostic #include "extern.h"
231301Sbill
2450024Schristos static void asyntax __P((struct wordent *, struct wordent *));
2550024Schristos static void asyn0 __P((struct wordent *, struct wordent *));
2650024Schristos static void asyn3 __P((struct wordent *, struct wordent *));
2750024Schristos static struct wordent
2850024Schristos *freenod __P((struct wordent *, struct wordent *));
2950024Schristos static struct command
3050024Schristos *syn0 __P((struct wordent *, struct wordent *, int));
3150024Schristos static struct command
3250024Schristos *syn1 __P((struct wordent *, struct wordent *, int));
3350024Schristos static struct command
3450024Schristos *syn1a __P((struct wordent *, struct wordent *, int));
3550024Schristos static struct command
3650024Schristos *syn1b __P((struct wordent *, struct wordent *, int));
3750024Schristos static struct command
3850024Schristos *syn2 __P((struct wordent *, struct wordent *, int));
3950024Schristos static struct command
4050024Schristos *syn3 __P((struct wordent *, struct wordent *, int));
411301Sbill
4249992Sbostic #define ALEFT 21 /* max of 20 alias expansions */
4349992Sbostic #define HLEFT 11 /* max of 10 history expansions */
441301Sbill /*
451301Sbill * Perform aliasing on the word list lex
461301Sbill * Do a (very rudimentary) parse to separate into commands.
471301Sbill * If word 0 of a command has an alias, do it.
481301Sbill * Repeat a maximum of 20 times.
491301Sbill */
5049992Sbostic static int aleft;
5149992Sbostic extern int hleft;
5249992Sbostic void
alias(lex)531301Sbill alias(lex)
5449992Sbostic register struct wordent *lex;
551301Sbill {
5649992Sbostic jmp_buf osetexit;
571301Sbill
5849992Sbostic aleft = ALEFT;
5949992Sbostic hleft = HLEFT;
6049992Sbostic getexit(osetexit);
6149992Sbostic (void) setexit();
6249992Sbostic if (haderr) {
631301Sbill resexit(osetexit);
6449992Sbostic reset();
6549992Sbostic }
6649992Sbostic if (--aleft == 0)
6749992Sbostic stderror(ERR_ALIASLOOP);
6849992Sbostic asyntax(lex->next, lex);
6949992Sbostic resexit(osetexit);
701301Sbill }
711301Sbill
7249992Sbostic static void
asyntax(p1,p2)731301Sbill asyntax(p1, p2)
7449992Sbostic register struct wordent *p1, *p2;
751301Sbill {
7649992Sbostic while (p1 != p2)
7749992Sbostic if (any(";&\n", p1->word[0]))
7849992Sbostic p1 = p1->next;
7949992Sbostic else {
8049992Sbostic asyn0(p1, p2);
8149992Sbostic return;
8249992Sbostic }
831301Sbill }
841301Sbill
8549992Sbostic static void
asyn0(p1,p2)861301Sbill asyn0(p1, p2)
8749992Sbostic struct wordent *p1;
8849992Sbostic register struct wordent *p2;
891301Sbill {
9049992Sbostic register struct wordent *p;
9149992Sbostic register int l = 0;
921301Sbill
9349992Sbostic for (p = p1; p != p2; p = p->next)
9449992Sbostic switch (p->word[0]) {
951301Sbill
9649992Sbostic case '(':
9749992Sbostic l++;
9849992Sbostic continue;
991301Sbill
10049992Sbostic case ')':
10149992Sbostic l--;
10249992Sbostic if (l < 0)
10349992Sbostic stderror(ERR_TOOMANYRP);
10449992Sbostic continue;
1051301Sbill
10649992Sbostic case '>':
10749992Sbostic if (p->next != p2 && eq(p->next->word, STRand))
10849992Sbostic p = p->next;
10949992Sbostic continue;
1101301Sbill
11149992Sbostic case '&':
11249992Sbostic case '|':
11349992Sbostic case ';':
11449992Sbostic case '\n':
11549992Sbostic if (l != 0)
11649992Sbostic continue;
11749992Sbostic asyn3(p1, p);
11849992Sbostic asyntax(p->next, p2);
11949992Sbostic return;
12049992Sbostic }
12149992Sbostic if (l == 0)
12249992Sbostic asyn3(p1, p2);
1231301Sbill }
1241301Sbill
12549992Sbostic static void
asyn3(p1,p2)1261301Sbill asyn3(p1, p2)
12749992Sbostic struct wordent *p1;
12849992Sbostic register struct wordent *p2;
1291301Sbill {
13049992Sbostic register struct varent *ap;
13149992Sbostic struct wordent alout;
13249992Sbostic register bool redid;
1331301Sbill
13449992Sbostic if (p1 == p2)
13549992Sbostic return;
13649992Sbostic if (p1->word[0] == '(') {
13749992Sbostic for (p2 = p2->prev; p2->word[0] != ')'; p2 = p2->prev)
13849992Sbostic if (p2 == p1)
1391301Sbill return;
14049992Sbostic if (p2 == p1->next)
14149992Sbostic return;
14249992Sbostic asyn0(p1->next, p2);
14349992Sbostic return;
14449992Sbostic }
14549992Sbostic ap = adrof1(p1->word, &aliases);
14649992Sbostic if (ap == 0)
14749992Sbostic return;
14849992Sbostic alhistp = p1->prev;
14949992Sbostic alhistt = p2;
15049992Sbostic alvec = ap->vec;
15149992Sbostic redid = lex(&alout);
15249992Sbostic alhistp = alhistt = 0;
15349992Sbostic alvec = 0;
15449992Sbostic if (seterr) {
15549992Sbostic freelex(&alout);
15649992Sbostic stderror(ERR_OLD);
15749992Sbostic }
15849992Sbostic if (p1->word[0] && eq(p1->word, alout.next->word)) {
15949992Sbostic Char *cp = alout.next->word;
1601301Sbill
16149992Sbostic alout.next->word = Strspl(STRQNULL, cp);
16249992Sbostic xfree((ptr_t) cp);
16349992Sbostic }
16449992Sbostic p1 = freenod(p1, redid ? p2 : p1->next);
16549992Sbostic if (alout.next != &alout) {
16649992Sbostic p1->next->prev = alout.prev->prev;
16749992Sbostic alout.prev->prev->next = p1->next;
16849992Sbostic alout.next->prev = p1;
16949992Sbostic p1->next = alout.next;
17049992Sbostic xfree((ptr_t) alout.prev->word);
17149992Sbostic xfree((ptr_t) (alout.prev));
17249992Sbostic }
17349992Sbostic reset(); /* throw! */
1741301Sbill }
1751301Sbill
17649992Sbostic static struct wordent *
freenod(p1,p2)1771301Sbill freenod(p1, p2)
17849992Sbostic register struct wordent *p1, *p2;
1791301Sbill {
18049992Sbostic register struct wordent *retp = p1->prev;
1811301Sbill
18249992Sbostic while (p1 != p2) {
18349992Sbostic xfree((ptr_t) p1->word);
18449992Sbostic p1 = p1->next;
18549992Sbostic xfree((ptr_t) (p1->prev));
18649992Sbostic }
18749992Sbostic retp->next = p2;
18849992Sbostic p2->prev = retp;
18949992Sbostic return (retp);
1901301Sbill }
1911301Sbill
1921301Sbill #define PHERE 1
1931301Sbill #define PIN 2
1941301Sbill #define POUT 4
19550439Schristos #define PERR 8
1961301Sbill
1971301Sbill /*
1981301Sbill * syntax
1991301Sbill * empty
2001301Sbill * syn0
2011301Sbill */
2021301Sbill struct command *
syntax(p1,p2,flags)2031301Sbill syntax(p1, p2, flags)
20449992Sbostic register struct wordent *p1, *p2;
20549992Sbostic int flags;
2061301Sbill {
2071301Sbill
20849992Sbostic while (p1 != p2)
20949992Sbostic if (any(";&\n", p1->word[0]))
21049992Sbostic p1 = p1->next;
21149992Sbostic else
21249992Sbostic return (syn0(p1, p2, flags));
21349992Sbostic return (0);
2141301Sbill }
2151301Sbill
2161301Sbill /*
2171301Sbill * syn0
2181301Sbill * syn1
2191301Sbill * syn1 & syntax
2201301Sbill */
22149992Sbostic static struct command *
syn0(p1,p2,flags)2221301Sbill syn0(p1, p2, flags)
22349992Sbostic struct wordent *p1, *p2;
22449992Sbostic int flags;
2251301Sbill {
22649992Sbostic register struct wordent *p;
22749992Sbostic register struct command *t, *t1;
22849992Sbostic int l;
2291301Sbill
23049992Sbostic l = 0;
23149992Sbostic for (p = p1; p != p2; p = p->next)
23249992Sbostic switch (p->word[0]) {
2331301Sbill
23449992Sbostic case '(':
23549992Sbostic l++;
23649992Sbostic continue;
2371301Sbill
23849992Sbostic case ')':
23949992Sbostic l--;
24049992Sbostic if (l < 0)
24149992Sbostic seterror(ERR_TOOMANYRP);
24249992Sbostic continue;
2431301Sbill
24449992Sbostic case '|':
24549992Sbostic if (p->word[1] == '|')
24649992Sbostic continue;
24749992Sbostic /* fall into ... */
2481301Sbill
24949992Sbostic case '>':
25049992Sbostic if (p->next != p2 && eq(p->next->word, STRand))
25149992Sbostic p = p->next;
25249992Sbostic continue;
2531301Sbill
25449992Sbostic case '&':
25549992Sbostic if (l != 0)
25649992Sbostic break;
25749992Sbostic if (p->word[1] == '&')
25849992Sbostic continue;
25949992Sbostic t1 = syn1(p1, p, flags);
26049992Sbostic if (t1->t_dtyp == NODE_LIST ||
26149992Sbostic t1->t_dtyp == NODE_AND ||
26249992Sbostic t1->t_dtyp == NODE_OR) {
26349992Sbostic t = (struct command *) xcalloc(1, sizeof(*t));
26449992Sbostic t->t_dtyp = NODE_PAREN;
26549992Sbostic t->t_dflg = F_AMPERSAND | F_NOINTERRUPT;
26649992Sbostic t->t_dspr = t1;
26749992Sbostic t1 = t;
26849992Sbostic }
26949992Sbostic else
27049992Sbostic t1->t_dflg |= F_AMPERSAND | F_NOINTERRUPT;
27149992Sbostic t = (struct command *) xcalloc(1, sizeof(*t));
27249992Sbostic t->t_dtyp = NODE_LIST;
27349992Sbostic t->t_dflg = 0;
27449992Sbostic t->t_dcar = t1;
27549992Sbostic t->t_dcdr = syntax(p, p2, flags);
27649992Sbostic return (t);
27749992Sbostic }
27849992Sbostic if (l == 0)
27949992Sbostic return (syn1(p1, p2, flags));
28049992Sbostic seterror(ERR_TOOMANYLP);
28149992Sbostic return (0);
2821301Sbill }
2831301Sbill
2841301Sbill /*
2851301Sbill * syn1
2861301Sbill * syn1a
2871301Sbill * syn1a ; syntax
2881301Sbill */
28949992Sbostic static struct command *
syn1(p1,p2,flags)2901301Sbill syn1(p1, p2, flags)
29149992Sbostic struct wordent *p1, *p2;
29249992Sbostic int flags;
2931301Sbill {
29449992Sbostic register struct wordent *p;
29549992Sbostic register struct command *t;
29649992Sbostic int l;
2971301Sbill
29849992Sbostic l = 0;
29949992Sbostic for (p = p1; p != p2; p = p->next)
30049992Sbostic switch (p->word[0]) {
3011301Sbill
30249992Sbostic case '(':
30349992Sbostic l++;
30449992Sbostic continue;
3051301Sbill
30649992Sbostic case ')':
30749992Sbostic l--;
30849992Sbostic continue;
3091301Sbill
31049992Sbostic case ';':
31149992Sbostic case '\n':
31249992Sbostic if (l != 0)
31349992Sbostic break;
31449992Sbostic t = (struct command *) xcalloc(1, sizeof(*t));
31549992Sbostic t->t_dtyp = NODE_LIST;
31649992Sbostic t->t_dcar = syn1a(p1, p, flags);
31749992Sbostic t->t_dcdr = syntax(p->next, p2, flags);
31849992Sbostic if (t->t_dcdr == 0)
31949992Sbostic t->t_dcdr = t->t_dcar, t->t_dcar = 0;
32049992Sbostic return (t);
32149992Sbostic }
32249992Sbostic return (syn1a(p1, p2, flags));
3231301Sbill }
3241301Sbill
3251301Sbill /*
3261301Sbill * syn1a
3271301Sbill * syn1b
3281301Sbill * syn1b || syn1a
3291301Sbill */
33049992Sbostic static struct command *
syn1a(p1,p2,flags)3311301Sbill syn1a(p1, p2, flags)
33249992Sbostic struct wordent *p1, *p2;
33349992Sbostic int flags;
3341301Sbill {
33549992Sbostic register struct wordent *p;
33649992Sbostic register struct command *t;
33749992Sbostic register int l = 0;
3381301Sbill
33949992Sbostic for (p = p1; p != p2; p = p->next)
34049992Sbostic switch (p->word[0]) {
3411301Sbill
34249992Sbostic case '(':
34349992Sbostic l++;
34449992Sbostic continue;
3451301Sbill
34649992Sbostic case ')':
34749992Sbostic l--;
34849992Sbostic continue;
3491301Sbill
35049992Sbostic case '|':
35149992Sbostic if (p->word[1] != '|')
35249992Sbostic continue;
35349992Sbostic if (l == 0) {
35449992Sbostic t = (struct command *) xcalloc(1, sizeof(*t));
35549992Sbostic t->t_dtyp = NODE_OR;
35649992Sbostic t->t_dcar = syn1b(p1, p, flags);
35749992Sbostic t->t_dcdr = syn1a(p->next, p2, flags);
35849992Sbostic t->t_dflg = 0;
35949992Sbostic return (t);
36049992Sbostic }
36149992Sbostic continue;
36249992Sbostic }
36349992Sbostic return (syn1b(p1, p2, flags));
3641301Sbill }
3651301Sbill
3661301Sbill /*
3671301Sbill * syn1b
3681301Sbill * syn2
3691301Sbill * syn2 && syn1b
3701301Sbill */
37149992Sbostic static struct command *
syn1b(p1,p2,flags)3721301Sbill syn1b(p1, p2, flags)
37349992Sbostic struct wordent *p1, *p2;
37449992Sbostic int flags;
3751301Sbill {
37649992Sbostic register struct wordent *p;
37749992Sbostic register struct command *t;
37849992Sbostic register int l = 0;
3791301Sbill
38049992Sbostic for (p = p1; p != p2; p = p->next)
38149992Sbostic switch (p->word[0]) {
3821301Sbill
38349992Sbostic case '(':
38449992Sbostic l++;
38549992Sbostic continue;
3861301Sbill
38749992Sbostic case ')':
38849992Sbostic l--;
38949992Sbostic continue;
3901301Sbill
39149992Sbostic case '&':
39249992Sbostic if (p->word[1] == '&' && l == 0) {
39349992Sbostic t = (struct command *) xcalloc(1, sizeof(*t));
39449992Sbostic t->t_dtyp = NODE_AND;
39549992Sbostic t->t_dcar = syn2(p1, p, flags);
39649992Sbostic t->t_dcdr = syn1b(p->next, p2, flags);
39749992Sbostic t->t_dflg = 0;
39849992Sbostic return (t);
39949992Sbostic }
40049992Sbostic continue;
40149992Sbostic }
40249992Sbostic return (syn2(p1, p2, flags));
4031301Sbill }
4041301Sbill
4051301Sbill /*
4061301Sbill * syn2
4071301Sbill * syn3
4081301Sbill * syn3 | syn2
4091301Sbill * syn3 |& syn2
4101301Sbill */
41149992Sbostic static struct command *
syn2(p1,p2,flags)4121301Sbill syn2(p1, p2, flags)
41349992Sbostic struct wordent *p1, *p2;
41449992Sbostic int flags;
4151301Sbill {
41649992Sbostic register struct wordent *p, *pn;
41749992Sbostic register struct command *t;
41849992Sbostic register int l = 0;
41949992Sbostic int f;
4201301Sbill
42149992Sbostic for (p = p1; p != p2; p = p->next)
42249992Sbostic switch (p->word[0]) {
4231301Sbill
42449992Sbostic case '(':
42549992Sbostic l++;
42649992Sbostic continue;
4271301Sbill
42849992Sbostic case ')':
42949992Sbostic l--;
43049992Sbostic continue;
4311301Sbill
43249992Sbostic case '|':
43349992Sbostic if (l != 0)
43449992Sbostic continue;
43549992Sbostic t = (struct command *) xcalloc(1, sizeof(*t));
43649992Sbostic f = flags | POUT;
43749992Sbostic pn = p->next;
43849992Sbostic if (pn != p2 && pn->word[0] == '&') {
43950439Schristos f |= PERR;
44049992Sbostic t->t_dflg |= F_STDERR;
44149992Sbostic }
44249992Sbostic t->t_dtyp = NODE_PIPE;
44349992Sbostic t->t_dcar = syn3(p1, p, f);
44449992Sbostic if (pn != p2 && pn->word[0] == '&')
44549992Sbostic p = pn;
44649992Sbostic t->t_dcdr = syn2(p->next, p2, flags | PIN);
44749992Sbostic return (t);
44849992Sbostic }
44949992Sbostic return (syn3(p1, p2, flags));
4501301Sbill }
4511301Sbill
45249992Sbostic static char RELPAR[] = {'<', '>', '(', ')', '\0'};
4531301Sbill
4541301Sbill /*
4551301Sbill * syn3
4561301Sbill * ( syn0 ) [ < in ] [ > out ]
4571301Sbill * word word* [ < in ] [ > out ]
4581301Sbill * KEYWORD ( word* ) word* [ < in ] [ > out ]
4591301Sbill *
4601301Sbill * KEYWORD = (@ exit foreach if set switch test while)
4611301Sbill */
46249992Sbostic static struct command *
syn3(p1,p2,flags)4631301Sbill syn3(p1, p2, flags)
46449992Sbostic struct wordent *p1, *p2;
46549992Sbostic int flags;
4661301Sbill {
46749992Sbostic register struct wordent *p;
46849992Sbostic struct wordent *lp, *rp;
46949992Sbostic register struct command *t;
47049992Sbostic register int l;
47149992Sbostic Char **av;
47249992Sbostic int n, c;
47349992Sbostic bool specp = 0;
4741301Sbill
47549992Sbostic if (p1 != p2) {
47649992Sbostic p = p1;
4771301Sbill again:
47849992Sbostic switch (srchx(p->word)) {
4791301Sbill
48049992Sbostic case T_ELSE:
48149992Sbostic p = p->next;
48249992Sbostic if (p != p2)
48349992Sbostic goto again;
48449992Sbostic break;
4851301Sbill
48649992Sbostic case T_EXIT:
48749992Sbostic case T_FOREACH:
48849992Sbostic case T_IF:
48949992Sbostic case T_LET:
49049992Sbostic case T_SET:
49149992Sbostic case T_SWITCH:
49249992Sbostic case T_WHILE:
49349992Sbostic specp = 1;
49449992Sbostic break;
4951301Sbill }
49649992Sbostic }
49749992Sbostic n = 0;
49849992Sbostic l = 0;
49949992Sbostic for (p = p1; p != p2; p = p->next)
50049992Sbostic switch (p->word[0]) {
5011301Sbill
50249992Sbostic case '(':
50349992Sbostic if (specp)
50449992Sbostic n++;
50549992Sbostic l++;
50649992Sbostic continue;
5071301Sbill
50849992Sbostic case ')':
50949992Sbostic if (specp)
51049992Sbostic n++;
51149992Sbostic l--;
51249992Sbostic continue;
5131301Sbill
51449992Sbostic case '>':
51549992Sbostic case '<':
51649992Sbostic if (l != 0) {
51749992Sbostic if (specp)
51849992Sbostic n++;
51949992Sbostic continue;
52049992Sbostic }
52149992Sbostic if (p->next == p2)
52249992Sbostic continue;
52349992Sbostic if (any(RELPAR, p->next->word[0]))
52449992Sbostic continue;
52549992Sbostic n--;
52649992Sbostic continue;
5271301Sbill
52849992Sbostic default:
52949992Sbostic if (!specp && l != 0)
53049992Sbostic continue;
53149992Sbostic n++;
53249992Sbostic continue;
53349992Sbostic }
53449992Sbostic if (n < 0)
5351301Sbill n = 0;
53649992Sbostic t = (struct command *) xcalloc(1, sizeof(*t));
53749992Sbostic av = (Char **) xcalloc((size_t) (n + 1), sizeof(Char **));
53849992Sbostic t->t_dcom = av;
53949992Sbostic n = 0;
54049992Sbostic if (p2->word[0] == ')')
54149992Sbostic t->t_dflg = F_NOFORK;
54249992Sbostic lp = 0;
54349992Sbostic rp = 0;
54449992Sbostic l = 0;
54549992Sbostic for (p = p1; p != p2; p = p->next) {
54649992Sbostic c = p->word[0];
54749992Sbostic switch (c) {
5481301Sbill
54949992Sbostic case '(':
55049992Sbostic if (l == 0) {
55149992Sbostic if (lp != 0 && !specp)
55249992Sbostic seterror(ERR_BADPLP);
55349992Sbostic lp = p->next;
55449992Sbostic }
55549992Sbostic l++;
55649992Sbostic goto savep;
5571301Sbill
55849992Sbostic case ')':
55949992Sbostic l--;
56049992Sbostic if (l == 0)
56149992Sbostic rp = p;
56249992Sbostic goto savep;
5631301Sbill
56449992Sbostic case '>':
56549992Sbostic if (l != 0)
56649992Sbostic goto savep;
56749992Sbostic if (p->word[1] == '>')
56849992Sbostic t->t_dflg |= F_APPEND;
56949992Sbostic if (p->next != p2 && eq(p->next->word, STRand)) {
57049992Sbostic t->t_dflg |= F_STDERR, p = p->next;
57150439Schristos if (flags & (POUT | PERR)) {
57249992Sbostic seterror(ERR_OUTRED);
57349992Sbostic continue;
57449992Sbostic }
57549992Sbostic }
57649992Sbostic if (p->next != p2 && eq(p->next->word, STRbang))
57749992Sbostic t->t_dflg |= F_OVERWRITE, p = p->next;
57849992Sbostic if (p->next == p2) {
57949992Sbostic seterror(ERR_MISRED);
58049992Sbostic continue;
58149992Sbostic }
58249992Sbostic p = p->next;
58349992Sbostic if (any(RELPAR, p->word[0])) {
58449992Sbostic seterror(ERR_MISRED);
58549992Sbostic continue;
58649992Sbostic }
58760237Schristos if ((flags & POUT) && ((flags & PERR) == 0 || t->t_drit))
58849992Sbostic seterror(ERR_OUTRED);
58949992Sbostic else
59049992Sbostic t->t_drit = Strsave(p->word);
59149992Sbostic continue;
5921301Sbill
59349992Sbostic case '<':
59449992Sbostic if (l != 0)
59549992Sbostic goto savep;
59649992Sbostic if (p->word[1] == '<')
59749992Sbostic t->t_dflg |= F_READ;
59849992Sbostic if (p->next == p2) {
59949992Sbostic seterror(ERR_MISRED);
60049992Sbostic continue;
60149992Sbostic }
60249992Sbostic p = p->next;
60349992Sbostic if (any(RELPAR, p->word[0])) {
60449992Sbostic seterror(ERR_MISRED);
60549992Sbostic continue;
60649992Sbostic }
60749992Sbostic if ((flags & PHERE) && (t->t_dflg & F_READ))
60849992Sbostic seterror(ERR_REDPAR);
60949992Sbostic else if ((flags & PIN) || t->t_dlef)
61049992Sbostic seterror(ERR_INRED);
61149992Sbostic else
61249992Sbostic t->t_dlef = Strsave(p->word);
61349992Sbostic continue;
6141301Sbill
61549992Sbostic savep:
61649992Sbostic if (!specp)
61749992Sbostic continue;
61849992Sbostic default:
61949992Sbostic if (l != 0 && !specp)
62049992Sbostic continue;
62149992Sbostic if (seterr == 0)
62249992Sbostic av[n] = Strsave(p->word);
62349992Sbostic n++;
62449992Sbostic continue;
6251301Sbill }
62649992Sbostic }
62749992Sbostic if (lp != 0 && !specp) {
62849992Sbostic if (n != 0)
62949992Sbostic seterror(ERR_BADPLPS);
63049992Sbostic t->t_dtyp = NODE_PAREN;
63149992Sbostic t->t_dspr = syn0(lp, rp, PHERE);
63249992Sbostic }
63349992Sbostic else {
63449992Sbostic if (n == 0)
63549992Sbostic seterror(ERR_NULLCOM);
63649992Sbostic t->t_dtyp = NODE_COMMAND;
63749992Sbostic }
63849992Sbostic return (t);
6391301Sbill }
6401301Sbill
64149992Sbostic void
freesyn(t)6421301Sbill freesyn(t)
64349992Sbostic register struct command *t;
6441301Sbill {
64549992Sbostic register Char **v;
6461301Sbill
64749992Sbostic if (t == 0)
64849992Sbostic return;
64949992Sbostic switch (t->t_dtyp) {
6501301Sbill
65149992Sbostic case NODE_COMMAND:
65249992Sbostic for (v = t->t_dcom; *v; v++)
65349992Sbostic xfree((ptr_t) * v);
65449992Sbostic xfree((ptr_t) (t->t_dcom));
65549992Sbostic xfree((ptr_t) t->t_dlef);
65649992Sbostic xfree((ptr_t) t->t_drit);
65749992Sbostic break;
65849992Sbostic case NODE_PAREN:
65949992Sbostic freesyn(t->t_dspr);
66049992Sbostic xfree((ptr_t) t->t_dlef);
66149992Sbostic xfree((ptr_t) t->t_drit);
66249992Sbostic break;
6631301Sbill
66449992Sbostic case NODE_AND:
66549992Sbostic case NODE_OR:
66649992Sbostic case NODE_PIPE:
66749992Sbostic case NODE_LIST:
66849992Sbostic freesyn(t->t_dcar), freesyn(t->t_dcdr);
66949992Sbostic break;
67049992Sbostic }
67149992Sbostic xfree((ptr_t) t);
6721301Sbill }
673