|
|
1.1 ! root 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.3 (Berkeley) 5/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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.