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 #ifndef lint 8 static char *sccsid = "@(#)exp.c 5.3 (Berkeley) 06/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 597