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: }

Defined functions

adrof1 defined in line 352; used 7 times
asx defined in line 112; used 4 times
balance defined in line 579; used 2 times
dolet defined in line 138; used 2 times
doset defined in line 17; used 2 times
exportpath defined in line 540; used 2 times
getinx defined in line 97; used 3 times
getvx defined in line 123; used 4 times
madrof defined in line 336; used 2 times
operate defined in line 235; used 4 times
plist defined in line 668; used 2 times
putn1 defined in line 291; used 2 times
set1 defined in line 382; used 5 times
setNS defined in line 513; used 4 times
setq defined in line 402; used 3 times
shift defined in line 520; used 2 times
unset defined in line 429; used 2 times
unset1 defined in line 444; used 2 times
unsetv defined in line 460; used 1 times
unsetv1 defined in line 470; used 2 times
value1 defined in line 325; used 2 times
xset defined in line 220; used 3 times

Defined variables

plusplus defined in line 136; used 1 times
putp defined in line 262; used 6 times
sccsid defined in line 8; never used

Defined macros

rleft defined in line 567; used 4 times
rright defined in line 561; used 4 times
Last modified: 1985-06-06
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1931
Valid CSS Valid XHTML 1.0 Strict