147823Sbostic /*- 247823Sbostic * Copyright (c) 1980, 1991 The Regents of the University of California. 347823Sbostic * All rights reserved. 447823Sbostic * 547823Sbostic * %sccs.include.redist.c% 621939Sdist */ 721939Sdist 817511Sedward #ifndef lint 9*50439Schristos static char sccsid[] = "@(#)parse.c 5.12 (Berkeley) 07/19/91"; 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 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 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 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 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 * 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 195*50439Schristos #define PERR 8 1961301Sbill 1971301Sbill /* 1981301Sbill * syntax 1991301Sbill * empty 2001301Sbill * syn0 2011301Sbill */ 2021301Sbill struct command * 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 * 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 * 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 * 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 * 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 * 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] == '&') { 439*50439Schristos 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 * 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; 571*50439Schristos 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 } 587*50439Schristos 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 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