1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * Copyright 1995 Sun Microsystems, Inc. All rights reserved. 3*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 4*7c478bd9Sstevel@tonic-gate */ 5*7c478bd9Sstevel@tonic-gate 6*7c478bd9Sstevel@tonic-gate /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 7*7c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 8*7c478bd9Sstevel@tonic-gate 9*7c478bd9Sstevel@tonic-gate /* 10*7c478bd9Sstevel@tonic-gate * Copyright (c) 1980 Regents of the University of California. 11*7c478bd9Sstevel@tonic-gate * All rights reserved. The Berkeley Software License Agreement 12*7c478bd9Sstevel@tonic-gate * specifies the terms and conditions for redistribution. 13*7c478bd9Sstevel@tonic-gate */ 14*7c478bd9Sstevel@tonic-gate 15*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 16*7c478bd9Sstevel@tonic-gate 17*7c478bd9Sstevel@tonic-gate #include "sh.h" 18*7c478bd9Sstevel@tonic-gate #include "sh.tconst.h" 19*7c478bd9Sstevel@tonic-gate 20*7c478bd9Sstevel@tonic-gate /* 21*7c478bd9Sstevel@tonic-gate * C shell 22*7c478bd9Sstevel@tonic-gate */ 23*7c478bd9Sstevel@tonic-gate 24*7c478bd9Sstevel@tonic-gate /* 25*7c478bd9Sstevel@tonic-gate * Perform aliasing on the word list lex 26*7c478bd9Sstevel@tonic-gate * Do a (very rudimentary) parse to separate into commands. 27*7c478bd9Sstevel@tonic-gate * If word 0 of a command has an alias, do it. 28*7c478bd9Sstevel@tonic-gate * Repeat a maximum of 20 times. 29*7c478bd9Sstevel@tonic-gate */ 30*7c478bd9Sstevel@tonic-gate alias(lex) 31*7c478bd9Sstevel@tonic-gate register struct wordent *lex; 32*7c478bd9Sstevel@tonic-gate { 33*7c478bd9Sstevel@tonic-gate int aleft = 21; 34*7c478bd9Sstevel@tonic-gate jmp_buf osetexit; 35*7c478bd9Sstevel@tonic-gate 36*7c478bd9Sstevel@tonic-gate #ifdef TRACE 37*7c478bd9Sstevel@tonic-gate tprintf("TRACE- alias()\n"); 38*7c478bd9Sstevel@tonic-gate #endif 39*7c478bd9Sstevel@tonic-gate getexit(osetexit); 40*7c478bd9Sstevel@tonic-gate setexit(); 41*7c478bd9Sstevel@tonic-gate if (haderr) { 42*7c478bd9Sstevel@tonic-gate resexit(osetexit); 43*7c478bd9Sstevel@tonic-gate reset(); 44*7c478bd9Sstevel@tonic-gate } 45*7c478bd9Sstevel@tonic-gate if (--aleft == 0) 46*7c478bd9Sstevel@tonic-gate error("Alias loop"); 47*7c478bd9Sstevel@tonic-gate asyntax(lex->next, lex); 48*7c478bd9Sstevel@tonic-gate resexit(osetexit); 49*7c478bd9Sstevel@tonic-gate } 50*7c478bd9Sstevel@tonic-gate 51*7c478bd9Sstevel@tonic-gate asyntax(p1, p2) 52*7c478bd9Sstevel@tonic-gate register struct wordent *p1, *p2; 53*7c478bd9Sstevel@tonic-gate { 54*7c478bd9Sstevel@tonic-gate #ifdef TRACE 55*7c478bd9Sstevel@tonic-gate tprintf("TRACE- asyntax()\n"); 56*7c478bd9Sstevel@tonic-gate #endif 57*7c478bd9Sstevel@tonic-gate 58*7c478bd9Sstevel@tonic-gate while (p1 != p2) 59*7c478bd9Sstevel@tonic-gate /* if (any(p1->word[0], ";&\n")) */ /* For char -> tchar */ 60*7c478bd9Sstevel@tonic-gate if (p1->word[0] == ';' || 61*7c478bd9Sstevel@tonic-gate p1->word[0] == '&' || 62*7c478bd9Sstevel@tonic-gate p1->word[0] == '\n') 63*7c478bd9Sstevel@tonic-gate p1 = p1->next; 64*7c478bd9Sstevel@tonic-gate else { 65*7c478bd9Sstevel@tonic-gate asyn0(p1, p2); 66*7c478bd9Sstevel@tonic-gate return; 67*7c478bd9Sstevel@tonic-gate } 68*7c478bd9Sstevel@tonic-gate } 69*7c478bd9Sstevel@tonic-gate 70*7c478bd9Sstevel@tonic-gate asyn0(p1, p2) 71*7c478bd9Sstevel@tonic-gate struct wordent *p1; 72*7c478bd9Sstevel@tonic-gate register struct wordent *p2; 73*7c478bd9Sstevel@tonic-gate { 74*7c478bd9Sstevel@tonic-gate register struct wordent *p; 75*7c478bd9Sstevel@tonic-gate register int l = 0; 76*7c478bd9Sstevel@tonic-gate 77*7c478bd9Sstevel@tonic-gate #ifdef TRACE 78*7c478bd9Sstevel@tonic-gate tprintf("TRACE- asyn0()\n"); 79*7c478bd9Sstevel@tonic-gate #endif 80*7c478bd9Sstevel@tonic-gate for (p = p1; p != p2; p = p->next) 81*7c478bd9Sstevel@tonic-gate switch (p->word[0]) { 82*7c478bd9Sstevel@tonic-gate 83*7c478bd9Sstevel@tonic-gate case '(': 84*7c478bd9Sstevel@tonic-gate l++; 85*7c478bd9Sstevel@tonic-gate continue; 86*7c478bd9Sstevel@tonic-gate 87*7c478bd9Sstevel@tonic-gate case ')': 88*7c478bd9Sstevel@tonic-gate l--; 89*7c478bd9Sstevel@tonic-gate if (l < 0) 90*7c478bd9Sstevel@tonic-gate error("Too many )'s"); 91*7c478bd9Sstevel@tonic-gate continue; 92*7c478bd9Sstevel@tonic-gate 93*7c478bd9Sstevel@tonic-gate case '>': 94*7c478bd9Sstevel@tonic-gate if (p->next != p2 && eq(p->next->word, S_AND /* "&"*/)) 95*7c478bd9Sstevel@tonic-gate p = p->next; 96*7c478bd9Sstevel@tonic-gate continue; 97*7c478bd9Sstevel@tonic-gate 98*7c478bd9Sstevel@tonic-gate case '&': 99*7c478bd9Sstevel@tonic-gate case '|': 100*7c478bd9Sstevel@tonic-gate case ';': 101*7c478bd9Sstevel@tonic-gate case '\n': 102*7c478bd9Sstevel@tonic-gate if (l != 0) 103*7c478bd9Sstevel@tonic-gate continue; 104*7c478bd9Sstevel@tonic-gate asyn3(p1, p); 105*7c478bd9Sstevel@tonic-gate asyntax(p->next, p2); 106*7c478bd9Sstevel@tonic-gate return; 107*7c478bd9Sstevel@tonic-gate } 108*7c478bd9Sstevel@tonic-gate if (l == 0) 109*7c478bd9Sstevel@tonic-gate asyn3(p1, p2); 110*7c478bd9Sstevel@tonic-gate } 111*7c478bd9Sstevel@tonic-gate 112*7c478bd9Sstevel@tonic-gate asyn3(p1, p2) 113*7c478bd9Sstevel@tonic-gate struct wordent *p1; 114*7c478bd9Sstevel@tonic-gate register struct wordent *p2; 115*7c478bd9Sstevel@tonic-gate { 116*7c478bd9Sstevel@tonic-gate register struct varent *ap; 117*7c478bd9Sstevel@tonic-gate struct wordent alout; 118*7c478bd9Sstevel@tonic-gate register bool redid; 119*7c478bd9Sstevel@tonic-gate 120*7c478bd9Sstevel@tonic-gate #ifdef TRACE 121*7c478bd9Sstevel@tonic-gate tprintf("TRACE- asyn3()\n"); 122*7c478bd9Sstevel@tonic-gate #endif 123*7c478bd9Sstevel@tonic-gate if (p1 == p2) 124*7c478bd9Sstevel@tonic-gate return; 125*7c478bd9Sstevel@tonic-gate if (p1->word[0] == '(') { 126*7c478bd9Sstevel@tonic-gate for (p2 = p2->prev; p2->word[0] != ')'; p2 = p2->prev) 127*7c478bd9Sstevel@tonic-gate if (p2 == p1) 128*7c478bd9Sstevel@tonic-gate return; 129*7c478bd9Sstevel@tonic-gate if (p2 == p1->next) 130*7c478bd9Sstevel@tonic-gate return; 131*7c478bd9Sstevel@tonic-gate asyn0(p1->next, p2); 132*7c478bd9Sstevel@tonic-gate return; 133*7c478bd9Sstevel@tonic-gate } 134*7c478bd9Sstevel@tonic-gate ap = adrof1(p1->word, &aliases); 135*7c478bd9Sstevel@tonic-gate if (ap == 0) 136*7c478bd9Sstevel@tonic-gate return; 137*7c478bd9Sstevel@tonic-gate alhistp = p1->prev; 138*7c478bd9Sstevel@tonic-gate alhistt = p2; 139*7c478bd9Sstevel@tonic-gate alvec = ap->vec; 140*7c478bd9Sstevel@tonic-gate redid = lex(&alout); 141*7c478bd9Sstevel@tonic-gate alhistp = alhistt = 0; 142*7c478bd9Sstevel@tonic-gate alvec = 0; 143*7c478bd9Sstevel@tonic-gate if (err) { 144*7c478bd9Sstevel@tonic-gate freelex(&alout); 145*7c478bd9Sstevel@tonic-gate error("%s", gettext(err)); 146*7c478bd9Sstevel@tonic-gate } 147*7c478bd9Sstevel@tonic-gate if (p1->word[0] && eq(p1->word, alout.next->word)) { 148*7c478bd9Sstevel@tonic-gate tchar *cp = alout.next->word; 149*7c478bd9Sstevel@tonic-gate 150*7c478bd9Sstevel@tonic-gate alout.next->word = strspl(S_TOPBIT /*"\200"*/, cp); 151*7c478bd9Sstevel@tonic-gate XFREE(cp) 152*7c478bd9Sstevel@tonic-gate } 153*7c478bd9Sstevel@tonic-gate p1 = freenod(p1, redid ? p2 : p1->next); 154*7c478bd9Sstevel@tonic-gate if (alout.next != &alout) { 155*7c478bd9Sstevel@tonic-gate p1->next->prev = alout.prev->prev; 156*7c478bd9Sstevel@tonic-gate alout.prev->prev->next = p1->next; 157*7c478bd9Sstevel@tonic-gate alout.next->prev = p1; 158*7c478bd9Sstevel@tonic-gate p1->next = alout.next; 159*7c478bd9Sstevel@tonic-gate XFREE(alout.prev->word) 160*7c478bd9Sstevel@tonic-gate XFREE( (tchar *)alout.prev) 161*7c478bd9Sstevel@tonic-gate } 162*7c478bd9Sstevel@tonic-gate reset(); /* throw! */ 163*7c478bd9Sstevel@tonic-gate } 164*7c478bd9Sstevel@tonic-gate 165*7c478bd9Sstevel@tonic-gate struct wordent * 166*7c478bd9Sstevel@tonic-gate freenod(p1, p2) 167*7c478bd9Sstevel@tonic-gate register struct wordent *p1, *p2; 168*7c478bd9Sstevel@tonic-gate { 169*7c478bd9Sstevel@tonic-gate register struct wordent *retp = p1->prev; 170*7c478bd9Sstevel@tonic-gate 171*7c478bd9Sstevel@tonic-gate #ifdef TRACE 172*7c478bd9Sstevel@tonic-gate tprintf("TRACE- freenod()\n"); 173*7c478bd9Sstevel@tonic-gate #endif 174*7c478bd9Sstevel@tonic-gate while (p1 != p2) { 175*7c478bd9Sstevel@tonic-gate XFREE(p1->word) 176*7c478bd9Sstevel@tonic-gate p1 = p1->next; 177*7c478bd9Sstevel@tonic-gate XFREE( (tchar *)p1->prev) 178*7c478bd9Sstevel@tonic-gate } 179*7c478bd9Sstevel@tonic-gate retp->next = p2; 180*7c478bd9Sstevel@tonic-gate p2->prev = retp; 181*7c478bd9Sstevel@tonic-gate return (retp); 182*7c478bd9Sstevel@tonic-gate } 183*7c478bd9Sstevel@tonic-gate 184*7c478bd9Sstevel@tonic-gate #define PHERE 1 185*7c478bd9Sstevel@tonic-gate #define PIN 2 186*7c478bd9Sstevel@tonic-gate #define POUT 4 187*7c478bd9Sstevel@tonic-gate #define PDIAG 8 188*7c478bd9Sstevel@tonic-gate 189*7c478bd9Sstevel@tonic-gate /* 190*7c478bd9Sstevel@tonic-gate * syntax 191*7c478bd9Sstevel@tonic-gate * empty 192*7c478bd9Sstevel@tonic-gate * syn0 193*7c478bd9Sstevel@tonic-gate */ 194*7c478bd9Sstevel@tonic-gate struct command * 195*7c478bd9Sstevel@tonic-gate syntax(p1, p2, flags) 196*7c478bd9Sstevel@tonic-gate register struct wordent *p1, *p2; 197*7c478bd9Sstevel@tonic-gate int flags; 198*7c478bd9Sstevel@tonic-gate { 199*7c478bd9Sstevel@tonic-gate #ifdef TRACE 200*7c478bd9Sstevel@tonic-gate tprintf("TRACE- syntax()\n"); 201*7c478bd9Sstevel@tonic-gate #endif 202*7c478bd9Sstevel@tonic-gate 203*7c478bd9Sstevel@tonic-gate while (p1 != p2) 204*7c478bd9Sstevel@tonic-gate /* if (any(p1->word[0], ";&\n")) */ /* for char -> tchar */ 205*7c478bd9Sstevel@tonic-gate if (p1->word[0] == ';' || 206*7c478bd9Sstevel@tonic-gate p1->word[0] == '&' || 207*7c478bd9Sstevel@tonic-gate p1->word[0] == '\n') 208*7c478bd9Sstevel@tonic-gate p1 = p1->next; 209*7c478bd9Sstevel@tonic-gate else 210*7c478bd9Sstevel@tonic-gate return (syn0(p1, p2, flags)); 211*7c478bd9Sstevel@tonic-gate return (0); 212*7c478bd9Sstevel@tonic-gate } 213*7c478bd9Sstevel@tonic-gate 214*7c478bd9Sstevel@tonic-gate /* 215*7c478bd9Sstevel@tonic-gate * syn0 216*7c478bd9Sstevel@tonic-gate * syn1 217*7c478bd9Sstevel@tonic-gate * syn1 & syntax 218*7c478bd9Sstevel@tonic-gate */ 219*7c478bd9Sstevel@tonic-gate struct command * 220*7c478bd9Sstevel@tonic-gate syn0(p1, p2, flags) 221*7c478bd9Sstevel@tonic-gate struct wordent *p1, *p2; 222*7c478bd9Sstevel@tonic-gate int flags; 223*7c478bd9Sstevel@tonic-gate { 224*7c478bd9Sstevel@tonic-gate register struct wordent *p; 225*7c478bd9Sstevel@tonic-gate register struct command *t, *t1; 226*7c478bd9Sstevel@tonic-gate int l; 227*7c478bd9Sstevel@tonic-gate 228*7c478bd9Sstevel@tonic-gate #ifdef TRACE 229*7c478bd9Sstevel@tonic-gate tprintf("TRACE- syn0()\n"); 230*7c478bd9Sstevel@tonic-gate #endif 231*7c478bd9Sstevel@tonic-gate l = 0; 232*7c478bd9Sstevel@tonic-gate for (p = p1; p != p2; p = p->next) 233*7c478bd9Sstevel@tonic-gate switch (p->word[0]) { 234*7c478bd9Sstevel@tonic-gate 235*7c478bd9Sstevel@tonic-gate case '(': 236*7c478bd9Sstevel@tonic-gate l++; 237*7c478bd9Sstevel@tonic-gate continue; 238*7c478bd9Sstevel@tonic-gate 239*7c478bd9Sstevel@tonic-gate case ')': 240*7c478bd9Sstevel@tonic-gate l--; 241*7c478bd9Sstevel@tonic-gate if (l < 0) 242*7c478bd9Sstevel@tonic-gate seterr("Too many )'s"); 243*7c478bd9Sstevel@tonic-gate continue; 244*7c478bd9Sstevel@tonic-gate 245*7c478bd9Sstevel@tonic-gate case '|': 246*7c478bd9Sstevel@tonic-gate if (p->word[1] == '|') 247*7c478bd9Sstevel@tonic-gate continue; 248*7c478bd9Sstevel@tonic-gate /* fall into ... */ 249*7c478bd9Sstevel@tonic-gate 250*7c478bd9Sstevel@tonic-gate case '>': 251*7c478bd9Sstevel@tonic-gate if (p->next != p2 && eq(p->next->word, S_AND /*"&"*/)) 252*7c478bd9Sstevel@tonic-gate p = p->next; 253*7c478bd9Sstevel@tonic-gate continue; 254*7c478bd9Sstevel@tonic-gate 255*7c478bd9Sstevel@tonic-gate case '&': 256*7c478bd9Sstevel@tonic-gate if (l != 0) 257*7c478bd9Sstevel@tonic-gate break; 258*7c478bd9Sstevel@tonic-gate if (p->word[1] == '&') 259*7c478bd9Sstevel@tonic-gate continue; 260*7c478bd9Sstevel@tonic-gate t1 = syn1(p1, p, flags); 261*7c478bd9Sstevel@tonic-gate if (t1->t_dtyp == TLST || 262*7c478bd9Sstevel@tonic-gate t1->t_dtyp == TAND || 263*7c478bd9Sstevel@tonic-gate t1->t_dtyp == TOR) { 264*7c478bd9Sstevel@tonic-gate t = (struct command *) calloc(1, sizeof (*t)); 265*7c478bd9Sstevel@tonic-gate t->t_dtyp = TPAR; 266*7c478bd9Sstevel@tonic-gate t->t_dflg = FAND|FINT; 267*7c478bd9Sstevel@tonic-gate t->t_dspr = t1; 268*7c478bd9Sstevel@tonic-gate t1 = t; 269*7c478bd9Sstevel@tonic-gate } else 270*7c478bd9Sstevel@tonic-gate t1->t_dflg |= FAND|FINT; 271*7c478bd9Sstevel@tonic-gate t = (struct command *) calloc(1, sizeof (*t)); 272*7c478bd9Sstevel@tonic-gate t->t_dtyp = TLST; 273*7c478bd9Sstevel@tonic-gate t->t_dflg = 0; 274*7c478bd9Sstevel@tonic-gate t->t_dcar = t1; 275*7c478bd9Sstevel@tonic-gate t->t_dcdr = syntax(p, p2, flags); 276*7c478bd9Sstevel@tonic-gate return(t); 277*7c478bd9Sstevel@tonic-gate } 278*7c478bd9Sstevel@tonic-gate if (l == 0) 279*7c478bd9Sstevel@tonic-gate return (syn1(p1, p2, flags)); 280*7c478bd9Sstevel@tonic-gate seterr("Too many ('s"); 281*7c478bd9Sstevel@tonic-gate return (0); 282*7c478bd9Sstevel@tonic-gate } 283*7c478bd9Sstevel@tonic-gate 284*7c478bd9Sstevel@tonic-gate /* 285*7c478bd9Sstevel@tonic-gate * syn1 286*7c478bd9Sstevel@tonic-gate * syn1a 287*7c478bd9Sstevel@tonic-gate * syn1a ; syntax 288*7c478bd9Sstevel@tonic-gate */ 289*7c478bd9Sstevel@tonic-gate struct command * 290*7c478bd9Sstevel@tonic-gate syn1(p1, p2, flags) 291*7c478bd9Sstevel@tonic-gate struct wordent *p1, *p2; 292*7c478bd9Sstevel@tonic-gate int flags; 293*7c478bd9Sstevel@tonic-gate { 294*7c478bd9Sstevel@tonic-gate register struct wordent *p; 295*7c478bd9Sstevel@tonic-gate register struct command *t; 296*7c478bd9Sstevel@tonic-gate int l; 297*7c478bd9Sstevel@tonic-gate 298*7c478bd9Sstevel@tonic-gate #ifdef TRACE 299*7c478bd9Sstevel@tonic-gate tprintf("TRACE- syn1()\n"); 300*7c478bd9Sstevel@tonic-gate #endif 301*7c478bd9Sstevel@tonic-gate l = 0; 302*7c478bd9Sstevel@tonic-gate for (p = p1; p != p2; p = p->next) 303*7c478bd9Sstevel@tonic-gate switch (p->word[0]) { 304*7c478bd9Sstevel@tonic-gate 305*7c478bd9Sstevel@tonic-gate case '(': 306*7c478bd9Sstevel@tonic-gate l++; 307*7c478bd9Sstevel@tonic-gate continue; 308*7c478bd9Sstevel@tonic-gate 309*7c478bd9Sstevel@tonic-gate case ')': 310*7c478bd9Sstevel@tonic-gate l--; 311*7c478bd9Sstevel@tonic-gate continue; 312*7c478bd9Sstevel@tonic-gate 313*7c478bd9Sstevel@tonic-gate case ';': 314*7c478bd9Sstevel@tonic-gate case '\n': 315*7c478bd9Sstevel@tonic-gate if (l != 0) 316*7c478bd9Sstevel@tonic-gate break; 317*7c478bd9Sstevel@tonic-gate t = (struct command *) calloc(1, sizeof (*t)); 318*7c478bd9Sstevel@tonic-gate t->t_dtyp = TLST; 319*7c478bd9Sstevel@tonic-gate t->t_dcar = syn1a(p1, p, flags); 320*7c478bd9Sstevel@tonic-gate t->t_dcdr = syntax(p->next, p2, flags); 321*7c478bd9Sstevel@tonic-gate if (t->t_dcdr == 0) 322*7c478bd9Sstevel@tonic-gate t->t_dcdr = t->t_dcar, t->t_dcar = 0; 323*7c478bd9Sstevel@tonic-gate return (t); 324*7c478bd9Sstevel@tonic-gate } 325*7c478bd9Sstevel@tonic-gate return (syn1a(p1, p2, flags)); 326*7c478bd9Sstevel@tonic-gate } 327*7c478bd9Sstevel@tonic-gate 328*7c478bd9Sstevel@tonic-gate /* 329*7c478bd9Sstevel@tonic-gate * syn1a 330*7c478bd9Sstevel@tonic-gate * syn1b 331*7c478bd9Sstevel@tonic-gate * syn1b || syn1a 332*7c478bd9Sstevel@tonic-gate */ 333*7c478bd9Sstevel@tonic-gate struct command * 334*7c478bd9Sstevel@tonic-gate syn1a(p1, p2, flags) 335*7c478bd9Sstevel@tonic-gate struct wordent *p1, *p2; 336*7c478bd9Sstevel@tonic-gate int flags; 337*7c478bd9Sstevel@tonic-gate { 338*7c478bd9Sstevel@tonic-gate register struct wordent *p; 339*7c478bd9Sstevel@tonic-gate register struct command *t; 340*7c478bd9Sstevel@tonic-gate register int l = 0; 341*7c478bd9Sstevel@tonic-gate 342*7c478bd9Sstevel@tonic-gate #ifdef TRACE 343*7c478bd9Sstevel@tonic-gate tprintf("TRACE- syn1a()\n"); 344*7c478bd9Sstevel@tonic-gate #endif 345*7c478bd9Sstevel@tonic-gate for (p = p1; p != p2; p = p->next) 346*7c478bd9Sstevel@tonic-gate switch (p->word[0]) { 347*7c478bd9Sstevel@tonic-gate 348*7c478bd9Sstevel@tonic-gate case '(': 349*7c478bd9Sstevel@tonic-gate l++; 350*7c478bd9Sstevel@tonic-gate continue; 351*7c478bd9Sstevel@tonic-gate 352*7c478bd9Sstevel@tonic-gate case ')': 353*7c478bd9Sstevel@tonic-gate l--; 354*7c478bd9Sstevel@tonic-gate continue; 355*7c478bd9Sstevel@tonic-gate 356*7c478bd9Sstevel@tonic-gate case '|': 357*7c478bd9Sstevel@tonic-gate if (p->word[1] != '|') 358*7c478bd9Sstevel@tonic-gate continue; 359*7c478bd9Sstevel@tonic-gate if (l == 0) { 360*7c478bd9Sstevel@tonic-gate t = (struct command *) calloc(1, sizeof (*t)); 361*7c478bd9Sstevel@tonic-gate t->t_dtyp = TOR; 362*7c478bd9Sstevel@tonic-gate t->t_dcar = syn1b(p1, p, flags); 363*7c478bd9Sstevel@tonic-gate t->t_dcdr = syn1a(p->next, p2, flags); 364*7c478bd9Sstevel@tonic-gate t->t_dflg = 0; 365*7c478bd9Sstevel@tonic-gate return (t); 366*7c478bd9Sstevel@tonic-gate } 367*7c478bd9Sstevel@tonic-gate continue; 368*7c478bd9Sstevel@tonic-gate } 369*7c478bd9Sstevel@tonic-gate return (syn1b(p1, p2, flags)); 370*7c478bd9Sstevel@tonic-gate } 371*7c478bd9Sstevel@tonic-gate 372*7c478bd9Sstevel@tonic-gate /* 373*7c478bd9Sstevel@tonic-gate * syn1b 374*7c478bd9Sstevel@tonic-gate * syn2 375*7c478bd9Sstevel@tonic-gate * syn2 && syn1b 376*7c478bd9Sstevel@tonic-gate */ 377*7c478bd9Sstevel@tonic-gate struct command * 378*7c478bd9Sstevel@tonic-gate syn1b(p1, p2, flags) 379*7c478bd9Sstevel@tonic-gate struct wordent *p1, *p2; 380*7c478bd9Sstevel@tonic-gate int flags; 381*7c478bd9Sstevel@tonic-gate { 382*7c478bd9Sstevel@tonic-gate register struct wordent *p; 383*7c478bd9Sstevel@tonic-gate register struct command *t; 384*7c478bd9Sstevel@tonic-gate register int l = 0; 385*7c478bd9Sstevel@tonic-gate 386*7c478bd9Sstevel@tonic-gate #ifdef TRACE 387*7c478bd9Sstevel@tonic-gate tprintf("TRACE- syn1b()\n"); 388*7c478bd9Sstevel@tonic-gate #endif 389*7c478bd9Sstevel@tonic-gate l = 0; 390*7c478bd9Sstevel@tonic-gate for (p = p1; p != p2; p = p->next) 391*7c478bd9Sstevel@tonic-gate switch (p->word[0]) { 392*7c478bd9Sstevel@tonic-gate 393*7c478bd9Sstevel@tonic-gate case '(': 394*7c478bd9Sstevel@tonic-gate l++; 395*7c478bd9Sstevel@tonic-gate continue; 396*7c478bd9Sstevel@tonic-gate 397*7c478bd9Sstevel@tonic-gate case ')': 398*7c478bd9Sstevel@tonic-gate l--; 399*7c478bd9Sstevel@tonic-gate continue; 400*7c478bd9Sstevel@tonic-gate 401*7c478bd9Sstevel@tonic-gate case '&': 402*7c478bd9Sstevel@tonic-gate if (p->word[1] == '&' && l == 0) { 403*7c478bd9Sstevel@tonic-gate t = (struct command *) calloc(1, sizeof (*t)); 404*7c478bd9Sstevel@tonic-gate t->t_dtyp = TAND; 405*7c478bd9Sstevel@tonic-gate t->t_dcar = syn2(p1, p, flags); 406*7c478bd9Sstevel@tonic-gate t->t_dcdr = syn1b(p->next, p2, flags); 407*7c478bd9Sstevel@tonic-gate t->t_dflg = 0; 408*7c478bd9Sstevel@tonic-gate return (t); 409*7c478bd9Sstevel@tonic-gate } 410*7c478bd9Sstevel@tonic-gate continue; 411*7c478bd9Sstevel@tonic-gate } 412*7c478bd9Sstevel@tonic-gate return (syn2(p1, p2, flags)); 413*7c478bd9Sstevel@tonic-gate } 414*7c478bd9Sstevel@tonic-gate 415*7c478bd9Sstevel@tonic-gate /* 416*7c478bd9Sstevel@tonic-gate * syn2 417*7c478bd9Sstevel@tonic-gate * syn3 418*7c478bd9Sstevel@tonic-gate * syn3 | syn2 419*7c478bd9Sstevel@tonic-gate * syn3 |& syn2 420*7c478bd9Sstevel@tonic-gate */ 421*7c478bd9Sstevel@tonic-gate struct command * 422*7c478bd9Sstevel@tonic-gate syn2(p1, p2, flags) 423*7c478bd9Sstevel@tonic-gate struct wordent *p1, *p2; 424*7c478bd9Sstevel@tonic-gate int flags; 425*7c478bd9Sstevel@tonic-gate { 426*7c478bd9Sstevel@tonic-gate register struct wordent *p, *pn; 427*7c478bd9Sstevel@tonic-gate register struct command *t; 428*7c478bd9Sstevel@tonic-gate register int l = 0; 429*7c478bd9Sstevel@tonic-gate int f; 430*7c478bd9Sstevel@tonic-gate 431*7c478bd9Sstevel@tonic-gate #ifdef TRACE 432*7c478bd9Sstevel@tonic-gate tprintf("TRACE- syn2()\n"); 433*7c478bd9Sstevel@tonic-gate #endif 434*7c478bd9Sstevel@tonic-gate for (p = p1; p != p2; p = p->next) 435*7c478bd9Sstevel@tonic-gate switch (p->word[0]) { 436*7c478bd9Sstevel@tonic-gate 437*7c478bd9Sstevel@tonic-gate case '(': 438*7c478bd9Sstevel@tonic-gate l++; 439*7c478bd9Sstevel@tonic-gate continue; 440*7c478bd9Sstevel@tonic-gate 441*7c478bd9Sstevel@tonic-gate case ')': 442*7c478bd9Sstevel@tonic-gate l--; 443*7c478bd9Sstevel@tonic-gate continue; 444*7c478bd9Sstevel@tonic-gate 445*7c478bd9Sstevel@tonic-gate case '|': 446*7c478bd9Sstevel@tonic-gate if (l != 0) 447*7c478bd9Sstevel@tonic-gate continue; 448*7c478bd9Sstevel@tonic-gate t = (struct command *) calloc(1, sizeof (*t)); 449*7c478bd9Sstevel@tonic-gate f = flags | POUT; 450*7c478bd9Sstevel@tonic-gate pn = p->next; 451*7c478bd9Sstevel@tonic-gate if (pn != p2 && pn->word[0] == '&') { 452*7c478bd9Sstevel@tonic-gate f |= PDIAG; 453*7c478bd9Sstevel@tonic-gate t->t_dflg |= FDIAG; 454*7c478bd9Sstevel@tonic-gate } 455*7c478bd9Sstevel@tonic-gate t->t_dtyp = TFIL; 456*7c478bd9Sstevel@tonic-gate t->t_dcar = syn3(p1, p, f); 457*7c478bd9Sstevel@tonic-gate if (pn != p2 && pn->word[0] == '&') 458*7c478bd9Sstevel@tonic-gate p = pn; 459*7c478bd9Sstevel@tonic-gate t->t_dcdr = syn2(p->next, p2, flags | PIN); 460*7c478bd9Sstevel@tonic-gate return (t); 461*7c478bd9Sstevel@tonic-gate } 462*7c478bd9Sstevel@tonic-gate return (syn3(p1, p2, flags)); 463*7c478bd9Sstevel@tonic-gate } 464*7c478bd9Sstevel@tonic-gate 465*7c478bd9Sstevel@tonic-gate tchar RELPAR[] = {'<', '>', '(', ')', 0}; /* "<>()" */ 466*7c478bd9Sstevel@tonic-gate 467*7c478bd9Sstevel@tonic-gate /* 468*7c478bd9Sstevel@tonic-gate * syn3 469*7c478bd9Sstevel@tonic-gate * ( syn0 ) [ < in ] [ > out ] 470*7c478bd9Sstevel@tonic-gate * word word* [ < in ] [ > out ] 471*7c478bd9Sstevel@tonic-gate * KEYWORD ( word* ) word* [ < in ] [ > out ] 472*7c478bd9Sstevel@tonic-gate * 473*7c478bd9Sstevel@tonic-gate * KEYWORD = (@ exit foreach if set switch test while) 474*7c478bd9Sstevel@tonic-gate */ 475*7c478bd9Sstevel@tonic-gate struct command * 476*7c478bd9Sstevel@tonic-gate syn3(p1, p2, flags) 477*7c478bd9Sstevel@tonic-gate struct wordent *p1, *p2; 478*7c478bd9Sstevel@tonic-gate int flags; 479*7c478bd9Sstevel@tonic-gate { 480*7c478bd9Sstevel@tonic-gate register struct wordent *p; 481*7c478bd9Sstevel@tonic-gate struct wordent *lp, *rp; 482*7c478bd9Sstevel@tonic-gate register struct command *t; 483*7c478bd9Sstevel@tonic-gate register int l; 484*7c478bd9Sstevel@tonic-gate tchar **av; 485*7c478bd9Sstevel@tonic-gate int n, c; 486*7c478bd9Sstevel@tonic-gate bool specp = 0; 487*7c478bd9Sstevel@tonic-gate 488*7c478bd9Sstevel@tonic-gate #ifdef TRACE 489*7c478bd9Sstevel@tonic-gate tprintf("TRACE- syn3()\n"); 490*7c478bd9Sstevel@tonic-gate #endif 491*7c478bd9Sstevel@tonic-gate if (p1 != p2) { 492*7c478bd9Sstevel@tonic-gate p = p1; 493*7c478bd9Sstevel@tonic-gate again: 494*7c478bd9Sstevel@tonic-gate switch (srchx(p->word)) { 495*7c478bd9Sstevel@tonic-gate 496*7c478bd9Sstevel@tonic-gate case ZELSE: 497*7c478bd9Sstevel@tonic-gate p = p->next; 498*7c478bd9Sstevel@tonic-gate if (p != p2) 499*7c478bd9Sstevel@tonic-gate goto again; 500*7c478bd9Sstevel@tonic-gate break; 501*7c478bd9Sstevel@tonic-gate 502*7c478bd9Sstevel@tonic-gate case ZEXIT: 503*7c478bd9Sstevel@tonic-gate case ZFOREACH: 504*7c478bd9Sstevel@tonic-gate case ZIF: 505*7c478bd9Sstevel@tonic-gate case ZLET: 506*7c478bd9Sstevel@tonic-gate case ZSET: 507*7c478bd9Sstevel@tonic-gate case ZSWITCH: 508*7c478bd9Sstevel@tonic-gate case ZWHILE: 509*7c478bd9Sstevel@tonic-gate specp = 1; 510*7c478bd9Sstevel@tonic-gate break; 511*7c478bd9Sstevel@tonic-gate } 512*7c478bd9Sstevel@tonic-gate } 513*7c478bd9Sstevel@tonic-gate n = 0; 514*7c478bd9Sstevel@tonic-gate l = 0; 515*7c478bd9Sstevel@tonic-gate for (p = p1; p != p2; p = p->next) 516*7c478bd9Sstevel@tonic-gate switch (p->word[0]) { 517*7c478bd9Sstevel@tonic-gate 518*7c478bd9Sstevel@tonic-gate case '(': 519*7c478bd9Sstevel@tonic-gate if (specp) 520*7c478bd9Sstevel@tonic-gate n++; 521*7c478bd9Sstevel@tonic-gate l++; 522*7c478bd9Sstevel@tonic-gate continue; 523*7c478bd9Sstevel@tonic-gate 524*7c478bd9Sstevel@tonic-gate case ')': 525*7c478bd9Sstevel@tonic-gate if (specp) 526*7c478bd9Sstevel@tonic-gate n++; 527*7c478bd9Sstevel@tonic-gate l--; 528*7c478bd9Sstevel@tonic-gate continue; 529*7c478bd9Sstevel@tonic-gate 530*7c478bd9Sstevel@tonic-gate case '>': 531*7c478bd9Sstevel@tonic-gate case '<': 532*7c478bd9Sstevel@tonic-gate if (l != 0) { 533*7c478bd9Sstevel@tonic-gate if (specp) 534*7c478bd9Sstevel@tonic-gate n++; 535*7c478bd9Sstevel@tonic-gate continue; 536*7c478bd9Sstevel@tonic-gate } 537*7c478bd9Sstevel@tonic-gate if (p->next == p2) 538*7c478bd9Sstevel@tonic-gate continue; 539*7c478bd9Sstevel@tonic-gate if (any(p->next->word[0], RELPAR)) 540*7c478bd9Sstevel@tonic-gate continue; 541*7c478bd9Sstevel@tonic-gate n--; 542*7c478bd9Sstevel@tonic-gate continue; 543*7c478bd9Sstevel@tonic-gate 544*7c478bd9Sstevel@tonic-gate default: 545*7c478bd9Sstevel@tonic-gate if (!specp && l != 0) 546*7c478bd9Sstevel@tonic-gate continue; 547*7c478bd9Sstevel@tonic-gate n++; 548*7c478bd9Sstevel@tonic-gate continue; 549*7c478bd9Sstevel@tonic-gate } 550*7c478bd9Sstevel@tonic-gate if (n < 0) 551*7c478bd9Sstevel@tonic-gate n = 0; 552*7c478bd9Sstevel@tonic-gate t = (struct command *) calloc(1, sizeof (*t)); 553*7c478bd9Sstevel@tonic-gate av = (tchar **) calloc((unsigned) (n + 1), sizeof (tchar **)); 554*7c478bd9Sstevel@tonic-gate t->t_dcom = av; 555*7c478bd9Sstevel@tonic-gate n = 0; 556*7c478bd9Sstevel@tonic-gate if (p2->word[0] == ')') 557*7c478bd9Sstevel@tonic-gate t->t_dflg = FPAR; 558*7c478bd9Sstevel@tonic-gate lp = 0; 559*7c478bd9Sstevel@tonic-gate rp = 0; 560*7c478bd9Sstevel@tonic-gate l = 0; 561*7c478bd9Sstevel@tonic-gate for (p = p1; p != p2; p = p->next) { 562*7c478bd9Sstevel@tonic-gate c = p->word[0]; 563*7c478bd9Sstevel@tonic-gate switch (c) { 564*7c478bd9Sstevel@tonic-gate 565*7c478bd9Sstevel@tonic-gate case '(': 566*7c478bd9Sstevel@tonic-gate if (l == 0) { 567*7c478bd9Sstevel@tonic-gate if (lp != 0 && !specp) 568*7c478bd9Sstevel@tonic-gate seterr("Badly placed ("); 569*7c478bd9Sstevel@tonic-gate lp = p->next; 570*7c478bd9Sstevel@tonic-gate } 571*7c478bd9Sstevel@tonic-gate l++; 572*7c478bd9Sstevel@tonic-gate goto savep; 573*7c478bd9Sstevel@tonic-gate 574*7c478bd9Sstevel@tonic-gate case ')': 575*7c478bd9Sstevel@tonic-gate l--; 576*7c478bd9Sstevel@tonic-gate if (l == 0) 577*7c478bd9Sstevel@tonic-gate rp = p; 578*7c478bd9Sstevel@tonic-gate goto savep; 579*7c478bd9Sstevel@tonic-gate 580*7c478bd9Sstevel@tonic-gate case '>': 581*7c478bd9Sstevel@tonic-gate if (l != 0) 582*7c478bd9Sstevel@tonic-gate goto savep; 583*7c478bd9Sstevel@tonic-gate if (p->word[1] == '>') 584*7c478bd9Sstevel@tonic-gate t->t_dflg |= FCAT; 585*7c478bd9Sstevel@tonic-gate if (p->next != p2 && eq(p->next->word, S_AND /*"&"*/)) { 586*7c478bd9Sstevel@tonic-gate t->t_dflg |= FDIAG, p = p->next; 587*7c478bd9Sstevel@tonic-gate if (flags & (POUT|PDIAG)) 588*7c478bd9Sstevel@tonic-gate goto badout; 589*7c478bd9Sstevel@tonic-gate } 590*7c478bd9Sstevel@tonic-gate if (p->next != p2 && eq(p->next->word, S_EXAS /*"!"*/)) 591*7c478bd9Sstevel@tonic-gate t->t_dflg |= FANY, p = p->next; 592*7c478bd9Sstevel@tonic-gate if (p->next == p2) { 593*7c478bd9Sstevel@tonic-gate missfile: 594*7c478bd9Sstevel@tonic-gate seterr("Missing name for redirect"); 595*7c478bd9Sstevel@tonic-gate continue; 596*7c478bd9Sstevel@tonic-gate } 597*7c478bd9Sstevel@tonic-gate p = p->next; 598*7c478bd9Sstevel@tonic-gate if (any(p->word[0], RELPAR)) 599*7c478bd9Sstevel@tonic-gate goto missfile; 600*7c478bd9Sstevel@tonic-gate if ((flags & POUT) && (flags & PDIAG) == 0 || t->t_drit) 601*7c478bd9Sstevel@tonic-gate badout: 602*7c478bd9Sstevel@tonic-gate seterr("Ambiguous output redirect"); 603*7c478bd9Sstevel@tonic-gate else 604*7c478bd9Sstevel@tonic-gate t->t_drit = savestr(p->word); 605*7c478bd9Sstevel@tonic-gate continue; 606*7c478bd9Sstevel@tonic-gate 607*7c478bd9Sstevel@tonic-gate case '<': 608*7c478bd9Sstevel@tonic-gate if (l != 0) 609*7c478bd9Sstevel@tonic-gate goto savep; 610*7c478bd9Sstevel@tonic-gate if (p->word[1] == '<') 611*7c478bd9Sstevel@tonic-gate t->t_dflg |= FHERE; 612*7c478bd9Sstevel@tonic-gate if (p->next == p2) 613*7c478bd9Sstevel@tonic-gate goto missfile; 614*7c478bd9Sstevel@tonic-gate p = p->next; 615*7c478bd9Sstevel@tonic-gate if (any(p->word[0], RELPAR)) 616*7c478bd9Sstevel@tonic-gate goto missfile; 617*7c478bd9Sstevel@tonic-gate if ((flags & PHERE) && (t->t_dflg & FHERE)) 618*7c478bd9Sstevel@tonic-gate seterr("Can't << within ()'s"); 619*7c478bd9Sstevel@tonic-gate else if ((flags & PIN) || t->t_dlef) 620*7c478bd9Sstevel@tonic-gate seterr("Ambiguous input redirect"); 621*7c478bd9Sstevel@tonic-gate else 622*7c478bd9Sstevel@tonic-gate t->t_dlef = savestr(p->word); 623*7c478bd9Sstevel@tonic-gate continue; 624*7c478bd9Sstevel@tonic-gate 625*7c478bd9Sstevel@tonic-gate savep: 626*7c478bd9Sstevel@tonic-gate if (!specp) 627*7c478bd9Sstevel@tonic-gate continue; 628*7c478bd9Sstevel@tonic-gate default: 629*7c478bd9Sstevel@tonic-gate if (l != 0 && !specp) 630*7c478bd9Sstevel@tonic-gate continue; 631*7c478bd9Sstevel@tonic-gate if (err == 0) 632*7c478bd9Sstevel@tonic-gate av[n] = savestr(p->word); 633*7c478bd9Sstevel@tonic-gate n++; 634*7c478bd9Sstevel@tonic-gate continue; 635*7c478bd9Sstevel@tonic-gate } 636*7c478bd9Sstevel@tonic-gate } 637*7c478bd9Sstevel@tonic-gate if (lp != 0 && !specp) { 638*7c478bd9Sstevel@tonic-gate if (n != 0) 639*7c478bd9Sstevel@tonic-gate seterr("Badly placed ()'s"); 640*7c478bd9Sstevel@tonic-gate t->t_dtyp = TPAR; 641*7c478bd9Sstevel@tonic-gate t->t_dspr = syn0(lp, rp, PHERE); 642*7c478bd9Sstevel@tonic-gate } else { 643*7c478bd9Sstevel@tonic-gate if (n == 0) 644*7c478bd9Sstevel@tonic-gate seterr("Invalid null command"); 645*7c478bd9Sstevel@tonic-gate t->t_dtyp = TCOM; 646*7c478bd9Sstevel@tonic-gate } 647*7c478bd9Sstevel@tonic-gate return (t); 648*7c478bd9Sstevel@tonic-gate } 649*7c478bd9Sstevel@tonic-gate 650*7c478bd9Sstevel@tonic-gate freesyn(t) 651*7c478bd9Sstevel@tonic-gate register struct command *t; 652*7c478bd9Sstevel@tonic-gate { 653*7c478bd9Sstevel@tonic-gate #ifdef TRACE 654*7c478bd9Sstevel@tonic-gate tprintf("TRACE- freesyn()\n"); 655*7c478bd9Sstevel@tonic-gate #endif 656*7c478bd9Sstevel@tonic-gate if (t == 0) 657*7c478bd9Sstevel@tonic-gate return; 658*7c478bd9Sstevel@tonic-gate switch (t->t_dtyp) { 659*7c478bd9Sstevel@tonic-gate 660*7c478bd9Sstevel@tonic-gate case TCOM: 661*7c478bd9Sstevel@tonic-gate blkfree(t->t_dcom); 662*7c478bd9Sstevel@tonic-gate if (t->cfname) 663*7c478bd9Sstevel@tonic-gate xfree(t->cfname); 664*7c478bd9Sstevel@tonic-gate if (t->cargs) 665*7c478bd9Sstevel@tonic-gate chr_blkfree(t->cargs); 666*7c478bd9Sstevel@tonic-gate goto lr; 667*7c478bd9Sstevel@tonic-gate 668*7c478bd9Sstevel@tonic-gate case TPAR: 669*7c478bd9Sstevel@tonic-gate freesyn(t->t_dspr); 670*7c478bd9Sstevel@tonic-gate /* fall into ... */ 671*7c478bd9Sstevel@tonic-gate 672*7c478bd9Sstevel@tonic-gate lr: 673*7c478bd9Sstevel@tonic-gate XFREE(t->t_dlef) 674*7c478bd9Sstevel@tonic-gate XFREE(t->t_drit) 675*7c478bd9Sstevel@tonic-gate break; 676*7c478bd9Sstevel@tonic-gate 677*7c478bd9Sstevel@tonic-gate case TAND: 678*7c478bd9Sstevel@tonic-gate case TOR: 679*7c478bd9Sstevel@tonic-gate case TFIL: 680*7c478bd9Sstevel@tonic-gate case TLST: 681*7c478bd9Sstevel@tonic-gate freesyn(t->t_dcar), freesyn(t->t_dcdr); 682*7c478bd9Sstevel@tonic-gate break; 683*7c478bd9Sstevel@tonic-gate } 684*7c478bd9Sstevel@tonic-gate XFREE( (tchar *)t) 685*7c478bd9Sstevel@tonic-gate } 686*7c478bd9Sstevel@tonic-gate 687*7c478bd9Sstevel@tonic-gate 688*7c478bd9Sstevel@tonic-gate chr_blkfree(vec) 689*7c478bd9Sstevel@tonic-gate register char **vec; 690*7c478bd9Sstevel@tonic-gate { 691*7c478bd9Sstevel@tonic-gate register char **av; 692*7c478bd9Sstevel@tonic-gate 693*7c478bd9Sstevel@tonic-gate for (av = vec; *av; av++) 694*7c478bd9Sstevel@tonic-gate xfree(*av); 695*7c478bd9Sstevel@tonic-gate xfree(vec); 696*7c478bd9Sstevel@tonic-gate } 697