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