Bug Summary

File:src/bin/csh/set.c
Warning:line 108, column 7
Dereference of null pointer

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.4 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name set.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 1 -pic-is-pie -mframe-pointer=all -relaxed-aliasing -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/bin/csh/obj -resource-dir /usr/local/llvm16/lib/clang/16 -I /usr/src/bin/csh -I . -internal-isystem /usr/local/llvm16/lib/clang/16/include -internal-externc-isystem /usr/include -O2 -fdebug-compilation-dir=/usr/src/bin/csh/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fcf-protection=branch -fno-jump-tables -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/scan/2024-01-11-140451-98009-1 -x c /usr/src/bin/csh/set.c
1/* $OpenBSD: set.c,v 1.25 2023/03/08 04:43:04 guenther Exp $ */
2/* $NetBSD: set.c,v 1.8 1995/03/21 18:35:52 mycroft Exp $ */
3
4/*-
5 * Copyright (c) 1980, 1991, 1993
6 * The Regents of the University of California. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the University nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33#include <sys/types.h>
34#include <stdlib.h>
35#include <stdarg.h>
36
37#include "csh.h"
38#include "extern.h"
39
40static Char *getinx(Char *, int *);
41static void asx(Char *, int, Char *);
42static struct varent
43 *getvx(Char *, int);
44static Char *xset(Char *, Char ***);
45static Char *operate(int, Char *, Char *);
46static struct varent
47 *madrof(Char *, struct varent *);
48static void unsetv1(struct varent *);
49static void exportpath(Char **);
50static void balance(struct varent *, int, int);
51
52
53/*
54 * C Shell
55 */
56
57void
58doset(Char **v, struct command *t)
59{
60 Char *p;
61 Char *vp, op;
62 Char **vecp;
63 bool hadsub;
64 int subscr;
65
66 v++;
67 p = *v++;
68 if (p == 0) {
1
Assuming 'p' is not equal to null
2
Taking false branch
69 prvars();
70 return;
71 }
72 do {
73 hadsub = 0;
74 vp = p;
75 if (letter(*p)(((*p) & 0100000U) ? 0 : (isalpha((unsigned char) (*p)) ||
(*p) == '_'))
)
3
Assuming the condition is false
4
'?' condition is false
5
Assuming the character is non-alphabetical
6
Assuming the condition is false
76 for (; alnum(*p)(((*p) & 0100000U) ? 0 : (isalnum((unsigned char) (*p)) ||
(*p) == '_'))
; p++)
77 continue;
78 if (vp
6.1
'vp' is equal to 'p'
== p || !letter(*vp)(((*vp) & 0100000U) ? 0 : (isalpha((unsigned char) (*vp))
|| (*vp) == '_'))
)
79 stderror(ERR_NAME0x10000000 | ERR_VARBEGIN30);
80 if ((p - vp) > MAXVARLEN30) {
7
Taking false branch
81 stderror(ERR_NAME0x10000000 | ERR_VARTOOLONG31);
82 return;
83 }
84 if (*p == '[') {
8
Assuming the condition is false
9
Taking false branch
85 hadsub++;
86 p = getinx(p, &subscr);
87 }
88 if ((op = *p) != '\0') {
10
Assuming the condition is false
89 *p++ = 0;
90 if (*p == 0 && *v && **v == '(')
91 p = *v++;
92 }
93 else if (*v && eq(*v, STRequal)(Strcmp(*v, STRequal) == 0)) {
11
Assuming pointer value is null
94 op = '=', v++;
95 if (*v)
96 p = *v++;
97 }
98 if (op
11.1
'op' is 0
&& op != '=')
99 stderror(ERR_NAME0x10000000 | ERR_SYNTAX0);
100 if (eq(p, STRLparen)(Strcmp(p, STRLparen) == 0)) {
12
Assuming the condition is true
13
Taking true branch
101 Char **e = v;
102
103 if (hadsub
13.1
'hadsub' is 0
)
14
Taking false branch
104 stderror(ERR_NAME0x10000000 | ERR_SYNTAX0);
105 for (;;) {
15
Loop condition is true. Entering loop body
106 if (!*e)
16
Taking true branch
107 stderror(ERR_NAME0x10000000 | ERR_MISSING51, ')');
108 if (**e == ')')
17
Dereference of null pointer
109 break;
110 e++;
111 }
112 p = *e;
113 *e = 0;
114 vecp = saveblk(v);
115 set1(vp, vecp, &shvhed);
116 *e = p;
117 v = e + 1;
118 }
119 else if (hadsub)
120 asx(vp, subscr, Strsave(p));
121 else
122 set(vp, Strsave(p));
123 if (eq(vp, STRpath)(Strcmp(vp, STRpath) == 0)) {
124 exportpath(adrof(STRpath)adrof1(STRpath, &shvhed)->vec);
125 dohash(NULL((void *)0), NULL((void *)0));
126 }
127 else if (eq(vp, STRhistchars)(Strcmp(vp, STRhistchars) == 0)) {
128 Char *pn = value(STRhistchars)value1(STRhistchars, &shvhed);
129
130 HIST = *pn++;
131 HISTSUB = *pn;
132 }
133 else if (eq(vp, STRuser)(Strcmp(vp, STRuser) == 0)) {
134 Setenv(STRUSER, value(vp)value1(vp, &shvhed));
135 Setenv(STRLOGNAME, value(vp)value1(vp, &shvhed));
136 }
137 else if (eq(vp, STRwordchars)(Strcmp(vp, STRwordchars) == 0)) {
138 word_chars = value(vp)value1(vp, &shvhed);
139 }
140 else if (eq(vp, STRterm)(Strcmp(vp, STRterm) == 0))
141 Setenv(STRTERM, value(vp)value1(vp, &shvhed));
142 else if (eq(vp, STRhome)(Strcmp(vp, STRhome) == 0)) {
143 Char *cp;
144
145 cp = Strsave(value(vp)value1(vp, &shvhed)); /* get the old value back */
146
147 /*
148 * convert to canonical pathname (possibly resolving symlinks)
149 */
150 cp = dcanon(cp, cp);
151
152 set(vp, Strsave(cp)); /* have to save the new val */
153
154 /* and now mirror home with HOME */
155 Setenv(STRHOME, cp);
156 /* fix directory stack for new tilde home */
157 dtilde();
158 free(cp);
159 }
160 else if (eq(vp, STRfilec)(Strcmp(vp, STRfilec) == 0))
161 filec = 1;
162 } while ((p = *v++) != NULL((void *)0));
163}
164
165static Char *
166getinx(Char *cp, int *ip)
167{
168
169 *ip = 0;
170 *cp++ = 0;
171 while (*cp && Isdigit(*cp)(((*cp) & 0100000U) ? 0 : isdigit((unsigned char) (*cp))))
172 *ip = *ip * 10 + *cp++ - '0';
173 if (*cp++ != ']')
174 stderror(ERR_NAME0x10000000 | ERR_SUBSCRIPT9);
175 return (cp);
176}
177
178static void
179asx(Char *vp, int subscr, Char *p)
180{
181 struct varent *v = getvx(vp, subscr);
182
183 free(v->vec[subscr - 1]);
184 v->vec[subscr - 1] = globone(p, G_APPEND2);
185}
186
187static struct varent *
188getvx(Char *vp, int subscr)
189{
190 struct varent *v = adrof(vp)adrof1(vp, &shvhed);
191
192 if (v == 0)
193 udvar(vp);
194 if (subscr < 1 || subscr > blklen(v->vec))
195 stderror(ERR_NAME0x10000000 | ERR_RANGE43);
196 return (v);
197}
198
199void
200dolet(Char **v, struct command *t)
201{
202 Char *p;
203 Char *vp, c, op;
204 bool hadsub;
205 int subscr;
206
207 v++;
208 p = *v++;
209 if (p == 0) {
210 prvars();
211 return;
212 }
213 do {
214 hadsub = 0;
215 vp = p;
216 if (letter(*p)(((*p) & 0100000U) ? 0 : (isalpha((unsigned char) (*p)) ||
(*p) == '_'))
)
217 for (; alnum(*p)(((*p) & 0100000U) ? 0 : (isalnum((unsigned char) (*p)) ||
(*p) == '_'))
; p++)
218 continue;
219 if (vp == p || !letter(*vp)(((*vp) & 0100000U) ? 0 : (isalpha((unsigned char) (*vp))
|| (*vp) == '_'))
)
220 stderror(ERR_NAME0x10000000 | ERR_VARBEGIN30);
221 if ((p - vp) > MAXVARLEN30)
222 stderror(ERR_NAME0x10000000 | ERR_VARTOOLONG31);
223 if (*p == '[') {
224 hadsub++;
225 p = getinx(p, &subscr);
226 }
227 if (*p == 0 && *v)
228 p = *v++;
229 if ((op = *p) != '\0')
230 *p++ = 0;
231 else
232 stderror(ERR_NAME0x10000000 | ERR_ASSIGN38);
233
234 if (*p == '\0' && *v == NULL((void *)0))
235 stderror(ERR_NAME0x10000000 | ERR_ASSIGN38);
236
237 vp = Strsave(vp);
238 if (op == '=') {
239 c = '=';
240 p = xset(p, &v);
241 }
242 else {
243 c = *p++;
244 if (any("+-", c)) {
245 if (c != op || *p)
246 stderror(ERR_NAME0x10000000 | ERR_UNKNOWNOP39);
247 p = Strsave(STR1);
248 }
249 else {
250 if (any("<>", op)) {
251 if (c != op)
252 stderror(ERR_NAME0x10000000 | ERR_UNKNOWNOP39);
253 c = *p++;
254 stderror(ERR_NAME0x10000000 | ERR_SYNTAX0);
255 }
256 if (c != '=')
257 stderror(ERR_NAME0x10000000 | ERR_UNKNOWNOP39);
258 p = xset(p, &v);
259 }
260 }
261 if (op == '=')
262 if (hadsub)
263 asx(vp, subscr, p);
264 else
265 set(vp, p);
266 else if (hadsub) {
267 struct varent *gv = getvx(vp, subscr);
268
269 asx(vp, subscr, operate(op, gv->vec[subscr - 1], p));
270 }
271 else
272 set(vp, operate(op, value(vp)value1(vp, &shvhed), p));
273 if (eq(vp, STRpath)(Strcmp(vp, STRpath) == 0)) {
274 exportpath(adrof(STRpath)adrof1(STRpath, &shvhed)->vec);
275 dohash(NULL((void *)0), NULL((void *)0));
276 }
277 free(vp);
278 if (c != '=')
279 free(p);
280 } while ((p = *v++) != NULL((void *)0));
281}
282
283static Char *
284xset(Char *cp, Char ***vp)
285{
286 Char *dp;
287
288 if (*cp) {
289 dp = Strsave(cp);
290 --(*vp);
291 free(** vp);
292 **vp = dp;
293 }
294 return (putn(expr(vp)));
295}
296
297static Char *
298operate(int op, Char *vp, Char *p)
299{
300 Char opr[2];
301 Char *vec[5];
302 Char **v = vec;
303 Char **vecp = v;
304 int i;
305
306 if (op != '=') {
307 if (*vp)
308 *v++ = vp;
309 opr[0] = op;
310 opr[1] = 0;
311 *v++ = opr;
312 if (op == '<' || op == '>')
313 *v++ = opr;
314 }
315 *v++ = p;
316 *v++ = 0;
317 i = expr(&vecp);
318 if (*vecp)
319 stderror(ERR_NAME0x10000000 | ERR_EXPRESSION34);
320 return (putn(i));
321}
322
323Char *
324putn(int n)
325{
326 char number[15];
327 int i;
328
329 i = snprintf(number, sizeof(number), "%d", n);
330 if (i < 0 || i >= sizeof(number))
331 return (STRNULL);
332 return (SAVE(number)(Strsave(str2short(number))));
333}
334
335int
336getn(Char *cp)
337{
338 int n;
339 int sign;
340
341 sign = 0;
342 if (cp[0] == '+' && cp[1])
343 cp++;
344 if (*cp == '-') {
345 sign++;
346 cp++;
347 if (!Isdigit(*cp)(((*cp) & 0100000U) ? 0 : isdigit((unsigned char) (*cp))))
348 stderror(ERR_NAME0x10000000 | ERR_BADNUM10);
349 }
350 n = 0;
351 while (Isdigit(*cp)(((*cp) & 0100000U) ? 0 : isdigit((unsigned char) (*cp))))
352 n = n * 10 + *cp++ - '0';
353 if (*cp)
354 stderror(ERR_NAME0x10000000 | ERR_BADNUM10);
355 return (sign ? -n : n);
356}
357
358Char *
359value1(Char *var, struct varent *head)
360{
361 struct varent *vp;
362
363 vp = adrof1(var, head);
364 return (vp == 0 || vp->vec[0] == 0 ? STRNULL : vp->vec[0]);
365}
366
367static struct varent *
368madrof(Char *pat, struct varent *vp)
369{
370 struct varent *vp1;
371
372 for (; vp; vp = vp->v_rightv_link[1]) {
373 if (vp->v_leftv_link[0] && (vp1 = madrof(pat, vp->v_leftv_link[0])))
374 return vp1;
375 if (Gmatch(vp->v_name, pat))
376 return vp;
377 }
378 return vp;
379}
380
381struct varent *
382adrof1(Char *name, struct varent *v)
383{
384 int cmp;
385
386 v = v->v_leftv_link[0];
387 while (v && ((cmp = *name - *v->v_name) ||
388 (cmp = Strcmp(name, v->v_name))))
389 if (cmp < 0)
390 v = v->v_leftv_link[0];
391 else
392 v = v->v_rightv_link[1];
393 return v;
394}
395
396/*
397 * The caller is responsible for putting value in a safe place
398 */
399void
400set(Char *var, Char *val)
401{
402 Char **vec = xreallocarray(NULL((void *)0), 2, sizeof(*vec));
403
404 vec[0] = val;
405 vec[1] = 0;
406 set1(var, vec, &shvhed);
407}
408
409void
410set1(Char *var, Char **vec, struct varent *head)
411{
412 Char **oldv = vec;
413
414 gflag = 0;
415 tglob(oldv);
416 if (gflag) {
417 vec = globall(oldv);
418 if (vec == 0) {
419 blkfree(oldv);
420 stderror(ERR_NAME0x10000000 | ERR_NOMATCH50);
421 return;
422 }
423 blkfree(oldv);
424 gargv = 0;
425 }
426 setq(var, vec, head);
427}
428
429
430void
431setq(Char *name, Char **vec, struct varent *p)
432{
433 struct varent *c;
434 int f;
435
436 f = 0; /* tree hangs off the header's left link */
437 while ((c = p->v_link[f]) != NULL((void *)0)) {
438 if ((f = *name - *c->v_name) == 0 &&
439 (f = Strcmp(name, c->v_name)) == 0) {
440 blkfree(c->vec);
441 goto found;
442 }
443 p = c;
444 f = f > 0;
445 }
446 p->v_link[f] = c = (struct varent *) xmalloc((size_t) sizeof(struct varent));
447 c->v_name = Strsave(name);
448 c->v_bal = 0;
449 c->v_leftv_link[0] = c->v_rightv_link[1] = 0;
450 c->v_parentv_link[2] = p;
451 balance(p, f, 0);
452found:
453 trim(c->vec = vec);
454}
455
456void
457unset(Char **v, struct command *t)
458{
459 unset1(v, &shvhed);
460 if (adrof(STRfilec)adrof1(STRfilec, &shvhed) == 0)
461 filec = 0;
462 if (adrof(STRhistchars)adrof1(STRhistchars, &shvhed) == 0) {
463 HIST = '!';
464 HISTSUB = '^';
465 }
466 if (adrof(STRwordchars)adrof1(STRwordchars, &shvhed) == 0)
467 word_chars = STR_WORD_CHARS;
468}
469
470void
471unset1(Char *v[], struct varent *head)
472{
473 struct varent *vp;
474 int cnt;
475
476 while (*++v) {
477 cnt = 0;
478 while ((vp = madrof(*v, head->v_leftv_link[0])) != NULL((void *)0))
479 unsetv1(vp), cnt++;
480 if (cnt == 0)
481 setname(vis_str(*v))(bname = (vis_str(*v)));
482 }
483}
484
485void
486unsetv(Char *var)
487{
488 struct varent *vp;
489
490 if ((vp = adrof1(var, &shvhed)) == 0)
491 udvar(var);
492 unsetv1(vp);
493}
494
495static void
496unsetv1(struct varent *p)
497{
498 struct varent *c, *pp;
499 int f;
500
501 /*
502 * Free associated memory first to avoid complications.
503 */
504 blkfree(p->vec);
505 free(p->v_name);
506 /*
507 * If p is missing one child, then we can move the other into where p is.
508 * Otherwise, we find the predecessor of p, which is guaranteed to have no
509 * right child, copy it into p, and move its left child into it.
510 */
511 if (p->v_rightv_link[1] == 0)
512 c = p->v_leftv_link[0];
513 else if (p->v_leftv_link[0] == 0)
514 c = p->v_rightv_link[1];
515 else {
516 for (c = p->v_leftv_link[0]; c->v_rightv_link[1]; c = c->v_rightv_link[1])
517 continue;
518 p->v_name = c->v_name;
519 p->vec = c->vec;
520 p = c;
521 c = p->v_leftv_link[0];
522 }
523 /*
524 * Move c into where p is.
525 */
526 pp = p->v_parentv_link[2];
527 f = pp->v_rightv_link[1] == p;
528 if ((pp->v_link[f] = c) != NULL((void *)0))
529 c->v_parentv_link[2] = pp;
530 /*
531 * Free the deleted node, and rebalance.
532 */
533 free(p);
534 balance(pp, f, 1);
535}
536
537void
538setNS(Char *cp)
539{
540 set(cp, Strsave(STRNULL));
541}
542
543void
544shift(Char **v, struct command *t)
545{
546 struct varent *argv;
547 Char *name;
548
549 v++;
550 name = *v;
551 if (name == 0)
552 name = STRargv;
553 else
554 (void) strip(name);
555 argv = adrof(name)adrof1(name, &shvhed);
556 if (argv == 0)
557 udvar(name);
558 if (argv->vec[0] == 0)
559 stderror(ERR_NAME0x10000000 | ERR_NOMORE11);
560 lshift(argv->vec, 1);
561}
562
563static void
564exportpath(Char **val)
565{
566 Char exppath[BUFSIZ1024];
567
568 exppath[0] = 0;
569 if (val)
570 while (*val) {
571 if (Strlen(*val) + Strlen(exppath) + 2 > BUFSIZ1024) {
572 (void) fprintf(csherr,
573 "Warning: ridiculously long PATH truncated\n");
574 break;
575 }
576 (void) Strlcat(exppath, *val++, sizeof exppath/sizeof(Char));
577 if (*val == 0 || eq(*val, STRRparen)(Strcmp(*val, STRRparen) == 0))
578 break;
579 (void) Strlcat(exppath, STRcolon, sizeof exppath/sizeof(Char));
580 }
581 Setenv(STRPATH, exppath);
582}
583
584/* macros to do single rotations on node p */
585#define rright(p)( t = (p)->v_link[0], (t)->v_link[2] = (p)->v_link[2
], ((p)->v_link[0] = t->v_link[1]) ? (t->v_link[1]->
v_link[2] = (p)) : 0, (t->v_link[1] = (p))->v_link[2] =
t, (p) = t)
(\
586 t = (p)->v_leftv_link[0],\
587 (t)->v_parentv_link[2] = (p)->v_parentv_link[2],\
588 ((p)->v_leftv_link[0] = t->v_rightv_link[1]) ? (t->v_rightv_link[1]->v_parentv_link[2] = (p)) : 0,\
589 (t->v_rightv_link[1] = (p))->v_parentv_link[2] = t,\
590 (p) = t)
591#define rleft(p)( t = (p)->v_link[1], (t)->v_link[2] = (p)->v_link[2
], ((p)->v_link[1] = t->v_link[0]) ? (t->v_link[0]->
v_link[2] = (p)) : 0, (t->v_link[0] = (p))->v_link[2] =
t, (p) = t)
(\
592 t = (p)->v_rightv_link[1],\
593 (t)->v_parentv_link[2] = (p)->v_parentv_link[2],\
594 ((p)->v_rightv_link[1] = t->v_leftv_link[0]) ? (t->v_leftv_link[0]->v_parentv_link[2] = (p)) : 0,\
595 (t->v_leftv_link[0] = (p))->v_parentv_link[2] = t,\
596 (p) = t)
597
598/*
599 * Rebalance a tree, starting at p and up.
600 * F == 0 means we've come from p's left child.
601 * D == 1 means we've just done a delete, otherwise an insert.
602 */
603static void
604balance(struct varent *p, int f, int d)
605{
606 struct varent *pp;
607 struct varent *t; /* used by the rotate macros */
608 int ff;
609
610 /*
611 * Ok, from here on, p is the node we're operating on; pp is its parent; f
612 * is the branch of p from which we have come; ff is the branch of pp which
613 * is p.
614 */
615 for (; (pp = p->v_parentv_link[2]) != NULL((void *)0); p = pp, f = ff) {
616 ff = pp->v_rightv_link[1] == p;
617 if (f ^ d) { /* right heavy */
618 switch (p->v_bal) {
619 case -1: /* was left heavy */
620 p->v_bal = 0;
621 break;
622 case 0: /* was balanced */
623 p->v_bal = 1;
624 break;
625 case 1: /* was already right heavy */
626 switch (p->v_rightv_link[1]->v_bal) {
627 case 1: /* single rotate */
628 pp->v_link[ff] = rleft(p)( t = (p)->v_link[1], (t)->v_link[2] = (p)->v_link[2
], ((p)->v_link[1] = t->v_link[0]) ? (t->v_link[0]->
v_link[2] = (p)) : 0, (t->v_link[0] = (p))->v_link[2] =
t, (p) = t)
;
629 p->v_leftv_link[0]->v_bal = 0;
630 p->v_bal = 0;
631 break;
632 case 0: /* single rotate */
633 pp->v_link[ff] = rleft(p)( t = (p)->v_link[1], (t)->v_link[2] = (p)->v_link[2
], ((p)->v_link[1] = t->v_link[0]) ? (t->v_link[0]->
v_link[2] = (p)) : 0, (t->v_link[0] = (p))->v_link[2] =
t, (p) = t)
;
634 p->v_leftv_link[0]->v_bal = 1;
635 p->v_bal = -1;
636 break;
637 case -1: /* double rotate */
638 (void) rright(p->v_right)( t = (p->v_link[1])->v_link[0], (t)->v_link[2] = (p
->v_link[1])->v_link[2], ((p->v_link[1])->v_link[
0] = t->v_link[1]) ? (t->v_link[1]->v_link[2] = (p->
v_link[1])) : 0, (t->v_link[1] = (p->v_link[1]))->v_link
[2] = t, (p->v_link[1]) = t)
;
639 pp->v_link[ff] = rleft(p)( t = (p)->v_link[1], (t)->v_link[2] = (p)->v_link[2
], ((p)->v_link[1] = t->v_link[0]) ? (t->v_link[0]->
v_link[2] = (p)) : 0, (t->v_link[0] = (p))->v_link[2] =
t, (p) = t)
;
640 p->v_leftv_link[0]->v_bal =
641 p->v_bal < 1 ? 0 : -1;
642 p->v_rightv_link[1]->v_bal =
643 p->v_bal > -1 ? 0 : 1;
644 p->v_bal = 0;
645 break;
646 }
647 break;
648 }
649 }
650 else { /* left heavy */
651 switch (p->v_bal) {
652 case 1: /* was right heavy */
653 p->v_bal = 0;
654 break;
655 case 0: /* was balanced */
656 p->v_bal = -1;
657 break;
658 case -1: /* was already left heavy */
659 switch (p->v_leftv_link[0]->v_bal) {
660 case -1: /* single rotate */
661 pp->v_link[ff] = rright(p)( t = (p)->v_link[0], (t)->v_link[2] = (p)->v_link[2
], ((p)->v_link[0] = t->v_link[1]) ? (t->v_link[1]->
v_link[2] = (p)) : 0, (t->v_link[1] = (p))->v_link[2] =
t, (p) = t)
;
662 p->v_rightv_link[1]->v_bal = 0;
663 p->v_bal = 0;
664 break;
665 case 0: /* single rotate */
666 pp->v_link[ff] = rright(p)( t = (p)->v_link[0], (t)->v_link[2] = (p)->v_link[2
], ((p)->v_link[0] = t->v_link[1]) ? (t->v_link[1]->
v_link[2] = (p)) : 0, (t->v_link[1] = (p))->v_link[2] =
t, (p) = t)
;
667 p->v_rightv_link[1]->v_bal = -1;
668 p->v_bal = 1;
669 break;
670 case 1: /* double rotate */
671 (void) rleft(p->v_left)( t = (p->v_link[0])->v_link[1], (t)->v_link[2] = (p
->v_link[0])->v_link[2], ((p->v_link[0])->v_link[
1] = t->v_link[0]) ? (t->v_link[0]->v_link[2] = (p->
v_link[0])) : 0, (t->v_link[0] = (p->v_link[0]))->v_link
[2] = t, (p->v_link[0]) = t)
;
672 pp->v_link[ff] = rright(p)( t = (p)->v_link[0], (t)->v_link[2] = (p)->v_link[2
], ((p)->v_link[0] = t->v_link[1]) ? (t->v_link[1]->
v_link[2] = (p)) : 0, (t->v_link[1] = (p))->v_link[2] =
t, (p) = t)
;
673 p->v_leftv_link[0]->v_bal =
674 p->v_bal < 1 ? 0 : -1;
675 p->v_rightv_link[1]->v_bal =
676 p->v_bal > -1 ? 0 : 1;
677 p->v_bal = 0;
678 break;
679 }
680 break;
681 }
682 }
683 /*
684 * If from insert, then we terminate when p is balanced. If from
685 * delete, then we terminate when p is unbalanced.
686 */
687 if ((p->v_bal == 0) ^ d)
688 break;
689 }
690}
691
692void
693plist(struct varent *p)
694{
695 struct varent *c;
696 int len;
697 sigset_t sigset;
698
699 if (setintr) {
700 sigemptyset(&sigset);
701 sigaddset(&sigset, SIGINT2);
702 sigprocmask(SIG_UNBLOCK2, &sigset, NULL((void *)0));
703 }
704
705 for (;;) {
706 while (p->v_leftv_link[0])
707 p = p->v_leftv_link[0];
708x:
709 if (p->v_parentv_link[2] == 0) /* is it the header? */
710 return;
711 len = blklen(p->vec);
712 (void) fprintf(cshout, "%s\t", short2str(p->v_name));
713 if (len != 1)
714 (void) fputc('(', cshout);
715 blkpr(cshout, p->vec);
716 if (len != 1)
717 (void) fputc(')', cshout);
718 (void) fputc('\n', cshout);
719 if (p->v_rightv_link[1]) {
720 p = p->v_rightv_link[1];
721 continue;
722 }
723 do {
724 c = p;
725 p = p->v_parentv_link[2];
726 } while (p->v_rightv_link[1] == c);
727 goto x;
728 }
729}