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[] = "@(#)set.c 5.5 (Berkeley) 04/04/91"; 10 #endif /* not lint */ 11 12 #include "sh.h" 13 14 /* 15 * C Shell 16 */ 17 18 doset(v) 19 register char **v; 20 { 21 register char *p; 22 char *vp, op; 23 char **vecp; 24 bool hadsub; 25 int subscr; 26 27 v++; 28 p = *v++; 29 if (p == 0) { 30 prvars(); 31 return; 32 } 33 do { 34 hadsub = 0; 35 for (vp = p; alnum(*p); p++) 36 continue; 37 if (vp == p || !letter(*vp)) 38 goto setsyn; 39 if (*p == '[') { 40 hadsub++; 41 p = getinx(p, &subscr); 42 } 43 if (op = *p) { 44 *p++ = 0; 45 if (*p == 0 && *v && **v == '(') 46 p = *v++; 47 } else if (*v && eq(*v, "=")) { 48 op = '=', v++; 49 if (*v) 50 p = *v++; 51 } 52 if (op && op != '=') 53 setsyn: 54 bferr("Syntax error"); 55 if (eq(p, "(")) { 56 register char **e = v; 57 58 if (hadsub) 59 goto setsyn; 60 for (;;) { 61 if (!*e) 62 bferr("Missing )"); 63 if (**e == ')') 64 break; 65 e++; 66 } 67 p = *e; 68 *e = 0; 69 vecp = saveblk(v); 70 set1(vp, vecp, &shvhed); 71 *e = p; 72 v = e + 1; 73 } else if (hadsub) 74 asx(vp, subscr, savestr(p)); 75 else 76 set(vp, savestr(p)); 77 if (eq(vp, "path")) { 78 exportpath(adrof("path")->vec); 79 dohash(); 80 } else if (eq(vp, "histchars")) { 81 register char *p = value("histchars"); 82 83 HIST = *p++; 84 HISTSUB = *p; 85 } else if (eq(vp, "user")) 86 setenv("USER", value(vp)); 87 else if (eq(vp, "term")) 88 setenv("TERM", value(vp)); 89 else if (eq(vp, "home")) 90 setenv("HOME", value(vp)); 91 #ifdef FILEC 92 else if (eq(vp, "filec")) 93 filec = 1; 94 #endif 95 } while (p = *v++); 96 } 97 98 char * 99 getinx(cp, ip) 100 register char *cp; 101 register int *ip; 102 { 103 104 *ip = 0; 105 *cp++ = 0; 106 while (*cp && digit(*cp)) 107 *ip = *ip * 10 + *cp++ - '0'; 108 if (*cp++ != ']') 109 bferr("Subscript error"); 110 return (cp); 111 } 112 113 asx(vp, subscr, p) 114 char *vp; 115 int subscr; 116 char *p; 117 { 118 register struct varent *v = getvx(vp, subscr); 119 120 xfree(v->vec[subscr - 1]); 121 v->vec[subscr - 1] = globone(p); 122 } 123 124 struct varent * 125 getvx(vp, subscr) 126 char *vp; 127 { 128 register struct varent *v = adrof(vp); 129 130 if (v == 0) 131 udvar(vp); 132 if (subscr < 1 || subscr > blklen(v->vec)) 133 bferr("Subscript out of range"); 134 return (v); 135 } 136 137 char plusplus[2] = { '1', 0 }; 138 139 dolet(v) 140 char **v; 141 { 142 register char *p; 143 char *vp, c, op; 144 bool hadsub; 145 int subscr; 146 147 v++; 148 p = *v++; 149 if (p == 0) { 150 prvars(); 151 return; 152 } 153 do { 154 hadsub = 0; 155 for (vp = p; alnum(*p); p++) 156 continue; 157 if (vp == p || !letter(*vp)) 158 goto letsyn; 159 if (*p == '[') { 160 hadsub++; 161 p = getinx(p, &subscr); 162 } 163 if (*p == 0 && *v) 164 p = *v++; 165 if (op = *p) 166 *p++ = 0; 167 else 168 goto letsyn; 169 vp = savestr(vp); 170 if (op == '=') { 171 c = '='; 172 p = xset(p, &v); 173 } else { 174 c = *p++; 175 if (index("+-", c)) { 176 if (c != op || *p) 177 goto letsyn; 178 p = plusplus; 179 } else { 180 if (index("<>", op)) { 181 if (c != op) 182 goto letsyn; 183 c = *p++; 184 letsyn: 185 bferr("Syntax error"); 186 } 187 if (c != '=') 188 goto letsyn; 189 p = xset(p, &v); 190 } 191 } 192 if (op == '=') 193 if (hadsub) 194 asx(vp, subscr, p); 195 else 196 set(vp, p); 197 else 198 if (hadsub) 199 #ifndef V6 200 /* avoid bug in vax CC */ 201 { 202 struct varent *gv = getvx(vp, subscr); 203 204 asx(vp, subscr, operate(op, gv->vec[subscr - 1], p)); 205 } 206 #else 207 asx(vp, subscr, operate(op, getvx(vp, subscr)->vec[subscr - 1], p)); 208 #endif 209 else 210 set(vp, operate(op, value(vp), p)); 211 if (eq(vp, "path")) { 212 exportpath(adrof("path")->vec); 213 dohash(); 214 } 215 XFREE(vp) 216 if (c != '=') 217 XFREE(p) 218 } while (p = *v++); 219 } 220 221 char * 222 xset(cp, vp) 223 char *cp, ***vp; 224 { 225 register char *dp; 226 227 if (*cp) { 228 dp = savestr(cp); 229 --(*vp); 230 xfree(**vp); 231 **vp = dp; 232 } 233 return (putn(exp(vp))); 234 } 235 236 char * 237 operate(op, vp, p) 238 char op, *vp, *p; 239 { 240 char opr[2]; 241 char *vec[5]; 242 register char **v = vec; 243 char **vecp = v; 244 register int i; 245 246 if (op != '=') { 247 if (*vp) 248 *v++ = vp; 249 opr[0] = op; 250 opr[1] = 0; 251 *v++ = opr; 252 if (op == '<' || op == '>') 253 *v++ = opr; 254 } 255 *v++ = p; 256 *v++ = 0; 257 i = exp(&vecp); 258 if (*vecp) 259 bferr("Expression syntax"); 260 return (putn(i)); 261 } 262 263 static char *putp; 264 265 char * 266 putn(n) 267 register int n; 268 { 269 static char number[15]; 270 271 putp = number; 272 if (n < 0) { 273 n = -n; 274 *putp++ = '-'; 275 } 276 if (sizeof (int) == 2 && n == -32768) { 277 *putp++ = '3'; 278 n = 2768; 279 #ifdef pdp11 280 } 281 #else 282 } else if (sizeof (int) == 4 && n == -2147483648) { 283 *putp++ = '2'; 284 n = 147483648; 285 } 286 #endif 287 putn1(n); 288 *putp = 0; 289 return (savestr(number)); 290 } 291 292 putn1(n) 293 register int n; 294 { 295 if (n > 9) 296 putn1(n / 10); 297 *putp++ = n % 10 + '0'; 298 } 299 300 getn(cp) 301 register char *cp; 302 { 303 register int n; 304 int sign; 305 306 sign = 0; 307 if (cp[0] == '+' && cp[1]) 308 cp++; 309 if (*cp == '-') { 310 sign++; 311 cp++; 312 if (!digit(*cp)) 313 goto badnum; 314 } 315 n = 0; 316 while (digit(*cp)) 317 n = n * 10 + *cp++ - '0'; 318 if (*cp) 319 goto badnum; 320 return (sign ? -n : n); 321 badnum: 322 bferr("Badly formed number"); 323 return (0); 324 } 325 326 char * 327 value1(var, head) 328 char *var; 329 struct varent *head; 330 { 331 register struct varent *vp; 332 333 vp = adrof1(var, head); 334 return (vp == 0 || vp->vec[0] == 0 ? "" : vp->vec[0]); 335 } 336 337 struct varent * 338 madrof(pat, vp) 339 char *pat; 340 register struct varent *vp; 341 { 342 register struct varent *vp1; 343 344 for (; vp; vp = vp->v_right) { 345 if (vp->v_left && (vp1 = madrof(pat, vp->v_left))) 346 return vp1; 347 if (Gmatch(vp->v_name, pat)) 348 return vp; 349 } 350 return vp; 351 } 352 353 struct varent * 354 adrof1(name, v) 355 register char *name; 356 register struct varent *v; 357 { 358 register cmp; 359 360 v = v->v_left; 361 while (v && ((cmp = *name - *v->v_name) || 362 (cmp = strcmp(name, v->v_name)))) 363 if (cmp < 0) 364 v = v->v_left; 365 else 366 v = v->v_right; 367 return v; 368 } 369 370 /* 371 * The caller is responsible for putting value in a safe place 372 */ 373 set(var, val) 374 char *var, *val; 375 { 376 register char **vec = (char **) xalloc(2 * sizeof (char **)); 377 378 vec[0] = onlyread(val) ? savestr(val) : val; 379 vec[1] = 0; 380 set1(var, vec, &shvhed); 381 } 382 383 set1(var, vec, head) 384 char *var, **vec; 385 struct varent *head; 386 { 387 register char **oldv = vec; 388 389 gflag = 0; tglob(oldv); 390 if (gflag) { 391 vec = globall(oldv); 392 if (vec == 0) { 393 bferr("No match"); 394 blkfree(oldv); 395 return; 396 } 397 blkfree(oldv); 398 gargv = 0; 399 } 400 setq(var, vec, head); 401 } 402 403 setq(name, vec, p) 404 char *name, **vec; 405 register struct varent *p; 406 { 407 register struct varent *c; 408 register f; 409 410 f = 0; /* tree hangs off the header's left link */ 411 while (c = p->v_link[f]) { 412 if ((f = *name - *c->v_name) == 0 && 413 (f = strcmp(name, c->v_name)) == 0) { 414 blkfree(c->vec); 415 goto found; 416 } 417 p = c; 418 f = f > 0; 419 } 420 p->v_link[f] = c = (struct varent *)xalloc(sizeof (struct varent)); 421 c->v_name = savestr(name); 422 c->v_bal = 0; 423 c->v_left = c->v_right = 0; 424 c->v_parent = p; 425 balance(p, f, 0); 426 found: 427 trim(c->vec = vec); 428 } 429 430 unset(v) 431 char *v[]; 432 { 433 434 unset1(v, &shvhed); 435 if (adrof("histchars") == 0) { 436 HIST = '!'; 437 HISTSUB = '^'; 438 } 439 #ifdef FILEC 440 if (adrof("filec") == 0) 441 filec = 0; 442 #endif 443 } 444 445 unset1(v, head) 446 register char *v[]; 447 struct varent *head; 448 { 449 register struct varent *vp; 450 register int cnt; 451 452 while (*++v) { 453 cnt = 0; 454 while (vp = madrof(*v, head->v_left)) 455 unsetv1(vp), cnt++; 456 if (cnt == 0) 457 setname(*v); 458 } 459 } 460 461 unsetv(var) 462 char *var; 463 { 464 register struct varent *vp; 465 466 if ((vp = adrof1(var, &shvhed)) == 0) 467 udvar(var); 468 unsetv1(vp); 469 } 470 471 unsetv1(p) 472 register struct varent *p; 473 { 474 register struct varent *c, *pp; 475 register f; 476 477 /* 478 * Free associated memory first to avoid complications. 479 */ 480 blkfree(p->vec); 481 XFREE(p->v_name); 482 /* 483 * If p is missing one child, then we can move the other 484 * into where p is. Otherwise, we find the predecessor 485 * of p, which is guaranteed to have no right child, copy 486 * it into p, and move it's left child into it. 487 */ 488 if (p->v_right == 0) 489 c = p->v_left; 490 else if (p->v_left == 0) 491 c = p->v_right; 492 else { 493 for (c = p->v_left; c->v_right; c = c->v_right) 494 ; 495 p->v_name = c->v_name; 496 p->vec = c->vec; 497 p = c; 498 c = p->v_left; 499 } 500 /* 501 * Move c into where p is. 502 */ 503 pp = p->v_parent; 504 f = pp->v_right == p; 505 if (pp->v_link[f] = c) 506 c->v_parent = pp; 507 /* 508 * Free the deleted node, and rebalance. 509 */ 510 XFREE((char *)p); 511 balance(pp, f, 1); 512 } 513 514 setNS(cp) 515 char *cp; 516 { 517 518 set(cp, ""); 519 } 520 521 shift(v) 522 register char **v; 523 { 524 register struct varent *argv; 525 register char *name; 526 527 v++; 528 name = *v; 529 if (name == 0) 530 name = "argv"; 531 else 532 (void) strip(name); 533 argv = adrof(name); 534 if (argv == 0) 535 udvar(name); 536 if (argv->vec[0] == 0) 537 bferr("No more words"); 538 lshift(argv->vec, 1); 539 } 540 541 exportpath(val) 542 char **val; 543 { 544 char exppath[BUFSIZ]; 545 546 exppath[0] = 0; 547 if (val) 548 while (*val) { 549 if (strlen(*val) + strlen(exppath) + 2 > BUFSIZ) { 550 printf("Warning: ridiculously long PATH truncated\n"); 551 break; 552 } 553 (void) strcat(exppath, *val++); 554 if (*val == 0 || eq(*val, ")")) 555 break; 556 (void) strcat(exppath, ":"); 557 } 558 setenv("PATH", exppath); 559 } 560 561 /* macros to do single rotations on node p */ 562 #define rright(p) (\ 563 t = (p)->v_left,\ 564 (t)->v_parent = (p)->v_parent,\ 565 ((p)->v_left = t->v_right) ? (t->v_right->v_parent = (p)) : 0,\ 566 (t->v_right = (p))->v_parent = t,\ 567 (p) = t) 568 #define rleft(p) (\ 569 t = (p)->v_right,\ 570 (t)->v_parent = (p)->v_parent,\ 571 ((p)->v_right = t->v_left) ? (t->v_left->v_parent = (p)) : 0,\ 572 (t->v_left = (p))->v_parent = t,\ 573 (p) = t) 574 575 /* 576 * Rebalance a tree, starting at p and up. 577 * F == 0 means we've come from p's left child. 578 * D == 1 means we've just done a delete, otherwise an insert. 579 */ 580 balance(p, f, d) 581 register struct varent *p; 582 register f; 583 { 584 register struct varent *pp; 585 register struct varent *t; /* used by the rotate macros */ 586 register ff; 587 588 /* 589 * Ok, from here on, p is the node we're operating on; 590 * pp is it's parent; f is the branch of p from which we have come; 591 * ff is the branch of pp which is p. 592 */ 593 for (; pp = p->v_parent; p = pp, f = ff) { 594 ff = pp->v_right == p; 595 if (f ^ d) { /* right heavy */ 596 switch (p->v_bal) { 597 case -1: /* was left heavy */ 598 p->v_bal = 0; 599 break; 600 case 0: /* was balanced */ 601 p->v_bal = 1; 602 break; 603 case 1: /* was already right heavy */ 604 switch (p->v_right->v_bal) { 605 case 1: /* sigle rotate */ 606 pp->v_link[ff] = rleft(p); 607 p->v_left->v_bal = 0; 608 p->v_bal = 0; 609 break; 610 case 0: /* single rotate */ 611 pp->v_link[ff] = rleft(p); 612 p->v_left->v_bal = 1; 613 p->v_bal = -1; 614 break; 615 case -1: /* double rotate */ 616 rright(p->v_right); 617 pp->v_link[ff] = rleft(p); 618 p->v_left->v_bal = 619 p->v_bal < 1 ? 0 : -1; 620 p->v_right->v_bal = 621 p->v_bal > -1 ? 0 : 1; 622 p->v_bal = 0; 623 break; 624 } 625 break; 626 } 627 } else { /* left heavy */ 628 switch (p->v_bal) { 629 case 1: /* was right heavy */ 630 p->v_bal = 0; 631 break; 632 case 0: /* was balanced */ 633 p->v_bal = -1; 634 break; 635 case -1: /* was already left heavy */ 636 switch (p->v_left->v_bal) { 637 case -1: /* single rotate */ 638 pp->v_link[ff] = rright(p); 639 p->v_right->v_bal = 0; 640 p->v_bal = 0; 641 break; 642 case 0: /* signle rotate */ 643 pp->v_link[ff] = rright(p); 644 p->v_right->v_bal = -1; 645 p->v_bal = 1; 646 break; 647 case 1: /* double rotate */ 648 rleft(p->v_left); 649 pp->v_link[ff] = rright(p); 650 p->v_left->v_bal = 651 p->v_bal < 1 ? 0 : -1; 652 p->v_right->v_bal = 653 p->v_bal > -1 ? 0 : 1; 654 p->v_bal = 0; 655 break; 656 } 657 break; 658 } 659 } 660 /* 661 * If from insert, then we terminate when p is balanced. 662 * If from delete, then we terminate when p is unbalanced. 663 */ 664 if ((p->v_bal == 0) ^ d) 665 break; 666 } 667 } 668 669 plist(p) 670 register struct varent *p; 671 { 672 register struct varent *c; 673 register len; 674 675 if (setintr) 676 (void) sigsetmask(sigblock(0) & ~ sigmask(SIGINT)); 677 for (;;) { 678 while (p->v_left) 679 p = p->v_left; 680 x: 681 if (p->v_parent == 0) /* is it the header? */ 682 return; 683 len = blklen(p->vec); 684 printf(p->v_name); 685 cshputchar('\t'); 686 if (len != 1) 687 cshputchar('('); 688 blkpr(p->vec); 689 if (len != 1) 690 cshputchar(')'); 691 cshputchar('\n'); 692 if (p->v_right) { 693 p = p->v_right; 694 continue; 695 } 696 do { 697 c = p; 698 p = p->v_parent; 699 } while (p->v_right == c); 700 goto x; 701 } 702 } 703