1: static char *sccsid = "@(#)sh.exp.c 4.1 10/9/80"; 2: 3: #include "sh.h" 4: 5: /* 6: * C shell 7: */ 8: 9: #define IGNORE 1 /* in ignore, it means to ignore value, just parse */ 10: #define NOGLOB 2 /* in ignore, it means not to globone */ 11: 12: #define ADDOP 1 13: #define MULOP 2 14: #define EQOP 4 15: #define RELOP 8 16: #define RESTOP 16 17: #define ANYOP 31 18: 19: #define EQEQ 1 20: #define GTR 2 21: #define LSS 4 22: #define NOTEQ 6 23: #define EQMATCH 7 24: #define NOTEQMATCH 8 25: 26: exp(vp) 27: register char ***vp; 28: { 29: 30: return (exp0(vp, 0)); 31: } 32: 33: exp0(vp, ignore) 34: register char ***vp; 35: bool ignore; 36: { 37: register int p1 = exp1(vp, ignore); 38: 39: #ifdef EDEBUG 40: etraci("exp0 p1", p1, vp); 41: #endif 42: if (**vp && eq(**vp, "||")) { 43: register int p2; 44: 45: (*vp)++; 46: p2 = exp0(vp, (ignore&IGNORE) || p1); 47: #ifdef EDEBUG 48: etraci("exp0 p2", p2, vp); 49: #endif 50: return (p1 || p2); 51: } 52: return (p1); 53: } 54: 55: exp1(vp, ignore) 56: register char ***vp; 57: { 58: register int p1 = exp2(vp, ignore); 59: 60: #ifdef EDEBUG 61: etraci("exp1 p1", p1, vp); 62: #endif 63: if (**vp && eq(**vp, "&&")) { 64: register int p2; 65: 66: (*vp)++; 67: p2 = exp1(vp, (ignore&IGNORE) || !p1); 68: #ifdef EDEBUG 69: etraci("exp1 p2", p2, vp); 70: #endif 71: return (p1 && p2); 72: } 73: return (p1); 74: } 75: 76: exp2(vp, ignore) 77: register char ***vp; 78: bool ignore; 79: { 80: register int p1 = exp2a(vp, ignore); 81: 82: #ifdef EDEBUG 83: etraci("exp3 p1", p1, vp); 84: #endif 85: if (**vp && eq(**vp, "|")) { 86: register int p2; 87: 88: (*vp)++; 89: p2 = exp2(vp, ignore); 90: #ifdef EDEBUG 91: etraci("exp3 p2", p2, vp); 92: #endif 93: return (p1 | p2); 94: } 95: return (p1); 96: } 97: 98: exp2a(vp, ignore) 99: register char ***vp; 100: bool ignore; 101: { 102: register int p1 = exp2b(vp, ignore); 103: 104: #ifdef EDEBUG 105: etraci("exp2a p1", p1, vp); 106: #endif 107: if (**vp && eq(**vp, "^")) { 108: register int p2; 109: 110: (*vp)++; 111: p2 = exp2a(vp, ignore); 112: #ifdef EDEBUG 113: etraci("exp2a p2", p2, vp); 114: #endif 115: return (p1 ^ p2); 116: } 117: return (p1); 118: } 119: 120: exp2b(vp, ignore) 121: register char ***vp; 122: bool ignore; 123: { 124: register int p1 = exp2c(vp, ignore); 125: 126: #ifdef EDEBUG 127: etraci("exp2b p1", p1, vp); 128: #endif 129: if (**vp && eq(**vp, "&")) { 130: register int p2; 131: 132: (*vp)++; 133: p2 = exp2b(vp, ignore); 134: #ifdef EDEBUG 135: etraci("exp2b p2", p2, vp); 136: #endif 137: return (p1 & p2); 138: } 139: return (p1); 140: } 141: 142: exp2c(vp, ignore) 143: register char ***vp; 144: bool ignore; 145: { 146: register char *p1 = exp3(vp, ignore); 147: register char *p2; 148: register int i; 149: 150: #ifdef EDEBUG 151: etracc("exp2c p1", p1, vp); 152: #endif 153: if (i = isa(**vp, EQOP)) { 154: (*vp)++; 155: if (i == EQMATCH || i == NOTEQMATCH) 156: ignore |= NOGLOB; 157: p2 = exp3(vp, ignore); 158: #ifdef EDEBUG 159: etracc("exp2c p2", p2, vp); 160: #endif 161: if (!(ignore&IGNORE)) switch (i) { 162: 163: case EQEQ: 164: i = eq(p1, p2); 165: break; 166: 167: case NOTEQ: 168: i = !eq(p1, p2); 169: break; 170: 171: case EQMATCH: 172: i = Gmatch(p1, p2); 173: break; 174: 175: case NOTEQMATCH: 176: i = !Gmatch(p1, p2); 177: break; 178: } 179: xfree(p1), xfree(p2); 180: return (i); 181: } 182: i = egetn(p1); 183: xfree(p1); 184: return (i); 185: } 186: 187: char * 188: exp3(vp, ignore) 189: register char ***vp; 190: bool ignore; 191: { 192: register char *p1, *p2; 193: register int i; 194: 195: p1 = exp3a(vp, ignore); 196: #ifdef EDEBUG 197: etracc("exp3 p1", p1, vp); 198: #endif 199: if (i = isa(**vp, RELOP)) { 200: (*vp)++; 201: if (**vp && eq(**vp, "=")) 202: i |= 1, (*vp)++; 203: p2 = exp3(vp, ignore); 204: #ifdef EDEBUG 205: etracc("exp3 p2", p2, vp); 206: #endif 207: if (!(ignore&IGNORE)) switch (i) { 208: 209: case GTR: 210: i = egetn(p1) > egetn(p2); 211: break; 212: 213: case GTR|1: 214: i = egetn(p1) >= egetn(p2); 215: break; 216: 217: case LSS: 218: i = egetn(p1) < egetn(p2); 219: break; 220: 221: case LSS|1: 222: i = egetn(p1) <= egetn(p2); 223: break; 224: } 225: xfree(p1), xfree(p2); 226: return (putn(i)); 227: } 228: return (p1); 229: } 230: 231: char * 232: exp3a(vp, ignore) 233: register char ***vp; 234: bool ignore; 235: { 236: register char *p1, *p2, *op; 237: register int i; 238: 239: p1 = exp4(vp, ignore); 240: #ifdef EDEBUG 241: etracc("exp3a p1", p1, vp); 242: #endif 243: op = **vp; 244: if (op && any(op[0], "<>") && op[0] == op[1]) { 245: (*vp)++; 246: p2 = exp3a(vp, ignore); 247: #ifdef EDEBUG 248: etracc("exp3a p2", p2, vp); 249: #endif 250: if (op[0] == '<') 251: i = egetn(p1) << egetn(p2); 252: else 253: i = egetn(p1) >> egetn(p2); 254: xfree(p1), xfree(p2); 255: return (putn(i)); 256: } 257: return (p1); 258: } 259: 260: char * 261: exp4(vp, ignore) 262: register char ***vp; 263: bool ignore; 264: { 265: register char *p1, *p2; 266: register int i = 0; 267: 268: p1 = exp5(vp, ignore); 269: #ifdef EDEBUG 270: etracc("exp4 p1", p1, vp); 271: #endif 272: if (isa(**vp, ADDOP)) { 273: register char *op = *(*vp)++; 274: 275: p2 = exp4(vp, ignore); 276: #ifdef EDEBUG 277: etracc("exp4 p2", p2, vp); 278: #endif 279: if (!(ignore&IGNORE)) switch (op[0]) { 280: 281: case '+': 282: i = egetn(p1) + egetn(p2); 283: break; 284: 285: case '-': 286: i = egetn(p1) - egetn(p2); 287: break; 288: } 289: xfree(p1), xfree(p2); 290: return (putn(i)); 291: } 292: return (p1); 293: } 294: 295: char * 296: exp5(vp, ignore) 297: register char ***vp; 298: bool ignore; 299: { 300: register char *p1, *p2; 301: register int i = 0; 302: 303: p1 = exp6(vp, ignore); 304: #ifdef EDEBUG 305: etracc("exp5 p1", p1, vp); 306: #endif 307: if (isa(**vp, MULOP)) { 308: register char *op = *(*vp)++; 309: 310: p2 = exp5(vp, ignore); 311: #ifdef EDEBUG 312: etracc("exp5 p2", p2, vp); 313: #endif 314: if (!(ignore&IGNORE)) switch (op[0]) { 315: 316: case '*': 317: i = egetn(p1) * egetn(p2); 318: break; 319: 320: case '/': 321: i = egetn(p2); 322: if (i == 0) 323: error("Divide by 0"); 324: i = egetn(p1) / i; 325: break; 326: 327: case '%': 328: i = egetn(p2); 329: if (i == 0) 330: error("Mod by 0"); 331: i = egetn(p1) % i; 332: break; 333: } 334: xfree(p1), xfree(p2); 335: return (putn(i)); 336: } 337: return (p1); 338: } 339: 340: char * 341: exp6(vp, ignore) 342: register char ***vp; 343: { 344: int ccode, i; 345: register char *cp, *dp, *ep; 346: 347: if (eq(**vp, "!")) { 348: (*vp)++; 349: cp = exp6(vp, ignore); 350: #ifdef EDEBUG 351: etracc("exp6 ! cp", cp, vp); 352: #endif 353: i = egetn(cp); 354: xfree(cp); 355: return (putn(!i)); 356: } 357: if (eq(**vp, "~")) { 358: (*vp)++; 359: cp = exp6(vp, ignore); 360: #ifdef EDEBUG 361: etracc("exp6 ~ cp", cp, vp); 362: #endif 363: i = egetn(cp); 364: xfree(cp); 365: return (putn(~i)); 366: } 367: if (eq(**vp, "(")) { 368: (*vp)++; 369: ccode = exp0(vp, ignore); 370: #ifdef EDEBUG 371: etraci("exp6 () ccode", ccode, vp); 372: #endif 373: if (*vp == 0 || **vp == 0 || ***vp != ')') 374: bferr("Expression syntax"); 375: (*vp)++; 376: return (putn(ccode)); 377: } 378: if (eq(**vp, "{")) { 379: register char **v; 380: struct command faket; 381: char *fakecom[2]; 382: 383: faket.t_dtyp = TCOM; 384: faket.t_dflg = 0; 385: faket.t_dcar = faket.t_dcdr = faket.t_dspr = (struct command *)0; 386: faket.t_dcom = fakecom; 387: fakecom[0] = "{ ... }"; 388: fakecom[1] = NOSTR; 389: (*vp)++; 390: v = *vp; 391: for (;;) { 392: if (!**vp) 393: bferr("Missing }"); 394: if (eq(*(*vp)++, "}")) 395: break; 396: } 397: if (ignore&IGNORE) 398: return (""); 399: psavejob(); 400: if (pfork(&faket, -1) == 0) { 401: *--(*vp) = 0; 402: evalav(v); 403: exitstat(); 404: } 405: pwait(); 406: prestjob(); 407: #ifdef EDEBUG 408: etraci("exp6 {} status", egetn(value("status")), vp); 409: #endif 410: return (putn(egetn(value("status")) == 0)); 411: } 412: if (isa(**vp, ANYOP)) 413: return (""); 414: cp = *(*vp)++; 415: if (*cp == '-' && any(cp[1], "erwxfdzo")) { 416: struct stat stb; 417: 418: if (isa(**vp, ANYOP)) 419: bferr("Missing file name"); 420: dp = *(*vp)++; 421: if (ignore&IGNORE) 422: return (""); 423: ep = globone(dp); 424: switch (cp[1]) { 425: 426: case 'r': 427: i = !access(ep, 4); 428: break; 429: 430: case 'w': 431: i = !access(ep, 2); 432: break; 433: 434: case 'x': 435: i = !access(ep, 1); 436: break; 437: 438: default: 439: if (stat(ep, &stb)) { 440: xfree(ep); 441: return ("0"); 442: } 443: switch (cp[1]) { 444: 445: case 'f': 446: i = (stb.st_mode & S_IFMT) == S_IFREG; 447: break; 448: 449: case 'd': 450: i = (stb.st_mode & S_IFMT) == S_IFDIR; 451: break; 452: 453: case 'z': 454: i = stb.st_size == 0; 455: break; 456: 457: case 'e': 458: i = 1; 459: break; 460: 461: case 'o': 462: i = stb.st_uid == uid; 463: break; 464: } 465: } 466: #ifdef EDEBUG 467: etraci("exp6 -? i", i, vp); 468: #endif 469: xfree(ep); 470: return (putn(i)); 471: } 472: #ifdef EDEBUG 473: etracc("exp6 default", cp, vp); 474: #endif 475: return (ignore&NOGLOB ? cp : globone(cp)); 476: } 477: 478: evalav(v) 479: register char **v; 480: { 481: struct wordent paraml; 482: register struct wordent *hp = ¶ml; 483: struct command *t; 484: register struct wordent *wdp = hp; 485: 486: set("status", "0"); 487: hp->prev = hp->next = hp; 488: hp->word = ""; 489: while (*v) { 490: register struct wordent *new = (struct wordent *) calloc(1, sizeof *wdp); 491: 492: new->prev = wdp; 493: new->next = hp; 494: wdp->next = new; 495: wdp = new; 496: wdp->word = savestr(*v++); 497: } 498: hp->prev = wdp; 499: alias(¶ml); 500: t = syntax(paraml.next, ¶ml, 0); 501: if (err) 502: error(err); 503: execute(t, -1); 504: freelex(¶ml), freesyn(t); 505: } 506: 507: isa(cp, what) 508: register char *cp; 509: register int what; 510: { 511: 512: if (cp == 0) 513: return ((what & RESTOP) != 0); 514: if (cp[1] == 0) { 515: if ((what & ADDOP) && any(cp[0], "+-")) 516: return (1); 517: if ((what & MULOP) && any(cp[0], "*/%")) 518: return (1); 519: if ((what & RESTOP) && any(cp[0], "()!~^")) 520: return (1); 521: } 522: if ((what & RESTOP) && (any(cp[0], "|&") || eq(cp, "<<") || eq(cp, ">>"))) 523: return (1); 524: if (what & EQOP) { 525: if (eq(cp, "==")) 526: return (EQEQ); 527: if (eq(cp, "!=")) 528: return (NOTEQ); 529: if (eq(cp, "=~")) 530: return (EQMATCH); 531: if (eq(cp, "!~")) 532: return (NOTEQMATCH); 533: } 534: if (!(what & RELOP)) 535: return (0); 536: if (*cp == '<') 537: return (LSS); 538: if (*cp == '>') 539: return (GTR); 540: return (0); 541: } 542: 543: egetn(cp) 544: register char *cp; 545: { 546: 547: if (*cp && *cp != '-' && !digit(*cp)) 548: bferr("Expression syntax"); 549: return (getn(cp)); 550: } 551: 552: /* Phew! */ 553: 554: #ifdef EDEBUG 555: etraci(str, i, vp) 556: char *str; 557: int i; 558: char ***vp; 559: { 560: 561: printf("%s=%d\t", str, i); 562: blkpr(*vp); 563: printf("\n"); 564: } 565: 566: etracc(str, cp, vp) 567: char *str, *cp; 568: char ***vp; 569: { 570: 571: printf("%s=%s\t", str, cp); 572: blkpr(*vp); 573: printf("\n"); 574: } 575: #endif