1*6685Smckusick /* cmd.c 4.1 82/05/07 */ 2*6685Smckusick 3*6685Smckusick # 4*6685Smckusick /* 5*6685Smckusick * UNIX shell 6*6685Smckusick * 7*6685Smckusick * S. R. Bourne 8*6685Smckusick * Bell Telephone Laboratories 9*6685Smckusick * 10*6685Smckusick */ 11*6685Smckusick 12*6685Smckusick #include "defs.h" 13*6685Smckusick #include "sym.h" 14*6685Smckusick 15*6685Smckusick PROC IOPTR inout(); 16*6685Smckusick PROC VOID chkword(); 17*6685Smckusick PROC VOID chksym(); 18*6685Smckusick PROC TREPTR term(); 19*6685Smckusick PROC TREPTR makelist(); 20*6685Smckusick PROC TREPTR list(); 21*6685Smckusick PROC REGPTR syncase(); 22*6685Smckusick PROC TREPTR item(); 23*6685Smckusick PROC VOID skipnl(); 24*6685Smckusick PROC VOID prsym(); 25*6685Smckusick PROC VOID synbad(); 26*6685Smckusick 27*6685Smckusick 28*6685Smckusick /* ======== command line decoding ========*/ 29*6685Smckusick 30*6685Smckusick 31*6685Smckusick 32*6685Smckusick 33*6685Smckusick TREPTR makefork(flgs, i) 34*6685Smckusick INT flgs; 35*6685Smckusick TREPTR i; 36*6685Smckusick { 37*6685Smckusick REG TREPTR t; 38*6685Smckusick 39*6685Smckusick t=getstak(FORKTYPE); 40*6685Smckusick t->forktyp=flgs|TFORK; t->forktre=i; t->forkio=0; 41*6685Smckusick return(t); 42*6685Smckusick } 43*6685Smckusick 44*6685Smckusick LOCAL TREPTR makelist(type,i,r) 45*6685Smckusick INT type; 46*6685Smckusick TREPTR i, r; 47*6685Smckusick { 48*6685Smckusick REG TREPTR t; 49*6685Smckusick 50*6685Smckusick IF i==0 ORF r==0 51*6685Smckusick THEN synbad(); 52*6685Smckusick ELSE t = getstak(LSTTYPE); 53*6685Smckusick t->lsttyp = type; 54*6685Smckusick t->lstlef = i; t->lstrit = r; 55*6685Smckusick FI 56*6685Smckusick return(t); 57*6685Smckusick } 58*6685Smckusick 59*6685Smckusick /* 60*6685Smckusick * cmd 61*6685Smckusick * empty 62*6685Smckusick * list 63*6685Smckusick * list & [ cmd ] 64*6685Smckusick * list [ ; cmd ] 65*6685Smckusick */ 66*6685Smckusick 67*6685Smckusick TREPTR cmd(sym,flg) 68*6685Smckusick REG INT sym; 69*6685Smckusick INT flg; 70*6685Smckusick { 71*6685Smckusick REG TREPTR i, e; 72*6685Smckusick 73*6685Smckusick i = list(flg); 74*6685Smckusick 75*6685Smckusick IF wdval==NL 76*6685Smckusick THEN IF flg&NLFLG 77*6685Smckusick THEN wdval=';'; chkpr(NL); 78*6685Smckusick FI 79*6685Smckusick ELIF i==0 ANDF (flg&MTFLG)==0 80*6685Smckusick THEN synbad(); 81*6685Smckusick FI 82*6685Smckusick 83*6685Smckusick SWITCH wdval IN 84*6685Smckusick 85*6685Smckusick case '&': 86*6685Smckusick IF i 87*6685Smckusick THEN i = makefork(FINT|FPRS|FAMP, i); 88*6685Smckusick ELSE synbad(); 89*6685Smckusick FI 90*6685Smckusick 91*6685Smckusick case ';': 92*6685Smckusick IF e=cmd(sym,flg|MTFLG) 93*6685Smckusick THEN i=makelist(TLST, i, e); 94*6685Smckusick FI 95*6685Smckusick break; 96*6685Smckusick 97*6685Smckusick case EOFSYM: 98*6685Smckusick IF sym==NL 99*6685Smckusick THEN break; 100*6685Smckusick FI 101*6685Smckusick 102*6685Smckusick default: 103*6685Smckusick IF sym 104*6685Smckusick THEN chksym(sym); 105*6685Smckusick FI 106*6685Smckusick 107*6685Smckusick ENDSW 108*6685Smckusick return(i); 109*6685Smckusick } 110*6685Smckusick 111*6685Smckusick /* 112*6685Smckusick * list 113*6685Smckusick * term 114*6685Smckusick * list && term 115*6685Smckusick * list || term 116*6685Smckusick */ 117*6685Smckusick 118*6685Smckusick LOCAL TREPTR list(flg) 119*6685Smckusick { 120*6685Smckusick REG TREPTR r; 121*6685Smckusick REG INT b; 122*6685Smckusick 123*6685Smckusick r = term(flg); 124*6685Smckusick WHILE r ANDF ((b=(wdval==ANDFSYM)) ORF wdval==ORFSYM) 125*6685Smckusick DO r = makelist((b ? TAND : TORF), r, term(NLFLG)); 126*6685Smckusick OD 127*6685Smckusick return(r); 128*6685Smckusick } 129*6685Smckusick 130*6685Smckusick /* 131*6685Smckusick * term 132*6685Smckusick * item 133*6685Smckusick * item |^ term 134*6685Smckusick */ 135*6685Smckusick 136*6685Smckusick LOCAL TREPTR term(flg) 137*6685Smckusick { 138*6685Smckusick REG TREPTR t; 139*6685Smckusick 140*6685Smckusick reserv++; 141*6685Smckusick IF flg&NLFLG 142*6685Smckusick THEN skipnl(); 143*6685Smckusick ELSE word(); 144*6685Smckusick FI 145*6685Smckusick 146*6685Smckusick IF (t=item(TRUE)) ANDF (wdval=='^' ORF wdval=='|') 147*6685Smckusick THEN return(makelist(TFIL, makefork(FPOU,t), makefork(FPIN|FPCL,term(NLFLG)))); 148*6685Smckusick ELSE return(t); 149*6685Smckusick FI 150*6685Smckusick } 151*6685Smckusick 152*6685Smckusick LOCAL REGPTR syncase(esym) 153*6685Smckusick REG INT esym; 154*6685Smckusick { 155*6685Smckusick skipnl(); 156*6685Smckusick IF wdval==esym 157*6685Smckusick THEN return(0); 158*6685Smckusick ELSE REG REGPTR r=getstak(REGTYPE); 159*6685Smckusick r->regptr=0; 160*6685Smckusick LOOP wdarg->argnxt=r->regptr; 161*6685Smckusick r->regptr=wdarg; 162*6685Smckusick IF wdval ORF ( word()!=')' ANDF wdval!='|' ) 163*6685Smckusick THEN synbad(); 164*6685Smckusick FI 165*6685Smckusick IF wdval=='|' 166*6685Smckusick THEN word(); 167*6685Smckusick ELSE break; 168*6685Smckusick FI 169*6685Smckusick POOL 170*6685Smckusick r->regcom=cmd(0,NLFLG|MTFLG); 171*6685Smckusick IF wdval==ECSYM 172*6685Smckusick THEN r->regnxt=syncase(esym); 173*6685Smckusick ELSE chksym(esym); 174*6685Smckusick r->regnxt=0; 175*6685Smckusick FI 176*6685Smckusick return(r); 177*6685Smckusick FI 178*6685Smckusick } 179*6685Smckusick 180*6685Smckusick /* 181*6685Smckusick * item 182*6685Smckusick * 183*6685Smckusick * ( cmd ) [ < in ] [ > out ] 184*6685Smckusick * word word* [ < in ] [ > out ] 185*6685Smckusick * if ... then ... else ... fi 186*6685Smckusick * for ... while ... do ... done 187*6685Smckusick * case ... in ... esac 188*6685Smckusick * begin ... end 189*6685Smckusick */ 190*6685Smckusick 191*6685Smckusick LOCAL TREPTR item(flag) 192*6685Smckusick BOOL flag; 193*6685Smckusick { 194*6685Smckusick REG TREPTR t; 195*6685Smckusick REG IOPTR io; 196*6685Smckusick 197*6685Smckusick IF flag 198*6685Smckusick THEN io=inout((IOPTR)0); 199*6685Smckusick ELSE io=0; 200*6685Smckusick FI 201*6685Smckusick 202*6685Smckusick SWITCH wdval IN 203*6685Smckusick 204*6685Smckusick case CASYM: 205*6685Smckusick BEGIN 206*6685Smckusick t=getstak(SWTYPE); 207*6685Smckusick chkword(); 208*6685Smckusick t->swarg=wdarg->argval; 209*6685Smckusick skipnl(); chksym(INSYM|BRSYM); 210*6685Smckusick t->swlst=syncase(wdval==INSYM?ESSYM:KTSYM); 211*6685Smckusick t->swtyp=TSW; 212*6685Smckusick break; 213*6685Smckusick END 214*6685Smckusick 215*6685Smckusick case IFSYM: 216*6685Smckusick BEGIN 217*6685Smckusick REG INT w; 218*6685Smckusick t=getstak(IFTYPE); 219*6685Smckusick t->iftyp=TIF; 220*6685Smckusick t->iftre=cmd(THSYM,NLFLG); 221*6685Smckusick t->thtre=cmd(ELSYM|FISYM|EFSYM,NLFLG); 222*6685Smckusick t->eltre=((w=wdval)==ELSYM ? cmd(FISYM,NLFLG) : (w==EFSYM ? (wdval=IFSYM, item(0)) : 0)); 223*6685Smckusick IF w==EFSYM THEN return(t) FI 224*6685Smckusick break; 225*6685Smckusick END 226*6685Smckusick 227*6685Smckusick case FORSYM: 228*6685Smckusick BEGIN 229*6685Smckusick t=getstak(FORTYPE); 230*6685Smckusick t->fortyp=TFOR; 231*6685Smckusick t->forlst=0; 232*6685Smckusick chkword(); 233*6685Smckusick t->fornam=wdarg->argval; 234*6685Smckusick IF skipnl()==INSYM 235*6685Smckusick THEN chkword(); 236*6685Smckusick t->forlst=item(0); 237*6685Smckusick IF wdval!=NL ANDF wdval!=';' 238*6685Smckusick THEN synbad(); 239*6685Smckusick FI 240*6685Smckusick chkpr(wdval); skipnl(); 241*6685Smckusick FI 242*6685Smckusick chksym(DOSYM|BRSYM); 243*6685Smckusick t->fortre=cmd(wdval==DOSYM?ODSYM:KTSYM,NLFLG); 244*6685Smckusick break; 245*6685Smckusick END 246*6685Smckusick 247*6685Smckusick case WHSYM: 248*6685Smckusick case UNSYM: 249*6685Smckusick BEGIN 250*6685Smckusick t=getstak(WHTYPE); 251*6685Smckusick t->whtyp=(wdval==WHSYM ? TWH : TUN); 252*6685Smckusick t->whtre = cmd(DOSYM,NLFLG); 253*6685Smckusick t->dotre = cmd(ODSYM,NLFLG); 254*6685Smckusick break; 255*6685Smckusick END 256*6685Smckusick 257*6685Smckusick case BRSYM: 258*6685Smckusick t=cmd(KTSYM,NLFLG); 259*6685Smckusick break; 260*6685Smckusick 261*6685Smckusick case '(': 262*6685Smckusick BEGIN 263*6685Smckusick REG PARPTR p; 264*6685Smckusick p=getstak(PARTYPE); 265*6685Smckusick p->partre=cmd(')',NLFLG); 266*6685Smckusick p->partyp=TPAR; 267*6685Smckusick t=makefork(0,p); 268*6685Smckusick break; 269*6685Smckusick END 270*6685Smckusick 271*6685Smckusick default: 272*6685Smckusick IF io==0 273*6685Smckusick THEN return(0); 274*6685Smckusick FI 275*6685Smckusick 276*6685Smckusick case 0: 277*6685Smckusick BEGIN 278*6685Smckusick REG ARGPTR argp; 279*6685Smckusick REG ARGPTR *argtail; 280*6685Smckusick REG ARGPTR *argset=0; 281*6685Smckusick INT keywd=1; 282*6685Smckusick t=getstak(COMTYPE); 283*6685Smckusick t->comio=io; /*initial io chain*/ 284*6685Smckusick argtail = &(t->comarg); 285*6685Smckusick WHILE wdval==0 286*6685Smckusick DO argp = wdarg; 287*6685Smckusick IF wdset ANDF keywd 288*6685Smckusick THEN argp->argnxt=argset; argset=argp; 289*6685Smckusick ELSE *argtail=argp; argtail = &(argp->argnxt); keywd=flags&keyflg; 290*6685Smckusick FI 291*6685Smckusick word(); 292*6685Smckusick IF flag 293*6685Smckusick THEN t->comio=inout(t->comio); 294*6685Smckusick FI 295*6685Smckusick OD 296*6685Smckusick 297*6685Smckusick t->comtyp=TCOM; t->comset=argset; *argtail=0; 298*6685Smckusick return(t); 299*6685Smckusick END 300*6685Smckusick 301*6685Smckusick ENDSW 302*6685Smckusick reserv++; word(); 303*6685Smckusick IF io=inout(io) 304*6685Smckusick THEN t=makefork(0,t); t->treio=io; 305*6685Smckusick FI 306*6685Smckusick return(t); 307*6685Smckusick } 308*6685Smckusick 309*6685Smckusick 310*6685Smckusick LOCAL VOID skipnl() 311*6685Smckusick { 312*6685Smckusick WHILE (reserv++, word()==NL) DO chkpr(NL) OD 313*6685Smckusick return(wdval); 314*6685Smckusick } 315*6685Smckusick 316*6685Smckusick LOCAL IOPTR inout(lastio) 317*6685Smckusick IOPTR lastio; 318*6685Smckusick { 319*6685Smckusick REG INT iof; 320*6685Smckusick REG IOPTR iop; 321*6685Smckusick REG CHAR c; 322*6685Smckusick 323*6685Smckusick iof=wdnum; 324*6685Smckusick 325*6685Smckusick SWITCH wdval IN 326*6685Smckusick 327*6685Smckusick case DOCSYM: 328*6685Smckusick iof |= IODOC; break; 329*6685Smckusick 330*6685Smckusick case APPSYM: 331*6685Smckusick case '>': 332*6685Smckusick IF wdnum==0 THEN iof |= 1 FI 333*6685Smckusick iof |= IOPUT; 334*6685Smckusick IF wdval==APPSYM 335*6685Smckusick THEN iof |= IOAPP; break; 336*6685Smckusick FI 337*6685Smckusick 338*6685Smckusick case '<': 339*6685Smckusick IF (c=nextc(0))=='&' 340*6685Smckusick THEN iof |= IOMOV; 341*6685Smckusick ELIF c=='>' 342*6685Smckusick THEN iof |= IORDW; 343*6685Smckusick ELSE peekc=c|MARK; 344*6685Smckusick FI 345*6685Smckusick break; 346*6685Smckusick 347*6685Smckusick default: 348*6685Smckusick return(lastio); 349*6685Smckusick ENDSW 350*6685Smckusick 351*6685Smckusick chkword(); 352*6685Smckusick iop=getstak(IOTYPE); iop->ioname=wdarg->argval; iop->iofile=iof; 353*6685Smckusick IF iof&IODOC 354*6685Smckusick THEN iop->iolst=iopend; iopend=iop; 355*6685Smckusick FI 356*6685Smckusick word(); iop->ionxt=inout(lastio); 357*6685Smckusick return(iop); 358*6685Smckusick } 359*6685Smckusick 360*6685Smckusick LOCAL VOID chkword() 361*6685Smckusick { 362*6685Smckusick IF word() 363*6685Smckusick THEN synbad(); 364*6685Smckusick FI 365*6685Smckusick } 366*6685Smckusick 367*6685Smckusick LOCAL VOID chksym(sym) 368*6685Smckusick { 369*6685Smckusick REG INT x = sym&wdval; 370*6685Smckusick IF ((x&SYMFLG) ? x : sym) != wdval 371*6685Smckusick THEN synbad(); 372*6685Smckusick FI 373*6685Smckusick } 374*6685Smckusick 375*6685Smckusick LOCAL VOID prsym(sym) 376*6685Smckusick { 377*6685Smckusick IF sym&SYMFLG 378*6685Smckusick THEN REG SYSPTR sp=reserved; 379*6685Smckusick WHILE sp->sysval 380*6685Smckusick ANDF sp->sysval!=sym 381*6685Smckusick DO sp++ OD 382*6685Smckusick prs(sp->sysnam); 383*6685Smckusick ELIF sym==EOFSYM 384*6685Smckusick THEN prs(endoffile); 385*6685Smckusick ELSE IF sym&SYMREP THEN prc(sym) FI 386*6685Smckusick IF sym==NL 387*6685Smckusick THEN prs("newline"); 388*6685Smckusick ELSE prc(sym); 389*6685Smckusick FI 390*6685Smckusick FI 391*6685Smckusick } 392*6685Smckusick 393*6685Smckusick LOCAL VOID synbad() 394*6685Smckusick { 395*6685Smckusick prp(); prs(synmsg); 396*6685Smckusick IF (flags&ttyflg)==0 397*6685Smckusick THEN prs(atline); prn(standin->flin); 398*6685Smckusick FI 399*6685Smckusick prs(colon); 400*6685Smckusick prc(LQ); 401*6685Smckusick IF wdval 402*6685Smckusick THEN prsym(wdval); 403*6685Smckusick ELSE prs(wdarg->argval); 404*6685Smckusick FI 405*6685Smckusick prc(RQ); prs(unexpected); 406*6685Smckusick newline(); 407*6685Smckusick exitsh(SYNBAD); 408*6685Smckusick } 409