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