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