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