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