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