home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / bin / csh / set.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-11-06  |  16.5 KB  |  843 lines

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