sh.parse.c revision 100616
1100616Smp/* $Header: /src/pub/tcsh/sh.parse.c,v 3.11 2002/03/08 17:36:46 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 35100616SmpRCSID("$Id: sh.parse.c,v 3.11 2002/03/08 17:36:46 christos Exp $") 3659243Sobrien 3759243Sobrien/* 3859243Sobrien * C shell 3959243Sobrien */ 4059243Sobrienstatic void asyntax __P((struct wordent *, struct wordent *)); 4159243Sobrienstatic void asyn0 __P((struct wordent *, struct wordent *)); 4259243Sobrienstatic void asyn3 __P((struct wordent *, struct wordent *)); 4359243Sobrienstatic struct wordent *freenod __P((struct wordent *, struct wordent *)); 4459243Sobrienstatic struct command *syn0 __P((struct wordent *, struct wordent *, int)); 4559243Sobrienstatic struct command *syn1 __P((struct wordent *, struct wordent *, int)); 4659243Sobrienstatic struct command *syn1a __P((struct wordent *, struct wordent *, int)); 4759243Sobrienstatic struct command *syn1b __P((struct wordent *, struct wordent *, int)); 4859243Sobrienstatic struct command *syn2 __P((struct wordent *, struct wordent *, int)); 4959243Sobrienstatic struct command *syn3 __P((struct wordent *, 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 */ 5959243Sobrienstatic int aleft; 6059243Sobrienextern int hleft; 6159243Sobrienvoid 6259243Sobrienalias(lexp) 6359243Sobrien register struct wordent *lexp; 6459243Sobrien{ 6559243Sobrien jmp_buf_t osetexit; 6659243Sobrien 6759243Sobrien aleft = ALEFT; 6859243Sobrien hleft = HLEFT; 6959243Sobrien getexit(osetexit); 7059243Sobrien (void) setexit(); 7159243Sobrien if (haderr) { 7259243Sobrien resexit(osetexit); 7359243Sobrien reset(); 7459243Sobrien } 7559243Sobrien if (--aleft == 0) 7659243Sobrien stderror(ERR_ALIASLOOP); 7759243Sobrien asyntax(lexp->next, lexp); 7859243Sobrien resexit(osetexit); 7959243Sobrien} 8059243Sobrien 8159243Sobrienstatic void 8259243Sobrienasyntax(p1, p2) 8359243Sobrien register struct wordent *p1, *p2; 8459243Sobrien{ 8559243Sobrien while (p1 != p2) 8659243Sobrien if (any(";&\n", p1->word[0])) 8759243Sobrien p1 = p1->next; 8859243Sobrien else { 8959243Sobrien asyn0(p1, p2); 9059243Sobrien return; 9159243Sobrien } 9259243Sobrien} 9359243Sobrien 9459243Sobrienstatic void 9559243Sobrienasyn0(p1, p2) 9659243Sobrien struct wordent *p1; 9759243Sobrien register struct wordent *p2; 9859243Sobrien{ 9959243Sobrien register struct wordent *p; 10059243Sobrien register int l = 0; 10159243Sobrien 10259243Sobrien for (p = p1; p != p2; p = p->next) 10359243Sobrien switch (p->word[0]) { 10459243Sobrien 10559243Sobrien case '(': 10659243Sobrien l++; 10759243Sobrien continue; 10859243Sobrien 10959243Sobrien case ')': 11059243Sobrien l--; 11159243Sobrien if (l < 0) 11259243Sobrien stderror(ERR_TOOMANYRP); 11359243Sobrien continue; 11459243Sobrien 11559243Sobrien case '>': 11659243Sobrien if (p->next != p2 && eq(p->next->word, STRand)) 11759243Sobrien p = p->next; 11859243Sobrien continue; 11959243Sobrien 12059243Sobrien case '&': 12159243Sobrien case '|': 12259243Sobrien case ';': 12359243Sobrien case '\n': 12459243Sobrien if (l != 0) 12559243Sobrien continue; 12659243Sobrien asyn3(p1, p); 12759243Sobrien asyntax(p->next, p2); 12859243Sobrien return; 12959243Sobrien 13059243Sobrien default: 13159243Sobrien break; 13259243Sobrien } 13359243Sobrien if (l == 0) 13459243Sobrien asyn3(p1, p2); 13559243Sobrien} 13659243Sobrien 13759243Sobrienstatic void 13859243Sobrienasyn3(p1, p2) 13959243Sobrien struct wordent *p1; 14059243Sobrien register struct wordent *p2; 14159243Sobrien{ 14259243Sobrien register struct varent *ap; 14359243Sobrien struct wordent alout; 14459243Sobrien register bool redid; 14559243Sobrien 14659243Sobrien if (p1 == p2) 14759243Sobrien return; 14859243Sobrien if (p1->word[0] == '(') { 14959243Sobrien for (p2 = p2->prev; p2->word[0] != ')'; p2 = p2->prev) 15059243Sobrien if (p2 == p1) 15159243Sobrien return; 15259243Sobrien if (p2 == p1->next) 15359243Sobrien return; 15459243Sobrien asyn0(p1->next, p2); 15559243Sobrien return; 15659243Sobrien } 15759243Sobrien ap = adrof1(p1->word, &aliases); 15859243Sobrien if (ap == 0) 15959243Sobrien return; 16059243Sobrien alhistp = p1->prev; 16159243Sobrien alhistt = p2; 16259243Sobrien alvec = ap->vec; 16359243Sobrien redid = lex(&alout); 16459243Sobrien alhistp = alhistt = 0; 16559243Sobrien alvec = 0; 16659243Sobrien if (seterr) { 16759243Sobrien freelex(&alout); 16859243Sobrien stderror(ERR_OLD); 16959243Sobrien } 17059243Sobrien if (p1->word[0] && eq(p1->word, alout.next->word)) { 17159243Sobrien Char *cp = alout.next->word; 17259243Sobrien 17359243Sobrien alout.next->word = Strspl(STRQNULL, cp); 17459243Sobrien xfree((ptr_t) cp); 17559243Sobrien } 17659243Sobrien p1 = freenod(p1, redid ? p2 : p1->next); 17759243Sobrien if (alout.next != &alout) { 17859243Sobrien p1->next->prev = alout.prev->prev; 17959243Sobrien alout.prev->prev->next = p1->next; 18059243Sobrien alout.next->prev = p1; 18159243Sobrien p1->next = alout.next; 18259243Sobrien xfree((ptr_t) alout.prev->word); 18359243Sobrien xfree((ptr_t) (alout.prev)); 18459243Sobrien } 18559243Sobrien reset(); /* throw! */ 18659243Sobrien} 18759243Sobrien 18859243Sobrienstatic struct wordent * 18959243Sobrienfreenod(p1, p2) 19059243Sobrien register struct wordent *p1, *p2; 19159243Sobrien{ 19259243Sobrien register struct wordent *retp = p1->prev; 19359243Sobrien 19459243Sobrien while (p1 != p2) { 19559243Sobrien xfree((ptr_t) p1->word); 19659243Sobrien p1 = p1->next; 19759243Sobrien xfree((ptr_t) (p1->prev)); 19859243Sobrien } 19959243Sobrien retp->next = p2; 20059243Sobrien p2->prev = retp; 20159243Sobrien return (retp); 20259243Sobrien} 20359243Sobrien 20459243Sobrien#define P_HERE 1 20559243Sobrien#define P_IN 2 20659243Sobrien#define P_OUT 4 20759243Sobrien#define P_DIAG 8 20859243Sobrien 20959243Sobrien/* 21059243Sobrien * syntax 21159243Sobrien * empty 21259243Sobrien * syn0 21359243Sobrien */ 21459243Sobrienstruct command * 21559243Sobriensyntax(p1, p2, flags) 21659243Sobrien register struct wordent *p1, *p2; 21759243Sobrien int flags; 21859243Sobrien{ 21959243Sobrien 22059243Sobrien while (p1 != p2) 22159243Sobrien if (any(";&\n", p1->word[0])) 22259243Sobrien p1 = p1->next; 22359243Sobrien else 22459243Sobrien return (syn0(p1, p2, flags)); 22559243Sobrien return (0); 22659243Sobrien} 22759243Sobrien 22859243Sobrien/* 22959243Sobrien * syn0 23059243Sobrien * syn1 23159243Sobrien * syn1 & syntax 23259243Sobrien */ 23359243Sobrienstatic struct command * 23459243Sobriensyn0(p1, p2, flags) 23559243Sobrien struct wordent *p1, *p2; 23659243Sobrien int flags; 23759243Sobrien{ 23859243Sobrien register struct wordent *p; 23959243Sobrien register struct command *t, *t1; 24059243Sobrien int l; 24159243Sobrien 24259243Sobrien l = 0; 24359243Sobrien for (p = p1; p != p2; p = p->next) 24459243Sobrien switch (p->word[0]) { 24559243Sobrien 24659243Sobrien case '(': 24759243Sobrien l++; 24859243Sobrien continue; 24959243Sobrien 25059243Sobrien case ')': 25159243Sobrien l--; 25259243Sobrien if (l < 0) 25359243Sobrien seterror(ERR_TOOMANYRP); 25459243Sobrien continue; 25559243Sobrien 25659243Sobrien case '|': 25759243Sobrien if (p->word[1] == '|') 25859243Sobrien continue; 25959243Sobrien /*FALLTHROUGH*/ 26059243Sobrien 26159243Sobrien case '>': 26259243Sobrien if (p->next != p2 && eq(p->next->word, STRand)) 26359243Sobrien p = p->next; 26459243Sobrien continue; 26559243Sobrien 26659243Sobrien case '&': 26759243Sobrien if (l != 0) 26859243Sobrien break; 26959243Sobrien if (p->word[1] == '&') 27059243Sobrien continue; 27159243Sobrien t1 = syn1(p1, p, flags); 27259243Sobrien if (t1->t_dtyp == NODE_LIST || 27359243Sobrien t1->t_dtyp == NODE_AND || 27459243Sobrien t1->t_dtyp == NODE_OR) { 27559243Sobrien t = (struct command *) xcalloc(1, sizeof(*t)); 27659243Sobrien t->t_dtyp = NODE_PAREN; 27759243Sobrien t->t_dflg = F_AMPERSAND | F_NOINTERRUPT; 27859243Sobrien t->t_dspr = t1; 27959243Sobrien t1 = t; 28059243Sobrien } 28159243Sobrien else 28259243Sobrien t1->t_dflg |= F_AMPERSAND | F_NOINTERRUPT; 28359243Sobrien t = (struct command *) xcalloc(1, sizeof(*t)); 28459243Sobrien t->t_dtyp = NODE_LIST; 28559243Sobrien t->t_dflg = 0; 28659243Sobrien t->t_dcar = t1; 28759243Sobrien t->t_dcdr = syntax(p, p2, flags); 28859243Sobrien return (t); 28959243Sobrien default: 29059243Sobrien break; 29159243Sobrien } 29259243Sobrien if (l == 0) 29359243Sobrien return (syn1(p1, p2, flags)); 29459243Sobrien seterror(ERR_TOOMANYLP); 29559243Sobrien return (0); 29659243Sobrien} 29759243Sobrien 29859243Sobrien/* 29959243Sobrien * syn1 30059243Sobrien * syn1a 30159243Sobrien * syn1a ; syntax 30259243Sobrien */ 30359243Sobrienstatic struct command * 30459243Sobriensyn1(p1, p2, flags) 30559243Sobrien struct wordent *p1, *p2; 30659243Sobrien int flags; 30759243Sobrien{ 30859243Sobrien register struct wordent *p; 30959243Sobrien register struct command *t; 31059243Sobrien int l; 31159243Sobrien 31259243Sobrien l = 0; 31359243Sobrien for (p = p1; p != p2; p = p->next) 31459243Sobrien switch (p->word[0]) { 31559243Sobrien 31659243Sobrien case '(': 31759243Sobrien l++; 31859243Sobrien continue; 31959243Sobrien 32059243Sobrien case ')': 32159243Sobrien l--; 32259243Sobrien continue; 32359243Sobrien 32459243Sobrien case ';': 32559243Sobrien case '\n': 32659243Sobrien if (l != 0) 32759243Sobrien break; 32859243Sobrien t = (struct command *) xcalloc(1, sizeof(*t)); 32959243Sobrien t->t_dtyp = NODE_LIST; 33059243Sobrien t->t_dcar = syn1a(p1, p, flags); 33159243Sobrien t->t_dcdr = syntax(p->next, p2, flags); 33259243Sobrien if (t->t_dcdr == 0) 33359243Sobrien t->t_dcdr = t->t_dcar, t->t_dcar = 0; 33459243Sobrien return (t); 33559243Sobrien 33659243Sobrien default: 33759243Sobrien break; 33859243Sobrien } 33959243Sobrien return (syn1a(p1, p2, flags)); 34059243Sobrien} 34159243Sobrien 34259243Sobrien/* 34359243Sobrien * syn1a 34459243Sobrien * syn1b 34559243Sobrien * syn1b || syn1a 34659243Sobrien */ 34759243Sobrienstatic struct command * 34859243Sobriensyn1a(p1, p2, flags) 34959243Sobrien struct wordent *p1, *p2; 35059243Sobrien int flags; 35159243Sobrien{ 35259243Sobrien register struct wordent *p; 35359243Sobrien register struct command *t; 35459243Sobrien register int l = 0; 35559243Sobrien 35659243Sobrien for (p = p1; p != p2; p = p->next) 35759243Sobrien switch (p->word[0]) { 35859243Sobrien 35959243Sobrien case '(': 36059243Sobrien l++; 36159243Sobrien continue; 36259243Sobrien 36359243Sobrien case ')': 36459243Sobrien l--; 36559243Sobrien continue; 36659243Sobrien 36759243Sobrien case '|': 36859243Sobrien if (p->word[1] != '|') 36959243Sobrien continue; 37059243Sobrien if (l == 0) { 37159243Sobrien t = (struct command *) xcalloc(1, sizeof(*t)); 37259243Sobrien t->t_dtyp = NODE_OR; 37359243Sobrien t->t_dcar = syn1b(p1, p, flags); 37459243Sobrien t->t_dcdr = syn1a(p->next, p2, flags); 37559243Sobrien t->t_dflg = 0; 37659243Sobrien return (t); 37759243Sobrien } 37859243Sobrien continue; 37959243Sobrien 38059243Sobrien default: 38159243Sobrien break; 38259243Sobrien } 38359243Sobrien return (syn1b(p1, p2, flags)); 38459243Sobrien} 38559243Sobrien 38659243Sobrien/* 38759243Sobrien * syn1b 38859243Sobrien * syn2 38959243Sobrien * syn2 && syn1b 39059243Sobrien */ 39159243Sobrienstatic struct command * 39259243Sobriensyn1b(p1, p2, flags) 39359243Sobrien struct wordent *p1, *p2; 39459243Sobrien int flags; 39559243Sobrien{ 39659243Sobrien register struct wordent *p; 39759243Sobrien register struct command *t; 39859243Sobrien register int l = 0; 39959243Sobrien 40059243Sobrien for (p = p1; p != p2; p = p->next) 40159243Sobrien switch (p->word[0]) { 40259243Sobrien 40359243Sobrien case '(': 40459243Sobrien l++; 40559243Sobrien continue; 40659243Sobrien 40759243Sobrien case ')': 40859243Sobrien l--; 40959243Sobrien continue; 41059243Sobrien 41159243Sobrien case '&': 41259243Sobrien if (p->word[1] == '&' && l == 0) { 41359243Sobrien t = (struct command *) xcalloc(1, sizeof(*t)); 41459243Sobrien t->t_dtyp = NODE_AND; 41559243Sobrien t->t_dcar = syn2(p1, p, flags); 41659243Sobrien t->t_dcdr = syn1b(p->next, p2, flags); 41759243Sobrien t->t_dflg = 0; 41859243Sobrien return (t); 41959243Sobrien } 42059243Sobrien continue; 42159243Sobrien 42259243Sobrien default: 42359243Sobrien break; 42459243Sobrien } 42559243Sobrien return (syn2(p1, p2, flags)); 42659243Sobrien} 42759243Sobrien 42859243Sobrien/* 42959243Sobrien * syn2 43059243Sobrien * syn3 43159243Sobrien * syn3 | syn2 43259243Sobrien * syn3 |& syn2 43359243Sobrien */ 43459243Sobrienstatic struct command * 43559243Sobriensyn2(p1, p2, flags) 43659243Sobrien struct wordent *p1, *p2; 43759243Sobrien int flags; 43859243Sobrien{ 43959243Sobrien register struct wordent *p, *pn; 44059243Sobrien register struct command *t; 44159243Sobrien register int l = 0; 44259243Sobrien int f; 44359243Sobrien 44459243Sobrien for (p = p1; p != p2; p = p->next) 44559243Sobrien switch (p->word[0]) { 44659243Sobrien 44759243Sobrien case '(': 44859243Sobrien l++; 44959243Sobrien continue; 45059243Sobrien 45159243Sobrien case ')': 45259243Sobrien l--; 45359243Sobrien continue; 45459243Sobrien 45559243Sobrien case '|': 45659243Sobrien if (l != 0) 45759243Sobrien continue; 45859243Sobrien t = (struct command *) xcalloc(1, sizeof(*t)); 45959243Sobrien f = flags | P_OUT; 46059243Sobrien pn = p->next; 46159243Sobrien if (pn != p2 && pn->word[0] == '&') { 46259243Sobrien f |= P_DIAG; 46359243Sobrien t->t_dflg |= F_STDERR; 46459243Sobrien } 46559243Sobrien t->t_dtyp = NODE_PIPE; 46659243Sobrien t->t_dcar = syn3(p1, p, f); 46759243Sobrien if (pn != p2 && pn->word[0] == '&') 46859243Sobrien p = pn; 46959243Sobrien t->t_dcdr = syn2(p->next, p2, flags | P_IN); 47059243Sobrien return (t); 47159243Sobrien 47259243Sobrien default: 47359243Sobrien break; 47459243Sobrien } 47559243Sobrien return (syn3(p1, p2, flags)); 47659243Sobrien} 47759243Sobrien 47859243Sobrienstatic char RELPAR[] = {'<', '>', '(', ')', '\0'}; 47959243Sobrien 48059243Sobrien/* 48159243Sobrien * syn3 48259243Sobrien * ( syn0 ) [ < in ] [ > out ] 48359243Sobrien * word word* [ < in ] [ > out ] 48459243Sobrien * KEYWORD ( word* ) word* [ < in ] [ > out ] 48559243Sobrien * 48659243Sobrien * KEYWORD = (@ exit foreach if set switch test while) 48759243Sobrien */ 48859243Sobrienstatic struct command * 48959243Sobriensyn3(p1, p2, flags) 49059243Sobrien struct wordent *p1, *p2; 49159243Sobrien int flags; 49259243Sobrien{ 49359243Sobrien register struct wordent *p; 49459243Sobrien struct wordent *lp, *rp; 49559243Sobrien register struct command *t; 49659243Sobrien register int l; 49759243Sobrien Char **av; 49859243Sobrien int n, c; 49959243Sobrien bool specp = 0; 50059243Sobrien 50159243Sobrien if (p1 != p2) { 50259243Sobrien p = p1; 50359243Sobrienagain: 50459243Sobrien switch (srchx(p->word)) { 50559243Sobrien 50659243Sobrien case TC_ELSE: 50759243Sobrien p = p->next; 50859243Sobrien if (p != p2) 50959243Sobrien goto again; 51059243Sobrien break; 51159243Sobrien 51259243Sobrien case TC_EXIT: 51359243Sobrien case TC_FOREACH: 51459243Sobrien case TC_IF: 51559243Sobrien case TC_LET: 51659243Sobrien case TC_SET: 51759243Sobrien case TC_SWITCH: 51859243Sobrien case TC_WHILE: 51959243Sobrien specp = 1; 52059243Sobrien break; 52159243Sobrien default: 52259243Sobrien break; 52359243Sobrien } 52459243Sobrien } 52559243Sobrien n = 0; 52659243Sobrien l = 0; 52759243Sobrien for (p = p1; p != p2; p = p->next) 52859243Sobrien switch (p->word[0]) { 52959243Sobrien 53059243Sobrien case '(': 53159243Sobrien if (specp) 53259243Sobrien n++; 53359243Sobrien l++; 53459243Sobrien continue; 53559243Sobrien 53659243Sobrien case ')': 53759243Sobrien if (specp) 53859243Sobrien n++; 53959243Sobrien l--; 54059243Sobrien continue; 54159243Sobrien 54259243Sobrien case '>': 54359243Sobrien case '<': 54459243Sobrien if (l != 0) { 54559243Sobrien if (specp) 54659243Sobrien n++; 54759243Sobrien continue; 54859243Sobrien } 54959243Sobrien if (p->next == p2) 55059243Sobrien continue; 55159243Sobrien if (any(RELPAR, p->next->word[0])) 55259243Sobrien continue; 55359243Sobrien n--; 55459243Sobrien continue; 55559243Sobrien 55659243Sobrien default: 55759243Sobrien if (!specp && l != 0) 55859243Sobrien continue; 55959243Sobrien n++; 56059243Sobrien continue; 56159243Sobrien } 56259243Sobrien if (n < 0) 56359243Sobrien n = 0; 56459243Sobrien t = (struct command *) xcalloc(1, sizeof(*t)); 56559243Sobrien av = (Char **) xcalloc((size_t) (n + 1), sizeof(Char **)); 56659243Sobrien t->t_dcom = av; 56759243Sobrien n = 0; 56859243Sobrien if (p2->word[0] == ')') 56959243Sobrien t->t_dflg = F_NOFORK; 57059243Sobrien lp = 0; 57159243Sobrien rp = 0; 57259243Sobrien l = 0; 57359243Sobrien for (p = p1; p != p2; p = p->next) { 57459243Sobrien c = p->word[0]; 57559243Sobrien switch (c) { 57659243Sobrien 57759243Sobrien case '(': 57859243Sobrien if (l == 0) { 57959243Sobrien if (lp != 0 && !specp) 58059243Sobrien seterror(ERR_BADPLP); 58159243Sobrien lp = p->next; 58259243Sobrien } 58359243Sobrien l++; 58459243Sobrien goto savep; 58559243Sobrien 58659243Sobrien case ')': 58759243Sobrien l--; 58859243Sobrien if (l == 0) 58959243Sobrien rp = p; 59059243Sobrien goto savep; 59159243Sobrien 59259243Sobrien case '>': 59359243Sobrien if (l != 0) 59459243Sobrien goto savep; 59559243Sobrien if (p->word[1] == '>') 59659243Sobrien t->t_dflg |= F_APPEND; 59759243Sobrien if (p->next != p2 && eq(p->next->word, STRand)) { 59859243Sobrien t->t_dflg |= F_STDERR, p = p->next; 59959243Sobrien if (flags & (P_OUT | P_DIAG)) { 60059243Sobrien seterror(ERR_OUTRED); 60159243Sobrien continue; 60259243Sobrien } 60359243Sobrien } 60459243Sobrien if (p->next != p2 && eq(p->next->word, STRbang)) 60559243Sobrien t->t_dflg |= F_OVERWRITE, p = p->next; 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_OUT) && (flags & P_DIAG) == 0) || t->t_drit) 61659243Sobrien seterror(ERR_OUTRED); 61759243Sobrien else 61859243Sobrien t->t_drit = Strsave(p->word); 61959243Sobrien continue; 62059243Sobrien 62159243Sobrien case '<': 62259243Sobrien if (l != 0) 62359243Sobrien goto savep; 62459243Sobrien if (p->word[1] == '<') 62559243Sobrien t->t_dflg |= F_READ; 62659243Sobrien if (p->next == p2) { 62759243Sobrien seterror(ERR_MISRED); 62859243Sobrien continue; 62959243Sobrien } 63059243Sobrien p = p->next; 63159243Sobrien if (any(RELPAR, p->word[0])) { 63259243Sobrien seterror(ERR_MISRED); 63359243Sobrien continue; 63459243Sobrien } 63559243Sobrien if ((flags & P_HERE) && (t->t_dflg & F_READ)) 63659243Sobrien seterror(ERR_REDPAR); 63759243Sobrien else if ((flags & P_IN) || t->t_dlef) 63859243Sobrien seterror(ERR_INRED); 63959243Sobrien else 64059243Sobrien t->t_dlef = Strsave(p->word); 64159243Sobrien continue; 64259243Sobrien 64359243Sobrien savep: 64459243Sobrien if (!specp) 64559243Sobrien continue; 64659243Sobrien default: 64759243Sobrien if (l != 0 && !specp) 64859243Sobrien continue; 64959243Sobrien if (seterr == 0) 65059243Sobrien av[n] = Strsave(p->word); 65159243Sobrien n++; 65259243Sobrien continue; 65359243Sobrien } 65459243Sobrien } 65559243Sobrien if (lp != 0 && !specp) { 65659243Sobrien if (n != 0) 65759243Sobrien seterror(ERR_BADPLPS); 65859243Sobrien t->t_dtyp = NODE_PAREN; 65959243Sobrien t->t_dspr = syn0(lp, rp, P_HERE); 66059243Sobrien } 66159243Sobrien else { 66259243Sobrien if (n == 0) 66359243Sobrien seterror(ERR_NULLCOM); 66459243Sobrien t->t_dtyp = NODE_COMMAND; 66559243Sobrien } 66659243Sobrien return (t); 66759243Sobrien} 66859243Sobrien 66959243Sobrienvoid 67059243Sobrienfreesyn(t) 67159243Sobrien register struct command *t; 67259243Sobrien{ 67359243Sobrien register Char **v; 67459243Sobrien 67559243Sobrien if (t == 0) 67659243Sobrien return; 67759243Sobrien switch (t->t_dtyp) { 67859243Sobrien 67959243Sobrien case NODE_COMMAND: 68059243Sobrien for (v = t->t_dcom; *v; v++) 68159243Sobrien xfree((ptr_t) * v); 68259243Sobrien xfree((ptr_t) (t->t_dcom)); 68359243Sobrien xfree((ptr_t) t->t_dlef); 68459243Sobrien xfree((ptr_t) t->t_drit); 68559243Sobrien break; 68659243Sobrien case NODE_PAREN: 68759243Sobrien freesyn(t->t_dspr); 68859243Sobrien xfree((ptr_t) t->t_dlef); 68959243Sobrien xfree((ptr_t) t->t_drit); 69059243Sobrien break; 69159243Sobrien 69259243Sobrien case NODE_AND: 69359243Sobrien case NODE_OR: 69459243Sobrien case NODE_PIPE: 69559243Sobrien case NODE_LIST: 69659243Sobrien freesyn(t->t_dcar), freesyn(t->t_dcdr); 69759243Sobrien break; 69859243Sobrien default: 69959243Sobrien break; 70059243Sobrien } 70159243Sobrien xfree((ptr_t) t); 70259243Sobrien} 703