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