1232633Smp/* $Header: /p/tcsh/cvsroot/tcsh/sh.parse.c,v 3.19 2011/03/30 16:21:37 christos Exp $ */ 259243Sobrien/* 359243Sobrien * sh.parse.c: Interpret a list of tokens 459243Sobrien */ 559243Sobrien/*- 659243Sobrien * Copyright (c) 1980, 1991 The Regents of the University of California. 759243Sobrien * All rights reserved. 859243Sobrien * 959243Sobrien * Redistribution and use in source and binary forms, with or without 1059243Sobrien * modification, are permitted provided that the following conditions 1159243Sobrien * are met: 1259243Sobrien * 1. Redistributions of source code must retain the above copyright 1359243Sobrien * notice, this list of conditions and the following disclaimer. 1459243Sobrien * 2. Redistributions in binary form must reproduce the above copyright 1559243Sobrien * notice, this list of conditions and the following disclaimer in the 1659243Sobrien * documentation and/or other materials provided with the distribution. 17100616Smp * 3. Neither the name of the University nor the names of its contributors 1859243Sobrien * may be used to endorse or promote products derived from this software 1959243Sobrien * without specific prior written permission. 2059243Sobrien * 2159243Sobrien * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2259243Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2359243Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2459243Sobrien * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2559243Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2659243Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2759243Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2859243Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2959243Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3059243Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3159243Sobrien * SUCH DAMAGE. 3259243Sobrien */ 3359243Sobrien#include "sh.h" 3459243Sobrien 35232633SmpRCSID("$tcsh: sh.parse.c,v 3.19 2011/03/30 16:21:37 christos Exp $") 3659243Sobrien 3759243Sobrien/* 3859243Sobrien * C shell 3959243Sobrien */ 40167465Smpstatic int asyntax (struct wordent *, struct wordent *); 41167465Smpstatic int asyn0 (struct wordent *, struct wordent *); 42167465Smpstatic int asyn3 (struct wordent *, struct wordent *); 43167465Smpstatic struct wordent *freenod (struct wordent *, struct wordent *); 44167465Smpstatic struct command *syn0 (const struct wordent *, const struct wordent *, int); 45167465Smpstatic struct command *syn1 (const struct wordent *, const struct wordent *, int); 46167465Smpstatic struct command *syn1a (const struct wordent *, const struct wordent *, int); 47167465Smpstatic struct command *syn1b (const struct wordent *, const struct wordent *, int); 48167465Smpstatic struct command *syn2 (const struct wordent *, const struct wordent *, int); 49167465Smpstatic struct command *syn3 (const struct wordent *, const struct wordent *, int); 5059243Sobrien 5159243Sobrien#define ALEFT 51 /* max of 50 alias expansions */ 5259243Sobrien#define HLEFT 11 /* max of 10 history expansions */ 5359243Sobrien/* 5459243Sobrien * Perform aliasing on the word list lexp 5559243Sobrien * Do a (very rudimentary) parse to separate into commands. 5659243Sobrien * If word 0 of a command has an alias, do it. 5759243Sobrien * Repeat a maximum of 50 times. 5859243Sobrien */ 5959243Sobrienextern int hleft; 6059243Sobrienvoid 61167465Smpalias(struct wordent *lexp) 6259243Sobrien{ 63167465Smp int aleft; 6459243Sobrien 6559243Sobrien aleft = ALEFT; 6659243Sobrien hleft = HLEFT; 67167465Smp do { 68167465Smp if (--aleft == 0) 69167465Smp stderror(ERR_ALIASLOOP); 70167465Smp } while (asyntax(lexp->next, lexp) != 0); 7159243Sobrien} 7259243Sobrien 73167465Smpstatic int 74167465Smpasyntax(struct wordent *p1, struct wordent *p2) 7559243Sobrien{ 76167465Smp while (p1 != p2) { 77167465Smp if (!any(";&\n", p1->word[0])) 78167465Smp return asyn0(p1, p2); 79167465Smp p1 = p1->next; 80167465Smp } 81167465Smp return 0; 8259243Sobrien} 8359243Sobrien 84167465Smpstatic int 85167465Smpasyn0(struct wordent *p1, struct wordent *p2) 8659243Sobrien{ 87145479Smp struct wordent *p; 88145479Smp int l = 0; 8959243Sobrien 9059243Sobrien for (p = p1; p != p2; p = p->next) 9159243Sobrien switch (p->word[0]) { 9259243Sobrien 9359243Sobrien case '(': 9459243Sobrien l++; 9559243Sobrien continue; 9659243Sobrien 9759243Sobrien case ')': 9859243Sobrien l--; 9959243Sobrien if (l < 0) 10059243Sobrien stderror(ERR_TOOMANYRP); 10159243Sobrien continue; 10259243Sobrien 10359243Sobrien case '>': 10459243Sobrien if (p->next != p2 && eq(p->next->word, STRand)) 10559243Sobrien p = p->next; 10659243Sobrien continue; 10759243Sobrien 10859243Sobrien case '&': 10959243Sobrien case '|': 11059243Sobrien case ';': 11159243Sobrien case '\n': 11259243Sobrien if (l != 0) 11359243Sobrien continue; 114167465Smp if (asyn3(p1, p) != 0) 115167465Smp return 1; 116167465Smp return asyntax(p->next, p2); 11759243Sobrien 11859243Sobrien default: 11959243Sobrien break; 12059243Sobrien } 12159243Sobrien if (l == 0) 122167465Smp return asyn3(p1, p2); 123167465Smp return 0; 12459243Sobrien} 12559243Sobrien 12659243Sobrienstatic void 127167465Smpalvec_cleanup(void *dummy) 12859243Sobrien{ 129167465Smp USE(dummy); 130167465Smp alhistp = NULL; 131167465Smp alhistt = NULL; 132167465Smp alvec = NULL; 133167465Smp} 134167465Smp 135167465Smpstatic int 136167465Smpasyn3(struct wordent *p1, struct wordent *p2) 137167465Smp{ 138145479Smp struct varent *ap; 13959243Sobrien struct wordent alout; 140145479Smp int redid; 14159243Sobrien 14259243Sobrien if (p1 == p2) 143167465Smp return 0; 14459243Sobrien if (p1->word[0] == '(') { 14559243Sobrien for (p2 = p2->prev; p2->word[0] != ')'; p2 = p2->prev) 14659243Sobrien if (p2 == p1) 147167465Smp return 0; 14859243Sobrien if (p2 == p1->next) 149167465Smp return 0; 150167465Smp return asyn0(p1->next, p2); 15159243Sobrien } 15259243Sobrien ap = adrof1(p1->word, &aliases); 15359243Sobrien if (ap == 0) 154167465Smp return 0; 15559243Sobrien alhistp = p1->prev; 15659243Sobrien alhistt = p2; 15759243Sobrien alvec = ap->vec; 158167465Smp cleanup_push(&alvec, alvec_cleanup); 15959243Sobrien redid = lex(&alout); 160167465Smp cleanup_until(&alvec); 16159243Sobrien if (seterr) { 16259243Sobrien freelex(&alout); 16359243Sobrien stderror(ERR_OLD); 16459243Sobrien } 16559243Sobrien if (p1->word[0] && eq(p1->word, alout.next->word)) { 16659243Sobrien Char *cp = alout.next->word; 16759243Sobrien 16859243Sobrien alout.next->word = Strspl(STRQNULL, cp); 169167465Smp xfree(cp); 17059243Sobrien } 17159243Sobrien p1 = freenod(p1, redid ? p2 : p1->next); 17259243Sobrien if (alout.next != &alout) { 17359243Sobrien p1->next->prev = alout.prev->prev; 17459243Sobrien alout.prev->prev->next = p1->next; 17559243Sobrien alout.next->prev = p1; 17659243Sobrien p1->next = alout.next; 177167465Smp xfree(alout.prev->word); 178167465Smp xfree(alout.prev); 17959243Sobrien } 180167465Smp return 1; 18159243Sobrien} 18259243Sobrien 18359243Sobrienstatic struct wordent * 184167465Smpfreenod(struct wordent *p1, struct wordent *p2) 18559243Sobrien{ 186145479Smp struct wordent *retp = p1->prev; 18759243Sobrien 18859243Sobrien while (p1 != p2) { 189167465Smp xfree(p1->word); 19059243Sobrien p1 = p1->next; 191167465Smp xfree(p1->prev); 19259243Sobrien } 19359243Sobrien retp->next = p2; 19459243Sobrien p2->prev = retp; 19559243Sobrien return (retp); 19659243Sobrien} 19759243Sobrien 19859243Sobrien#define P_HERE 1 19959243Sobrien#define P_IN 2 20059243Sobrien#define P_OUT 4 20159243Sobrien#define P_DIAG 8 20259243Sobrien 20359243Sobrien/* 20459243Sobrien * syntax 20559243Sobrien * empty 20659243Sobrien * syn0 20759243Sobrien */ 20859243Sobrienstruct command * 209167465Smpsyntax(const struct wordent *p1, const struct wordent *p2, int flags) 21059243Sobrien{ 21159243Sobrien 21259243Sobrien while (p1 != p2) 21359243Sobrien if (any(";&\n", p1->word[0])) 21459243Sobrien p1 = p1->next; 21559243Sobrien else 21659243Sobrien return (syn0(p1, p2, flags)); 21759243Sobrien return (0); 21859243Sobrien} 21959243Sobrien 22059243Sobrien/* 22159243Sobrien * syn0 22259243Sobrien * syn1 22359243Sobrien * syn1 & syntax 22459243Sobrien */ 22559243Sobrienstatic struct command * 226167465Smpsyn0(const struct wordent *p1, const struct wordent *p2, int flags) 22759243Sobrien{ 228167465Smp const struct wordent *p; 229145479Smp struct command *t, *t1; 23059243Sobrien int l; 23159243Sobrien 23259243Sobrien l = 0; 23359243Sobrien for (p = p1; p != p2; p = p->next) 23459243Sobrien switch (p->word[0]) { 23559243Sobrien 23659243Sobrien case '(': 23759243Sobrien l++; 23859243Sobrien continue; 23959243Sobrien 24059243Sobrien case ')': 24159243Sobrien l--; 24259243Sobrien if (l < 0) 24359243Sobrien seterror(ERR_TOOMANYRP); 24459243Sobrien continue; 24559243Sobrien 24659243Sobrien case '|': 24759243Sobrien if (p->word[1] == '|') 24859243Sobrien continue; 24959243Sobrien /*FALLTHROUGH*/ 25059243Sobrien 25159243Sobrien case '>': 25259243Sobrien if (p->next != p2 && eq(p->next->word, STRand)) 25359243Sobrien p = p->next; 25459243Sobrien continue; 25559243Sobrien 25659243Sobrien case '&': 25759243Sobrien if (l != 0) 25859243Sobrien break; 25959243Sobrien if (p->word[1] == '&') 26059243Sobrien continue; 26159243Sobrien t1 = syn1(p1, p, flags); 26259243Sobrien if (t1->t_dtyp == NODE_LIST || 26359243Sobrien t1->t_dtyp == NODE_AND || 26459243Sobrien t1->t_dtyp == NODE_OR) { 265167465Smp t = xcalloc(1, sizeof(*t)); 26659243Sobrien t->t_dtyp = NODE_PAREN; 26759243Sobrien t->t_dflg = F_AMPERSAND | F_NOINTERRUPT; 26859243Sobrien t->t_dspr = t1; 26959243Sobrien t1 = t; 27059243Sobrien } 27159243Sobrien else 27259243Sobrien t1->t_dflg |= F_AMPERSAND | F_NOINTERRUPT; 273167465Smp t = xcalloc(1, sizeof(*t)); 27459243Sobrien t->t_dtyp = NODE_LIST; 27559243Sobrien t->t_dflg = 0; 27659243Sobrien t->t_dcar = t1; 27759243Sobrien t->t_dcdr = syntax(p, p2, flags); 27859243Sobrien return (t); 27959243Sobrien default: 28059243Sobrien break; 28159243Sobrien } 28259243Sobrien if (l == 0) 28359243Sobrien return (syn1(p1, p2, flags)); 28459243Sobrien seterror(ERR_TOOMANYLP); 28559243Sobrien return (0); 28659243Sobrien} 28759243Sobrien 28859243Sobrien/* 28959243Sobrien * syn1 29059243Sobrien * syn1a 29159243Sobrien * syn1a ; syntax 29259243Sobrien */ 29359243Sobrienstatic struct command * 294167465Smpsyn1(const struct wordent *p1, const struct wordent *p2, int flags) 29559243Sobrien{ 296167465Smp const struct wordent *p; 297145479Smp struct command *t; 29859243Sobrien int l; 29959243Sobrien 30059243Sobrien l = 0; 30159243Sobrien for (p = p1; p != p2; p = p->next) 30259243Sobrien switch (p->word[0]) { 30359243Sobrien 30459243Sobrien case '(': 30559243Sobrien l++; 30659243Sobrien continue; 30759243Sobrien 30859243Sobrien case ')': 30959243Sobrien l--; 31059243Sobrien continue; 31159243Sobrien 31259243Sobrien case ';': 31359243Sobrien case '\n': 31459243Sobrien if (l != 0) 31559243Sobrien break; 316167465Smp t = xcalloc(1, sizeof(*t)); 31759243Sobrien t->t_dtyp = NODE_LIST; 31859243Sobrien t->t_dcar = syn1a(p1, p, flags); 31959243Sobrien t->t_dcdr = syntax(p->next, p2, flags); 32059243Sobrien if (t->t_dcdr == 0) 32159243Sobrien t->t_dcdr = t->t_dcar, t->t_dcar = 0; 32259243Sobrien return (t); 32359243Sobrien 32459243Sobrien default: 32559243Sobrien break; 32659243Sobrien } 32759243Sobrien return (syn1a(p1, p2, flags)); 32859243Sobrien} 32959243Sobrien 33059243Sobrien/* 33159243Sobrien * syn1a 33259243Sobrien * syn1b 33359243Sobrien * syn1b || syn1a 33459243Sobrien */ 33559243Sobrienstatic struct command * 336167465Smpsyn1a(const struct wordent *p1, const struct wordent *p2, int flags) 33759243Sobrien{ 338167465Smp const struct wordent *p; 339145479Smp struct command *t; 340145479Smp int l = 0; 34159243Sobrien 34259243Sobrien for (p = p1; p != p2; p = p->next) 34359243Sobrien switch (p->word[0]) { 34459243Sobrien 34559243Sobrien case '(': 34659243Sobrien l++; 34759243Sobrien continue; 34859243Sobrien 34959243Sobrien case ')': 35059243Sobrien l--; 35159243Sobrien continue; 35259243Sobrien 35359243Sobrien case '|': 35459243Sobrien if (p->word[1] != '|') 35559243Sobrien continue; 35659243Sobrien if (l == 0) { 357167465Smp t = xcalloc(1, sizeof(*t)); 35859243Sobrien t->t_dtyp = NODE_OR; 35959243Sobrien t->t_dcar = syn1b(p1, p, flags); 36059243Sobrien t->t_dcdr = syn1a(p->next, p2, flags); 36159243Sobrien t->t_dflg = 0; 36259243Sobrien return (t); 36359243Sobrien } 36459243Sobrien continue; 36559243Sobrien 36659243Sobrien default: 36759243Sobrien break; 36859243Sobrien } 36959243Sobrien return (syn1b(p1, p2, flags)); 37059243Sobrien} 37159243Sobrien 37259243Sobrien/* 37359243Sobrien * syn1b 37459243Sobrien * syn2 37559243Sobrien * syn2 && syn1b 37659243Sobrien */ 37759243Sobrienstatic struct command * 378167465Smpsyn1b(const struct wordent *p1, const struct wordent *p2, int flags) 37959243Sobrien{ 380167465Smp const struct wordent *p; 381145479Smp struct command *t; 382145479Smp int l = 0; 38359243Sobrien 38459243Sobrien for (p = p1; p != p2; p = p->next) 38559243Sobrien switch (p->word[0]) { 38659243Sobrien 38759243Sobrien case '(': 38859243Sobrien l++; 38959243Sobrien continue; 39059243Sobrien 39159243Sobrien case ')': 39259243Sobrien l--; 39359243Sobrien continue; 39459243Sobrien 39559243Sobrien case '&': 39659243Sobrien if (p->word[1] == '&' && l == 0) { 397167465Smp t = xcalloc(1, sizeof(*t)); 39859243Sobrien t->t_dtyp = NODE_AND; 39959243Sobrien t->t_dcar = syn2(p1, p, flags); 40059243Sobrien t->t_dcdr = syn1b(p->next, p2, flags); 40159243Sobrien t->t_dflg = 0; 40259243Sobrien return (t); 40359243Sobrien } 40459243Sobrien continue; 40559243Sobrien 40659243Sobrien default: 40759243Sobrien break; 40859243Sobrien } 40959243Sobrien return (syn2(p1, p2, flags)); 41059243Sobrien} 41159243Sobrien 41259243Sobrien/* 41359243Sobrien * syn2 41459243Sobrien * syn3 41559243Sobrien * syn3 | syn2 41659243Sobrien * syn3 |& syn2 41759243Sobrien */ 41859243Sobrienstatic struct command * 419167465Smpsyn2(const struct wordent *p1, const struct wordent *p2, int flags) 42059243Sobrien{ 421167465Smp const struct wordent *p, *pn; 422145479Smp struct command *t; 423145479Smp int l = 0; 42459243Sobrien int f; 42559243Sobrien 42659243Sobrien for (p = p1; p != p2; p = p->next) 42759243Sobrien switch (p->word[0]) { 42859243Sobrien 42959243Sobrien case '(': 43059243Sobrien l++; 43159243Sobrien continue; 43259243Sobrien 43359243Sobrien case ')': 43459243Sobrien l--; 43559243Sobrien continue; 43659243Sobrien 43759243Sobrien case '|': 43859243Sobrien if (l != 0) 43959243Sobrien continue; 440167465Smp t = xcalloc(1, sizeof(*t)); 44159243Sobrien f = flags | P_OUT; 44259243Sobrien pn = p->next; 44359243Sobrien if (pn != p2 && pn->word[0] == '&') { 44459243Sobrien f |= P_DIAG; 44559243Sobrien t->t_dflg |= F_STDERR; 44659243Sobrien } 44759243Sobrien t->t_dtyp = NODE_PIPE; 44859243Sobrien t->t_dcar = syn3(p1, p, f); 44959243Sobrien if (pn != p2 && pn->word[0] == '&') 45059243Sobrien p = pn; 45159243Sobrien t->t_dcdr = syn2(p->next, p2, flags | P_IN); 45259243Sobrien return (t); 45359243Sobrien 45459243Sobrien default: 45559243Sobrien break; 45659243Sobrien } 45759243Sobrien return (syn3(p1, p2, flags)); 45859243Sobrien} 45959243Sobrien 460167465Smpstatic const char RELPAR[] = {'<', '>', '(', ')', '\0'}; 46159243Sobrien 46259243Sobrien/* 46359243Sobrien * syn3 46459243Sobrien * ( syn0 ) [ < in ] [ > out ] 46559243Sobrien * word word* [ < in ] [ > out ] 46659243Sobrien * KEYWORD ( word* ) word* [ < in ] [ > out ] 46759243Sobrien * 46859243Sobrien * KEYWORD = (@ exit foreach if set switch test while) 46959243Sobrien */ 47059243Sobrienstatic struct command * 471167465Smpsyn3(const struct wordent *p1, const struct wordent *p2, int flags) 47259243Sobrien{ 473167465Smp const struct wordent *p; 474167465Smp const struct wordent *lp, *rp; 475145479Smp struct command *t; 476145479Smp int l; 47759243Sobrien Char **av; 47859243Sobrien int n, c; 479145479Smp int specp = 0; 48059243Sobrien 48159243Sobrien if (p1 != p2) { 48259243Sobrien p = p1; 48359243Sobrienagain: 48459243Sobrien switch (srchx(p->word)) { 48559243Sobrien 48659243Sobrien case TC_ELSE: 48759243Sobrien p = p->next; 48859243Sobrien if (p != p2) 48959243Sobrien goto again; 49059243Sobrien break; 49159243Sobrien 49259243Sobrien case TC_EXIT: 49359243Sobrien case TC_FOREACH: 49459243Sobrien case TC_IF: 49559243Sobrien case TC_LET: 49659243Sobrien case TC_SET: 49759243Sobrien case TC_SWITCH: 49859243Sobrien case TC_WHILE: 49959243Sobrien specp = 1; 50059243Sobrien break; 50159243Sobrien default: 50259243Sobrien break; 50359243Sobrien } 50459243Sobrien } 50559243Sobrien n = 0; 50659243Sobrien l = 0; 50759243Sobrien for (p = p1; p != p2; p = p->next) 50859243Sobrien switch (p->word[0]) { 50959243Sobrien 51059243Sobrien case '(': 51159243Sobrien if (specp) 51259243Sobrien n++; 51359243Sobrien l++; 51459243Sobrien continue; 51559243Sobrien 51659243Sobrien case ')': 51759243Sobrien if (specp) 51859243Sobrien n++; 51959243Sobrien l--; 52059243Sobrien continue; 52159243Sobrien 52259243Sobrien case '>': 52359243Sobrien case '<': 52459243Sobrien if (l != 0) { 52559243Sobrien if (specp) 52659243Sobrien n++; 52759243Sobrien continue; 52859243Sobrien } 52959243Sobrien if (p->next == p2) 53059243Sobrien continue; 53159243Sobrien if (any(RELPAR, p->next->word[0])) 53259243Sobrien continue; 53359243Sobrien n--; 53459243Sobrien continue; 53559243Sobrien 53659243Sobrien default: 53759243Sobrien if (!specp && l != 0) 53859243Sobrien continue; 53959243Sobrien n++; 54059243Sobrien continue; 54159243Sobrien } 54259243Sobrien if (n < 0) 54359243Sobrien n = 0; 544167465Smp t = xcalloc(1, sizeof(*t)); 545167465Smp av = xcalloc(n + 1, sizeof(Char **)); 54659243Sobrien t->t_dcom = av; 54759243Sobrien n = 0; 54859243Sobrien if (p2->word[0] == ')') 54959243Sobrien t->t_dflg = F_NOFORK; 55059243Sobrien lp = 0; 55159243Sobrien rp = 0; 55259243Sobrien l = 0; 55359243Sobrien for (p = p1; p != p2; p = p->next) { 55459243Sobrien c = p->word[0]; 55559243Sobrien switch (c) { 55659243Sobrien 55759243Sobrien case '(': 55859243Sobrien if (l == 0) { 55959243Sobrien if (lp != 0 && !specp) 56059243Sobrien seterror(ERR_BADPLP); 56159243Sobrien lp = p->next; 56259243Sobrien } 56359243Sobrien l++; 56459243Sobrien goto savep; 56559243Sobrien 56659243Sobrien case ')': 56759243Sobrien l--; 56859243Sobrien if (l == 0) 56959243Sobrien rp = p; 57059243Sobrien goto savep; 57159243Sobrien 57259243Sobrien case '>': 57359243Sobrien if (l != 0) 57459243Sobrien goto savep; 57559243Sobrien if (p->word[1] == '>') 57659243Sobrien t->t_dflg |= F_APPEND; 57759243Sobrien if (p->next != p2 && eq(p->next->word, STRand)) { 57859243Sobrien t->t_dflg |= F_STDERR, p = p->next; 57959243Sobrien if (flags & (P_OUT | P_DIAG)) { 58059243Sobrien seterror(ERR_OUTRED); 58159243Sobrien continue; 58259243Sobrien } 58359243Sobrien } 58459243Sobrien if (p->next != p2 && eq(p->next->word, STRbang)) 58559243Sobrien t->t_dflg |= F_OVERWRITE, p = p->next; 58659243Sobrien if (p->next == p2) { 58759243Sobrien seterror(ERR_MISRED); 58859243Sobrien continue; 58959243Sobrien } 59059243Sobrien p = p->next; 59159243Sobrien if (any(RELPAR, p->word[0])) { 59259243Sobrien seterror(ERR_MISRED); 59359243Sobrien continue; 59459243Sobrien } 59559243Sobrien if (((flags & P_OUT) && (flags & P_DIAG) == 0) || t->t_drit) 59659243Sobrien seterror(ERR_OUTRED); 59759243Sobrien else 59859243Sobrien t->t_drit = Strsave(p->word); 59959243Sobrien continue; 60059243Sobrien 60159243Sobrien case '<': 60259243Sobrien if (l != 0) 60359243Sobrien goto savep; 60459243Sobrien if (p->word[1] == '<') 60559243Sobrien t->t_dflg |= F_READ; 60659243Sobrien if (p->next == p2) { 60759243Sobrien seterror(ERR_MISRED); 60859243Sobrien continue; 60959243Sobrien } 61059243Sobrien p = p->next; 61159243Sobrien if (any(RELPAR, p->word[0])) { 61259243Sobrien seterror(ERR_MISRED); 61359243Sobrien continue; 61459243Sobrien } 61559243Sobrien if ((flags & P_HERE) && (t->t_dflg & F_READ)) 61659243Sobrien seterror(ERR_REDPAR); 61759243Sobrien else if ((flags & P_IN) || t->t_dlef) 61859243Sobrien seterror(ERR_INRED); 61959243Sobrien else 62059243Sobrien t->t_dlef = Strsave(p->word); 62159243Sobrien continue; 62259243Sobrien 62359243Sobrien savep: 62459243Sobrien if (!specp) 62559243Sobrien continue; 62659243Sobrien default: 62759243Sobrien if (l != 0 && !specp) 62859243Sobrien continue; 62959243Sobrien if (seterr == 0) 63059243Sobrien av[n] = Strsave(p->word); 63159243Sobrien n++; 63259243Sobrien continue; 63359243Sobrien } 63459243Sobrien } 63559243Sobrien if (lp != 0 && !specp) { 63659243Sobrien if (n != 0) 63759243Sobrien seterror(ERR_BADPLPS); 63859243Sobrien t->t_dtyp = NODE_PAREN; 63959243Sobrien t->t_dspr = syn0(lp, rp, P_HERE); 64059243Sobrien } 64159243Sobrien else { 64259243Sobrien if (n == 0) 64359243Sobrien seterror(ERR_NULLCOM); 64459243Sobrien t->t_dtyp = NODE_COMMAND; 64559243Sobrien } 64659243Sobrien return (t); 64759243Sobrien} 64859243Sobrien 64959243Sobrienvoid 650167465Smpfreesyn(struct command *t) 65159243Sobrien{ 652145479Smp Char **v; 65359243Sobrien 65459243Sobrien if (t == 0) 65559243Sobrien return; 65659243Sobrien switch (t->t_dtyp) { 65759243Sobrien 65859243Sobrien case NODE_COMMAND: 65959243Sobrien for (v = t->t_dcom; *v; v++) 660167465Smp xfree(*v); 661167465Smp xfree(t->t_dcom); 662167465Smp xfree(t->t_dlef); 663167465Smp xfree(t->t_drit); 66459243Sobrien break; 66559243Sobrien case NODE_PAREN: 66659243Sobrien freesyn(t->t_dspr); 667167465Smp xfree(t->t_dlef); 668167465Smp xfree(t->t_drit); 66959243Sobrien break; 67059243Sobrien 67159243Sobrien case NODE_AND: 67259243Sobrien case NODE_OR: 67359243Sobrien case NODE_PIPE: 67459243Sobrien case NODE_LIST: 67559243Sobrien freesyn(t->t_dcar), freesyn(t->t_dcdr); 67659243Sobrien break; 67759243Sobrien default: 67859243Sobrien break; 67959243Sobrien } 680232633Smp#ifdef DEBUG 681232633Smp memset(t, 0, sizeof(*t)); 682232633Smp#endif 683167465Smp xfree(t); 68459243Sobrien} 685167465Smp 686167465Smpvoid 687167465Smpsyntax_cleanup(void *xt) 688167465Smp{ 689167465Smp struct command *t; 690167465Smp 691167465Smp t = xt; 692167465Smp freesyn(t); 693167465Smp} 694