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 = "@(#)sh.set.c 5.2 (Berkeley) 6/6/85"; 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: putchar('\t'); 685: if (len != 1) 686: putchar('('); 687: blkpr(p->vec); 688: if (len != 1) 689: putchar(')'); 690: putchar('\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: }