File: | src/bin/csh/set.c |
Warning: | line 504, column 13 Access to field 'vec' results in a dereference of a null pointer (loaded from variable 'p') |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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 | ||||
40 | static Char *getinx(Char *, int *); | |||
41 | static void asx(Char *, int, Char *); | |||
42 | static struct varent | |||
43 | *getvx(Char *, int); | |||
44 | static Char *xset(Char *, Char ***); | |||
45 | static Char *operate(int, Char *, Char *); | |||
46 | static struct varent | |||
47 | *madrof(Char *, struct varent *); | |||
48 | static void unsetv1(struct varent *); | |||
49 | static void exportpath(Char **); | |||
50 | static void balance(struct varent *, int, int); | |||
51 | ||||
52 | ||||
53 | /* | |||
54 | * C Shell | |||
55 | */ | |||
56 | ||||
57 | void | |||
58 | doset(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) { | |||
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) == '_'))) | |||
76 | for (; alnum(*p)(((*p) & 0100000U) ? 0 : (isalnum((unsigned char) (*p)) || (*p) == '_')); p++) | |||
77 | continue; | |||
78 | if (vp == p || !letter(*vp)(((*vp) & 0100000U) ? 0 : (isalpha((unsigned char) (*vp)) || (*vp) == '_'))) | |||
79 | stderror(ERR_NAME0x10000000 | ERR_VARBEGIN30); | |||
80 | if ((p - vp) > MAXVARLEN30) { | |||
81 | stderror(ERR_NAME0x10000000 | ERR_VARTOOLONG31); | |||
82 | return; | |||
83 | } | |||
84 | if (*p == '[') { | |||
85 | hadsub++; | |||
86 | p = getinx(p, &subscr); | |||
87 | } | |||
88 | if ((op = *p) != '\0') { | |||
89 | *p++ = 0; | |||
90 | if (*p == 0 && *v && **v == '(') | |||
91 | p = *v++; | |||
92 | } | |||
93 | else if (*v && eq(*v, STRequal)(Strcmp(*v, STRequal) == 0)) { | |||
94 | op = '=', v++; | |||
95 | if (*v) | |||
96 | p = *v++; | |||
97 | } | |||
98 | if (op && op != '=') | |||
99 | stderror(ERR_NAME0x10000000 | ERR_SYNTAX0); | |||
100 | if (eq(p, STRLparen)(Strcmp(p, STRLparen) == 0)) { | |||
101 | Char **e = v; | |||
102 | ||||
103 | if (hadsub) | |||
104 | stderror(ERR_NAME0x10000000 | ERR_SYNTAX0); | |||
105 | for (;;) { | |||
106 | if (!*e) | |||
107 | stderror(ERR_NAME0x10000000 | ERR_MISSING51, ')'); | |||
108 | if (**e == ')') | |||
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 | ||||
165 | static Char * | |||
166 | getinx(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 | ||||
178 | static void | |||
179 | asx(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 | ||||
187 | static struct varent * | |||
188 | getvx(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 | ||||
199 | void | |||
200 | dolet(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 | ||||
283 | static Char * | |||
284 | xset(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 | ||||
297 | static Char * | |||
298 | operate(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 | ||||
323 | Char * | |||
324 | putn(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 | ||||
335 | int | |||
336 | getn(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 | ||||
358 | Char * | |||
359 | value1(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 | ||||
367 | static struct varent * | |||
368 | madrof(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 | ||||
381 | struct varent * | |||
382 | adrof1(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 | */ | |||
399 | void | |||
400 | set(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 | ||||
409 | void | |||
410 | set1(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 | ||||
430 | void | |||
431 | setq(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); | |||
452 | found: | |||
453 | trim(c->vec = vec); | |||
454 | } | |||
455 | ||||
456 | void | |||
457 | unset(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 | ||||
470 | void | |||
471 | unset1(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 | ||||
485 | void | |||
486 | unsetv(Char *var) | |||
487 | { | |||
488 | struct varent *vp; | |||
489 | ||||
490 | if ((vp = adrof1(var, &shvhed)) == 0) | |||
| ||||
491 | udvar(var); | |||
492 | unsetv1(vp); | |||
493 | } | |||
494 | ||||
495 | static void | |||
496 | unsetv1(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 | ||||
537 | void | |||
538 | setNS(Char *cp) | |||
539 | { | |||
540 | set(cp, Strsave(STRNULL)); | |||
541 | } | |||
542 | ||||
543 | void | |||
544 | shift(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 | ||||
563 | static void | |||
564 | exportpath(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 | */ | |||
603 | static void | |||
604 | balance(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 | ||||
692 | void | |||
693 | plist(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]; | |||
708 | x: | |||
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 | } |