1: /* $Header: /home/hyperion/mu/christos/src/sys/tcsh-6.00/RCS/sh.set.c,v 3.0 1991/07/04 21:49:28 christos Exp $ */
   2: /*
   3:  * sh.set.c: Setting and Clearing of variables
   4:  */
   5: /*-
   6:  * Copyright (c) 1980, 1991 The Regents of the University of California.
   7:  * All rights reserved.
   8:  *
   9:  * Redistribution and use in source and binary forms, with or without
  10:  * modification, are permitted provided that the following conditions
  11:  * are met:
  12:  * 1. Redistributions of source code must retain the above copyright
  13:  *    notice, this list of conditions and the following disclaimer.
  14:  * 2. Redistributions in binary form must reproduce the above copyright
  15:  *    notice, this list of conditions and the following disclaimer in the
  16:  *    documentation and/or other materials provided with the distribution.
  17:  * 3. All advertising materials mentioning features or use of this software
  18:  *    must display the following acknowledgement:
  19:  *	This product includes software developed by the University of
  20:  *	California, Berkeley and its contributors.
  21:  * 4. Neither the name of the University nor the names of its contributors
  22:  *    may be used to endorse or promote products derived from this software
  23:  *    without specific prior written permission.
  24:  *
  25:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  26:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  27:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  28:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  29:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  30:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  31:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  32:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  33:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  34:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  35:  * SUCH DAMAGE.
  36:  */
  37: #include "config.h"
  38: #if !defined(lint) && !defined(pdp11)
  39: static char *rcsid()
  40:     { return "$Id: sh.set.c,v 3.0 1991/07/04 21:49:28 christos Exp $"; }
  41: #endif
  42: 
  43: #include "sh.h"
  44: #include "ed.h"
  45: #include "tw.h"
  46: 
  47: extern Char HistLit;
  48: extern bool GotTermCaps;
  49: 
  50: static  Char        *getinx     __P((Char *, int *));
  51: static  void         asx        __P((Char *, int, Char *));
  52: static  struct varent   *getvx      __P((Char *, int));
  53: static  Char        *xset       __P((Char *, Char ***));
  54: static  Char        *operate    __P((int, Char *, Char *));
  55: static  void         putn1      __P((int));
  56: static  struct varent   *madrof     __P((Char *, struct varent *));
  57: static  void         unsetv1    __P((struct varent *));
  58: static  void         exportpath __P((Char **));
  59: static  void         balance    __P((struct varent *, int, int));
  60: 
  61: /*
  62:  * C Shell
  63:  */
  64: 
  65: void
  66: doset(v)
  67:     register Char **v;
  68: {
  69:     register Char *p;
  70:     Char   *vp, op;
  71:     Char  **vecp;
  72:     bool    hadsub;
  73:     int     subscr;
  74: 
  75:     v++;
  76:     p = *v++;
  77:     if (p == 0) {
  78:     prvars();
  79:     return;
  80:     }
  81:     do {
  82:     hadsub = 0;
  83:     vp = p;
  84:     if (letter(*p))
  85:         for (; alnum(*p); p++)
  86:         continue;
  87:     if (vp == p || !letter(*vp))
  88:         stderror(ERR_NAME | ERR_VARBEGIN);
  89:     if ((p - vp) > MAXVARLEN) {
  90:         stderror(ERR_NAME | ERR_VARTOOLONG);
  91:         return;
  92:     }
  93:     if (*p == '[') {
  94:         hadsub++;
  95:         p = getinx(p, &subscr);
  96:     }
  97:     if (op = *p) {
  98:         *p++ = 0;
  99:         if (*p == 0 && *v && **v == '(')
 100:         p = *v++;
 101:     }
 102:     else if (*v && eq(*v, STRequal)) {
 103:         op = '=', v++;
 104:         if (*v)
 105:         p = *v++;
 106:     }
 107:     if (op && op != '=')
 108:         stderror(ERR_NAME | ERR_SYNTAX);
 109:     if (eq(p, STRLparen)) {
 110:         register Char **e = v;
 111: 
 112:         if (hadsub)
 113:         stderror(ERR_NAME | ERR_SYNTAX);
 114:         for (;;) {
 115:         if (!*e)
 116:             stderror(ERR_NAME | ERR_MISSING, ')');
 117:         if (**e == ')')
 118:             break;
 119:         e++;
 120:         }
 121:         p = *e;
 122:         *e = 0;
 123:         vecp = saveblk(v);
 124:         set1(vp, vecp, &shvhed);
 125:         *e = p;
 126:         v = e + 1;
 127:     }
 128:     else if (hadsub)
 129:         asx(vp, subscr, Strsave(p));
 130:     else
 131:         set(vp, Strsave(p));
 132:     if (eq(vp, STRpath)) {
 133:         exportpath(adrof(STRpath)->vec);
 134:         dohash();
 135:     }
 136:     else if (eq(vp, STRhstc)) {
 137:         register Char *pn = value(STRhstc);
 138: 
 139:         HIST = *pn++;
 140:         HISTSUB = *pn;
 141:     }
 142:     else if (eq(vp, STRhstl)) {
 143:         HistLit = 1;
 144:     }
 145:     else if (eq(vp, STRuser)) {
 146:         Setenv(STRUSER, value(vp));
 147:         Setenv(STRLOGNAME, value(vp));
 148:     }
 149:     else if (eq(vp, STRwordchars)) {
 150:         word_chars = value(vp);
 151:     }
 152:     else if (eq(vp, STRterm)) {
 153: #ifdef DOESNT_WORK_RIGHT
 154:         register Char *cp;
 155: 
 156: #endif
 157:         Setenv(STRTRM, value(vp));
 158: #ifdef DOESNT_WORK_RIGHT
 159:         cp = getenv("TERMCAP");
 160:         if (cp && (*cp != '/')) /* if TERMCAP and not a path */
 161:         Unsetenv(STRTRMCAP);
 162: #endif				/* DOESNT_WORK_RIGHT */
 163:         GotTermCaps = 0;
 164:         ed_I();     /* reset the editor */
 165:     }
 166:     else if (eq(vp, STRhome)) {
 167:         register Char *cp;
 168: 
 169:         cp = Strsave(value(vp));    /* get the old value back */
 170: 
 171:         /*
 172: 	     * convert to cononical pathname (possibly resolving symlinks)
 173: 	     */
 174:         cp = dcanon(cp, cp);
 175: 
 176:         set(vp, Strsave(cp));   /* have to save the new val */
 177: 
 178:         /* and now mirror home with HOME */
 179:         Setenv(STRHOME, cp);
 180:         /* fix directory stack for new tilde home */
 181:         dtilde();
 182:         xfree((ptr_t) cp);
 183:     }
 184:     else if (eq(vp, STRedit)) {
 185:         editing = 1;
 186:         /* PWP: add more stuff in here later */
 187:     }
 188:     else if (eq(vp, STRshlvl)) {
 189:         Setenv(STRSHLVL, value(vp));
 190:     }
 191:     else if (eq(vp, STRbKslash_quote)) {
 192:         bslash_quote = 1;
 193:     }
 194:     else if (eq(vp, STRrecognize_only_executables)) {
 195:         tw_clear_comm_list();
 196:     }
 197:     else if (eq(vp, STRwatch)) {
 198:         resetwatch();
 199:     }
 200:     } while (p = *v++);
 201: }
 202: 
 203: static Char *
 204: getinx(cp, ip)
 205:     register Char *cp;
 206:     register int *ip;
 207: {
 208:     *ip = 0;
 209:     *cp++ = 0;
 210:     while (*cp && Isdigit(*cp))
 211:     *ip = *ip * 10 + *cp++ - '0';
 212:     if (*cp++ != ']')
 213:     stderror(ERR_NAME | ERR_SUBSCRIPT);
 214:     return (cp);
 215: }
 216: 
 217: static void
 218: asx(vp, subscr, p)
 219:     Char   *vp;
 220:     int     subscr;
 221:     Char   *p;
 222: {
 223:     register struct varent *v = getvx(vp, subscr);
 224: 
 225:     xfree((ptr_t) v->vec[subscr - 1]);
 226:     v->vec[subscr - 1] = globone(p, G_APPEND);
 227: }
 228: 
 229: static struct varent *
 230: getvx(vp, subscr)
 231:     Char   *vp;
 232:     int     subscr;
 233: {
 234:     register struct varent *v = adrof(vp);
 235: 
 236:     if (v == 0)
 237:     udvar(vp);
 238:     if (subscr < 1 || subscr > blklen(v->vec))
 239:     stderror(ERR_NAME | ERR_RANGE);
 240:     return (v);
 241: }
 242: 
 243: void
 244: dolet(v)
 245:     Char  **v;
 246: {
 247:     register Char *p;
 248:     Char   *vp, c, op;
 249:     bool    hadsub;
 250:     int     subscr;
 251: 
 252:     v++;
 253:     p = *v++;
 254:     if (p == 0) {
 255:     prvars();
 256:     return;
 257:     }
 258:     do {
 259:     hadsub = 0;
 260:     vp = p;
 261:     if (letter(*p))
 262:         for (; alnum(*p); p++)
 263:         continue;
 264:     if (vp == p || !letter(*vp))
 265:         stderror(ERR_NAME | ERR_VARBEGIN);
 266:     if ((p - vp) > MAXVARLEN)
 267:         stderror(ERR_NAME | ERR_VARTOOLONG);
 268:     if (*p == '[') {
 269:         hadsub++;
 270:         p = getinx(p, &subscr);
 271:     }
 272:     if (*p == 0 && *v)
 273:         p = *v++;
 274:     if (op = *p)
 275:         *p++ = 0;
 276:     else
 277:         stderror(ERR_NAME | ERR_ASSIGN);
 278: 
 279:     /*
 280: 	 * if there is no expression after the '=' then print a "Syntax Error"
 281: 	 * message - strike
 282: 	 */
 283:     if (*p == '\0' && *v == NULL)
 284:         stderror(ERR_NAME | ERR_ASSIGN);
 285: 
 286:     vp = Strsave(vp);
 287:     if (op == '=') {
 288:         c = '=';
 289:         p = xset(p, &v);
 290:     }
 291:     else {
 292:         c = *p++;
 293:         if (any("+-", c)) {
 294:         if (c != op || *p)
 295:             stderror(ERR_NAME | ERR_UNKNOWNOP);
 296:         p = Strsave(STR1);
 297:         }
 298:         else {
 299:         if (any("<>", op)) {
 300:             if (c != op)
 301:             stderror(ERR_NAME | ERR_UNKNOWNOP);
 302:             c = *p++;
 303:             stderror(ERR_NAME | ERR_SYNTAX);
 304:         }
 305:         if (c != '=')
 306:             stderror(ERR_NAME | ERR_UNKNOWNOP);
 307:         p = xset(p, &v);
 308:         }
 309:     }
 310:     if (op == '=')
 311:         if (hadsub)
 312:         asx(vp, subscr, p);
 313:         else
 314:         set(vp, p);
 315:     else if (hadsub) {
 316:         struct varent *gv = getvx(vp, subscr);
 317: 
 318:         asx(vp, subscr, operate(op, gv->vec[subscr - 1], p));
 319:     }
 320:     else
 321:         set(vp, operate(op, value(vp), p));
 322:     if (eq(vp, STRpath)) {
 323:         exportpath(adrof(STRpath)->vec);
 324:         dohash();
 325:     }
 326:     xfree((ptr_t) vp);
 327:     if (c != '=')
 328:         xfree((ptr_t) p);
 329:     } while (p = *v++);
 330: }
 331: 
 332: static Char *
 333: xset(cp, vp)
 334:     Char   *cp, ***vp;
 335: {
 336:     register Char *dp;
 337: 
 338:     if (*cp) {
 339:     dp = Strsave(cp);
 340:     --(*vp);
 341:     xfree((ptr_t) ** vp);
 342:     **vp = dp;
 343:     }
 344:     return (putn(exp(vp)));
 345: }
 346: 
 347: static Char *
 348: operate(op, vp, p)
 349:     Char    op, *vp, *p;
 350: {
 351:     Char    opr[2];
 352:     Char   *vec[5];
 353:     register Char **v = vec;
 354:     Char  **vecp = v;
 355:     register int i;
 356: 
 357:     if (op != '=') {
 358:     if (*vp)
 359:         *v++ = vp;
 360:     opr[0] = op;
 361:     opr[1] = 0;
 362:     *v++ = opr;
 363:     if (op == '<' || op == '>')
 364:         *v++ = opr;
 365:     }
 366:     *v++ = p;
 367:     *v++ = 0;
 368:     i = exp(&vecp);
 369:     if (*vecp)
 370:     stderror(ERR_NAME | ERR_EXPRESSION);
 371:     return (putn(i));
 372: }
 373: 
 374: static Char *putp;
 375: 
 376: Char   *
 377: putn(n)
 378:     register int n;
 379: {
 380:     int     num;
 381:     static Char number[15];
 382: 
 383:     putp = number;
 384:     if (n < 0) {
 385:     n = -n;
 386:     *putp++ = '-';
 387:     }
 388:     num = 2;            /* comfuse lint */
 389:     if (sizeof(int) == num && n == -32768) {
 390:     *putp++ = '3';
 391:     n = 2768;
 392: #ifdef pdp11
 393:     }
 394: #else
 395:     }
 396:     else {
 397:     num = 4;        /* comfuse lint */
 398:     if (sizeof(int) == num && n == -2147483648) {
 399:         *putp++ = '2';
 400:         n = 147483648;
 401:     }
 402:     }
 403: #endif
 404:     putn1(n);
 405:     *putp = 0;
 406:     return (Strsave(number));
 407: }
 408: 
 409: static void
 410: putn1(n)
 411:     register int n;
 412: {
 413:     if (n > 9)
 414:     putn1(n / 10);
 415:     *putp++ = n % 10 + '0';
 416: }
 417: 
 418: int
 419: getn(cp)
 420:     register Char *cp;
 421: {
 422:     register int n;
 423:     int     sign;
 424: 
 425:     sign = 0;
 426:     if (cp[0] == '+' && cp[1])
 427:     cp++;
 428:     if (*cp == '-') {
 429:     sign++;
 430:     cp++;
 431:     if (!Isdigit(*cp))
 432:         stderror(ERR_NAME | ERR_BADNUM);
 433:     }
 434:     n = 0;
 435:     while (Isdigit(*cp))
 436:     n = n * 10 + *cp++ - '0';
 437:     if (*cp)
 438:     stderror(ERR_NAME | ERR_BADNUM);
 439:     return (sign ? -n : n);
 440: }
 441: 
 442: Char   *
 443: value1(var, head)
 444:     Char   *var;
 445:     struct varent *head;
 446: {
 447:     register struct varent *vp;
 448: 
 449:     vp = adrof1(var, head);
 450:     return (vp == 0 || vp->vec[0] == 0 ? STRNULL : vp->vec[0]);
 451: }
 452: 
 453: static struct varent *
 454: madrof(pat, vp)
 455:     Char   *pat;
 456:     register struct varent *vp;
 457: {
 458:     register struct varent *vp1;
 459: 
 460:     for (; vp; vp = vp->v_right) {
 461:     if (vp->v_left && (vp1 = madrof(pat, vp->v_left)))
 462:         return vp1;
 463:     if (Gmatch(vp->v_name, pat))
 464:         return vp;
 465:     }
 466:     return vp;
 467: }
 468: 
 469: struct varent *
 470: adrof1(name, v)
 471:     register Char *name;
 472:     register struct varent *v;
 473: {
 474:     register cmp;
 475: 
 476:     v = v->v_left;
 477:     while (v && ((cmp = *name - *v->v_name) || (cmp = Strcmp(name, v->v_name))))
 478:     if (cmp < 0)
 479:         v = v->v_left;
 480:     else
 481:         v = v->v_right;
 482:     return v;
 483: }
 484: 
 485: /*
 486:  * The caller is responsible for putting value in a safe place
 487:  */
 488: void
 489: set(var, val)
 490:     Char   *var, *val;
 491: {
 492:     register Char **vec = (Char **) xmalloc((size_t) (2 * sizeof(Char **)));
 493: 
 494:     vec[0] = val;
 495:     vec[1] = 0;
 496:     set1(var, vec, &shvhed);
 497: }
 498: 
 499: void
 500: set1(var, vec, head)
 501:     Char   *var, **vec;
 502:     struct varent *head;
 503: {
 504:     register Char **oldv = vec;
 505: 
 506:     gflag = 0;
 507:     tglob(oldv);
 508:     if (gflag) {
 509:     vec = globall(oldv);
 510:     if (vec == 0) {
 511:         blkfree(oldv);
 512:         stderror(ERR_NAME | ERR_NOMATCH);
 513:         return;
 514:     }
 515:     blkfree(oldv);
 516:     gargv = 0;
 517:     }
 518:     setq(var, vec, head);
 519: }
 520: 
 521: 
 522: void
 523: setq(name, vec, p)
 524:     Char   *name, **vec;
 525:     register struct varent *p;
 526: {
 527:     register struct varent *c;
 528:     register f;
 529: 
 530:     f = 0;          /* tree hangs off the header's left link */
 531:     while (c = p->v_link[f]) {
 532:     if ((f = *name - *c->v_name) == 0 &&
 533:         (f = Strcmp(name, c->v_name)) == 0) {
 534:         blkfree(c->vec);
 535:         goto found;
 536:     }
 537:     p = c;
 538:     f = f > 0;
 539:     }
 540:     p->v_link[f] = c = (struct varent *) xmalloc((size_t)sizeof(struct varent));
 541:     c->v_name = Strsave(name);
 542:     c->v_bal = 0;
 543:     c->v_left = c->v_right = 0;
 544:     c->v_parent = p;
 545:     balance(p, f, 0);
 546: found:
 547:     trim(c->vec = vec);
 548: }
 549: 
 550: void
 551: unset(v)
 552:     Char   *v[];
 553: {
 554:     register bool did_only;
 555: 
 556:     did_only = adrof(STRrecognize_only_executables) != 0;
 557:     unset1(v, &shvhed);
 558:     if (adrof(STRhstc) == 0) {
 559:     HIST = '!';
 560:     HISTSUB = '^';
 561:     }
 562:     if (adrof(STRhstl) == 0)
 563:     HistLit = 0;
 564:     if (adrof(STRwordchars) == 0)
 565:     word_chars = STR_WORD_CHARS;
 566:     if (adrof(STRedit) == 0)
 567:     editing = 0;
 568:     if (adrof(STRbKslash_quote) == 0)
 569:     bslash_quote = 0;
 570:     if (did_only && adrof(STRrecognize_only_executables) == 0)
 571:     tw_clear_comm_list();
 572: }
 573: 
 574: void
 575: unset1(v, head)
 576:     register Char *v[];
 577:     struct varent *head;
 578: {
 579:     register struct varent *vp;
 580:     register int cnt;
 581: 
 582:     while (*++v) {
 583:     cnt = 0;
 584:     while (vp = madrof(*v, head->v_left))
 585:         unsetv1(vp), cnt++;
 586:     if (cnt == 0)
 587:         setname(short2str(*v));
 588:     }
 589: }
 590: 
 591: void
 592: unsetv(var)
 593:     Char   *var;
 594: {
 595:     register struct varent *vp;
 596: 
 597:     if ((vp = adrof1(var, &shvhed)) == 0)
 598:     udvar(var);
 599:     unsetv1(vp);
 600: }
 601: 
 602: static void
 603: unsetv1(p)
 604:     register struct varent *p;
 605: {
 606:     register struct varent *c, *pp;
 607:     register f;
 608: 
 609:     /*
 610:      * Free associated memory first to avoid complications.
 611:      */
 612:     blkfree(p->vec);
 613:     xfree((ptr_t) p->v_name);
 614:     /*
 615:      * If p is missing one child, then we can move the other into where p is.
 616:      * Otherwise, we find the predecessor of p, which is guaranteed to have no
 617:      * right child, copy it into p, and move it's left child into it.
 618:      */
 619:     if (p->v_right == 0)
 620:     c = p->v_left;
 621:     else if (p->v_left == 0)
 622:     c = p->v_right;
 623:     else {
 624:     for (c = p->v_left; c->v_right; c = c->v_right);
 625:     p->v_name = c->v_name;
 626:     p->vec = c->vec;
 627:     p = c;
 628:     c = p->v_left;
 629:     }
 630:     /*
 631:      * Move c into where p is.
 632:      */
 633:     pp = p->v_parent;
 634:     f = pp->v_right == p;
 635:     if (pp->v_link[f] = c)
 636:     c->v_parent = pp;
 637:     /*
 638:      * Free the deleted node, and rebalance.
 639:      */
 640:     xfree((ptr_t) p);
 641:     balance(pp, f, 1);
 642: }
 643: 
 644: void
 645: setNS(cp)
 646:     Char   *cp;
 647: {
 648:     set(cp, Strsave(STRNULL));
 649: }
 650: 
 651: void
 652: shift(v)
 653:     register Char **v;
 654: {
 655:     register struct varent *argv;
 656:     register Char *name;
 657: 
 658:     v++;
 659:     name = *v;
 660:     if (name == 0)
 661:     name = STRargv;
 662:     else
 663:     (void) strip(name);
 664:     argv = adrof(name);
 665:     if (argv == 0)
 666:     udvar(name);
 667:     if (argv->vec[0] == 0)
 668:     stderror(ERR_NAME | ERR_NOMORE);
 669:     lshift(argv->vec, 1);
 670: }
 671: 
 672: static void
 673: exportpath(val)
 674:     Char  **val;
 675: {
 676:     Char    exppath[BUFSIZ];
 677: 
 678:     exppath[0] = 0;
 679:     if (val)
 680:     while (*val) {
 681:         if (Strlen(*val) + Strlen(exppath) + 2 > BUFSIZ) {
 682:         xprintf("Warning: ridiculously long PATH truncated\n");
 683:         break;
 684:         }
 685:         (void) Strcat(exppath, *val++);
 686:         if (*val == 0 || eq(*val, STRRparen))
 687:         break;
 688:         (void) Strcat(exppath, STRcolon);
 689:     }
 690:     Setenv(STRPATH, exppath);
 691: }
 692: 
 693: #ifndef lint
 694:  /*
 695:   * Lint thinks these have null effect
 696:   */
 697:  /* macros to do single rotations on node p */
 698: #define rright(p) (\
 699:     t = (p)->v_left,\
 700:     (t)->v_parent = (p)->v_parent,\
 701:     ((p)->v_left = t->v_right) ? (t->v_right->v_parent = (p)) : 0,\
 702:     (t->v_right = (p))->v_parent = t,\
 703:     (p) = t)
 704: #define rleft(p) (\
 705:     t = (p)->v_right,\
 706:     (t)->v_parent = (p)->v_parent,\
 707:     ((p)->v_right = t->v_left) ? (t->v_left->v_parent = (p)) : 0,\
 708:     (t->v_left = (p))->v_parent = t,\
 709:     (p) = t)
 710: #else
 711: struct varent *
 712: rleft(p)
 713:     struct varent *p;
 714: {
 715:     return (p);
 716: }
 717: struct varent *
 718: rright(p)
 719:     struct varent *p;
 720: {
 721:     return (p);
 722: }
 723: 
 724: #endif				/* ! lint */
 725: 
 726: 
 727: /*
 728:  * Rebalance a tree, starting at p and up.
 729:  * F == 0 means we've come from p's left child.
 730:  * D == 1 means we've just done a delete, otherwise an insert.
 731:  */
 732: static void
 733: balance(p, f, d)
 734:     register struct varent *p;
 735:     register int f, d;
 736: {
 737:     register struct varent *pp;
 738: 
 739: #ifndef lint
 740:     register struct varent *t;  /* used by the rotate macros */
 741: 
 742: #endif
 743:     register ff;
 744: 
 745:     /*
 746:      * Ok, from here on, p is the node we're operating on; pp is it's parent; f
 747:      * is the branch of p from which we have come; ff is the branch of pp which
 748:      * is p.
 749:      */
 750:     for (; pp = p->v_parent; p = pp, f = ff) {
 751:     ff = pp->v_right == p;
 752:     if (f ^ d) {        /* right heavy */
 753:         switch (p->v_bal) {
 754:         case -1:        /* was left heavy */
 755:         p->v_bal = 0;
 756:         break;
 757:         case 0:     /* was balanced */
 758:         p->v_bal = 1;
 759:         break;
 760:         case 1:     /* was already right heavy */
 761:         switch (p->v_right->v_bal) {
 762:         case 1: /* sigle rotate */
 763:             pp->v_link[ff] = rleft(p);
 764:             p->v_left->v_bal = 0;
 765:             p->v_bal = 0;
 766:             break;
 767:         case 0: /* single rotate */
 768:             pp->v_link[ff] = rleft(p);
 769:             p->v_left->v_bal = 1;
 770:             p->v_bal = -1;
 771:             break;
 772:         case -1:    /* double rotate */
 773:             (void) rright(p->v_right);
 774:             pp->v_link[ff] = rleft(p);
 775:             p->v_left->v_bal =
 776:             p->v_bal < 1 ? 0 : -1;
 777:             p->v_right->v_bal =
 778:             p->v_bal > -1 ? 0 : 1;
 779:             p->v_bal = 0;
 780:             break;
 781:         }
 782:         break;
 783:         }
 784:     }
 785:     else {          /* left heavy */
 786:         switch (p->v_bal) {
 787:         case 1:     /* was right heavy */
 788:         p->v_bal = 0;
 789:         break;
 790:         case 0:     /* was balanced */
 791:         p->v_bal = -1;
 792:         break;
 793:         case -1:        /* was already left heavy */
 794:         switch (p->v_left->v_bal) {
 795:         case -1:    /* single rotate */
 796:             pp->v_link[ff] = rright(p);
 797:             p->v_right->v_bal = 0;
 798:             p->v_bal = 0;
 799:             break;
 800:         case 0: /* signle rotate */
 801:             pp->v_link[ff] = rright(p);
 802:             p->v_right->v_bal = -1;
 803:             p->v_bal = 1;
 804:             break;
 805:         case 1: /* double rotate */
 806:             (void) rleft(p->v_left);
 807:             pp->v_link[ff] = rright(p);
 808:             p->v_left->v_bal =
 809:             p->v_bal < 1 ? 0 : -1;
 810:             p->v_right->v_bal =
 811:             p->v_bal > -1 ? 0 : 1;
 812:             p->v_bal = 0;
 813:             break;
 814:         }
 815:         break;
 816:         }
 817:     }
 818:     /*
 819: 	 * If from insert, then we terminate when p is balanced. If from
 820: 	 * delete, then we terminate when p is unbalanced.
 821: 	 */
 822:     if ((p->v_bal == 0) ^ d)
 823:         break;
 824:     }
 825: }
 826: 
 827: void
 828: plist(p)
 829:     register struct varent *p;
 830: {
 831:     register struct varent *c;
 832:     register len;
 833: 
 834:     if (setintr)
 835: #ifdef BSDSIGS
 836:     (void) sigsetmask(sigblock((sigmask_t) 0) & ~sigmask(SIGINT));
 837: #else               /* BSDSIGS */
 838:     (void) sigrelse(SIGINT);
 839: #endif				/* BSDSIGS */
 840: 
 841:     for (;;) {
 842:     while (p->v_left)
 843:         p = p->v_left;
 844: x:
 845:     if (p->v_parent == 0)   /* is it the header? */
 846:         return;
 847:     len = blklen(p->vec);
 848:     xprintf(short2str(p->v_name));
 849:     xputchar('\t');
 850:     if (len != 1)
 851:         xputchar('(');
 852:     blkpr(p->vec);
 853:     if (len != 1)
 854:         xputchar(')');
 855:     xputchar('\n');
 856:     if (p->v_right) {
 857:         p = p->v_right;
 858:         continue;
 859:     }
 860:     do {
 861:         c = p;
 862:         p = p->v_parent;
 863:     } while (p->v_right == c);
 864:     goto x;
 865:     }
 866: }

Defined functions

asx defined in line 217; used 3 times
balance defined in line 732; used 2 times
dolet defined in line 243; used 1 times
doset defined in line 65; used 1 times
exportpath defined in line 672; used 2 times
getinx defined in line 203; used 2 times
getvx defined in line 229; used 2 times
madrof defined in line 453; used 2 times
operate defined in line 347; used 2 times
plist defined in line 827; used 11 times
putn1 defined in line 409; used 2 times
rcsid defined in line 39; never used
rleft defined in line 711; never used
rright defined in line 717; never used
set1 defined in line 499; used 5 times
setNS defined in line 644; never used
setq defined in line 522; used 4 times
shift defined in line 651; used 1 times
unset defined in line 550; used 1 times
unset1 defined in line 574; used 3 times
unsetv defined in line 591; used 1 times
unsetv1 defined in line 602; used 2 times
value1 defined in line 442; used 1 times
xset defined in line 332; used 2 times

Defined variables

putp defined in line 374; used 6 times

Defined macros

rleft defined in line 704; used 4 times
rright defined in line 698; used 4 times
Last modified: 1991-08-20
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 4461
Valid CSS Valid XHTML 1.0 Strict