Fix warning.
[dragonfly.git] / contrib / tcsh / sh.set.c
blob531da301fed0ff4a26044045e0058b0dca1f1ac2
1 /* $Header: /src/pub/tcsh/sh.set.c,v 3.44 2002/07/01 20:50:22 christos Exp $ */
2 /*
3 * sh.set.c: Setting and Clearing of variables
4 */
5 /*-
6 * Copyright (c) 1980, 1991 The Regents of the University of California.
7 * All rights reserved.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. 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.
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.
33 #include "sh.h"
35 RCSID("$Id: sh.set.c,v 3.44 2002/07/01 20:50:22 christos Exp $")
37 #include "ed.h"
38 #include "tw.h"
40 extern Char HistLit;
41 extern bool GotTermCaps;
43 static void update_vars __P((Char *));
44 static Char *getinx __P((Char *, int *));
45 static void asx __P((Char *, int, Char *));
46 static struct varent *getvx __P((Char *, int));
47 static Char *xset __P((Char *, Char ***));
48 static Char *operate __P((int, Char *, Char *));
49 static void putn1 __P((int));
50 static struct varent *madrof __P((Char *, struct varent *));
51 static void unsetv1 __P((struct varent *));
52 static void exportpath __P((Char **));
53 static void balance __P((struct varent *, int, int));
56 * C Shell
59 static void
60 update_vars(vp)
61 Char *vp;
63 if (eq(vp, STRpath)) {
64 exportpath(adrof(STRpath)->vec);
65 dohash(NULL, NULL);
67 else if (eq(vp, STRhistchars)) {
68 register Char *pn = varval(vp);
70 HIST = *pn++;
71 HISTSUB = *pn;
73 else if (eq(vp, STRpromptchars)) {
74 register Char *pn = varval(vp);
76 PRCH = *pn++;
77 PRCHROOT = *pn;
79 else if (eq(vp, STRhistlit)) {
80 HistLit = 1;
82 else if (eq(vp, STRuser)) {
83 tsetenv(STRKUSER, varval(vp));
84 tsetenv(STRLOGNAME, varval(vp));
86 else if (eq(vp, STRgroup)) {
87 tsetenv(STRKGROUP, varval(vp));
89 else if (eq(vp, STRwordchars)) {
90 word_chars = varval(vp);
92 else if (eq(vp, STRloginsh)) {
93 loginsh = 1;
95 else if (eq(vp, STRsymlinks)) {
96 register Char *pn = varval(vp);
98 if (eq(pn, STRignore))
99 symlinks = SYM_IGNORE;
100 else if (eq(pn, STRexpand))
101 symlinks = SYM_EXPAND;
102 else if (eq(pn, STRchase))
103 symlinks = SYM_CHASE;
104 else
105 symlinks = 0;
107 else if (eq(vp, STRterm)) {
108 Char *cp = varval(vp);
109 tsetenv(STRKTERM, cp);
110 #ifdef DOESNT_WORK_RIGHT
111 cp = getenv("TERMCAP");
112 if (cp && (*cp != '/')) /* if TERMCAP and not a path */
113 Unsetenv(STRTERMCAP);
114 #endif /* DOESNT_WORK_RIGHT */
115 GotTermCaps = 0;
116 if (noediting && Strcmp(cp, STRnetwork) != 0 &&
117 Strcmp(cp, STRunknown) != 0 && Strcmp(cp, STRdumb) != 0) {
118 editing = 1;
119 noediting = 0;
120 set(STRedit, Strsave(STRNULL), VAR_READWRITE);
122 ed_Init(); /* reset the editor */
124 else if (eq(vp, STRhome)) {
125 register Char *cp;
127 cp = Strsave(varval(vp)); /* get the old value back */
130 * convert to cononical pathname (possibly resolving symlinks)
132 cp = dcanon(cp, cp);
134 set(vp, Strsave(cp), VAR_READWRITE); /* have to save the new val */
136 /* and now mirror home with HOME */
137 tsetenv(STRKHOME, cp);
138 /* fix directory stack for new tilde home */
139 dtilde();
140 xfree((ptr_t) cp);
142 else if (eq(vp, STRedit)) {
143 editing = 1;
144 noediting = 0;
145 /* PWP: add more stuff in here later */
147 else if (eq(vp, STRshlvl)) {
148 tsetenv(STRKSHLVL, varval(vp));
150 else if (eq(vp, STRbackslash_quote)) {
151 bslash_quote = 1;
153 else if (eq(vp, STRdirstack)) {
154 dsetstack();
156 else if (eq(vp, STRrecognize_only_executables)) {
157 tw_cmd_free();
159 else if (eq(vp, STRkillring)) {
160 SetKillRing(getn(varval(vp)));
162 #ifndef HAVENOUTMP
163 else if (eq(vp, STRwatch)) {
164 resetwatch();
166 #endif /* HAVENOUTMP */
167 else if (eq(vp, STRimplicitcd)) {
168 implicit_cd = ((eq(varval(vp), STRverbose)) ? 2 : 1);
170 #ifdef COLOR_LS_F
171 else if (eq(vp, STRcolor)) {
172 set_color_context();
174 #endif /* COLOR_LS_F */
175 #if defined(KANJI) && defined(SHORT_STRINGS) && defined(DSPMBYTE)
176 else if(eq(vp, CHECK_MBYTEVAR) || eq(vp, STRnokanji)) {
177 update_dspmbyte_vars();
179 #endif
180 #ifdef NLS_CATALOGS
181 else if (eq(vp, STRcatalog)) {
182 (void) catclose(catd);
183 nlsinit();
185 #if defined(FILEC) && defined(TIOCSTI)
186 else if (eq(vp, STRfilec))
187 filec = 1;
188 #endif
189 #endif /* NLS_CATALOGS */
193 /*ARGSUSED*/
194 void
195 doset(v, c)
196 register Char **v;
197 struct command *c;
199 register Char *p;
200 Char *vp, op;
201 Char **vecp;
202 bool hadsub;
203 int subscr;
204 int flags = VAR_READWRITE;
205 bool first_match = 0;
206 bool last_match = 0;
207 bool changed = 0;
209 USE(c);
210 v++;
211 do {
212 changed = 0;
214 * Readonly addition From: Tim P. Starrin <noid@cyborg.larc.nasa.gov>
216 if (*v && eq(*v, STRmr)) {
217 flags = VAR_READONLY;
218 v++;
219 changed = 1;
221 if (*v && eq(*v, STRmf) && !last_match) {
222 first_match = 1;
223 v++;
224 changed = 1;
226 if (*v && eq(*v, STRml) && !first_match) {
227 last_match = 1;
228 v++;
229 changed = 1;
231 } while(changed);
232 p = *v++;
233 if (p == 0) {
234 plist(&shvhed, flags);
235 return;
237 do {
238 hadsub = 0;
239 vp = p;
240 if (letter(*p))
241 for (; alnum(*p); p++)
242 continue;
243 if (vp == p || !letter(*vp))
244 stderror(ERR_NAME | ERR_VARBEGIN);
245 if ((p - vp) > MAXVARLEN) {
246 stderror(ERR_NAME | ERR_VARTOOLONG);
247 return;
249 if (*p == '[') {
250 hadsub++;
251 p = getinx(p, &subscr);
253 if ((op = *p) != 0) {
254 *p++ = 0;
255 if (*p == 0 && *v && **v == '(')
256 p = *v++;
258 else if (*v && eq(*v, STRequal)) {
259 op = '=', v++;
260 if (*v)
261 p = *v++;
263 if (op && op != '=')
264 stderror(ERR_NAME | ERR_SYNTAX);
265 if (eq(p, STRLparen)) {
266 register Char **e = v;
268 if (hadsub)
269 stderror(ERR_NAME | ERR_SYNTAX);
270 for (;;) {
271 if (!*e)
272 stderror(ERR_NAME | ERR_MISSING, ')');
273 if (**e == ')')
274 break;
275 e++;
277 p = *e;
278 *e = 0;
279 vecp = saveblk(v);
280 if (first_match)
281 flags |= VAR_FIRST;
282 else if (last_match)
283 flags |= VAR_LAST;
285 set1(vp, vecp, &shvhed, flags);
286 *e = p;
287 v = e + 1;
289 else if (hadsub)
290 asx(vp, subscr, Strsave(p));
291 else
292 set(vp, Strsave(p), flags);
293 update_vars(vp);
294 } while ((p = *v++) != NULL);
297 static Char *
298 getinx(cp, ip)
299 register Char *cp;
300 register int *ip;
302 *ip = 0;
303 *cp++ = 0;
304 while (*cp && Isdigit(*cp))
305 *ip = *ip * 10 + *cp++ - '0';
306 if (*cp++ != ']')
307 stderror(ERR_NAME | ERR_SUBSCRIPT);
308 return (cp);
311 static void
312 asx(vp, subscr, p)
313 Char *vp;
314 int subscr;
315 Char *p;
317 register struct varent *v = getvx(vp, subscr);
319 if (v->v_flags & VAR_READONLY)
320 stderror(ERR_READONLY|ERR_NAME, v->v_name);
321 xfree((ptr_t) v->vec[subscr - 1]);
322 v->vec[subscr - 1] = globone(p, G_APPEND);
325 static struct varent *
326 getvx(vp, subscr)
327 Char *vp;
328 int subscr;
330 register struct varent *v = adrof(vp);
332 if (v == 0)
333 udvar(vp);
334 if (subscr < 1 || subscr > blklen(v->vec))
335 stderror(ERR_NAME | ERR_RANGE);
336 return (v);
339 /*ARGSUSED*/
340 void
341 dolet(v, dummy)
342 Char **v;
343 struct command *dummy;
345 register Char *p;
346 Char *vp, c, op;
347 bool hadsub;
348 int subscr;
350 USE(dummy);
351 v++;
352 p = *v++;
353 if (p == 0) {
354 prvars();
355 return;
357 do {
358 hadsub = 0;
359 vp = p;
360 if (letter(*p))
361 for (; alnum(*p); p++)
362 continue;
363 if (vp == p || !letter(*vp))
364 stderror(ERR_NAME | ERR_VARBEGIN);
365 if ((p - vp) > MAXVARLEN)
366 stderror(ERR_NAME | ERR_VARTOOLONG);
367 if (*p == '[') {
368 hadsub++;
369 p = getinx(p, &subscr);
371 if (*p == 0 && *v)
372 p = *v++;
373 if ((op = *p) != 0)
374 *p++ = 0;
375 else
376 stderror(ERR_NAME | ERR_ASSIGN);
379 * if there is no expression after the '=' then print a "Syntax Error"
380 * message - strike
382 if (*p == '\0' && *v == NULL)
383 stderror(ERR_NAME | ERR_ASSIGN);
385 vp = Strsave(vp);
386 if (op == '=') {
387 c = '=';
388 p = xset(p, &v);
390 else {
391 c = *p++;
392 if (any("+-", c)) {
393 if (c != op || *p)
394 stderror(ERR_NAME | ERR_UNKNOWNOP);
395 p = Strsave(STR1);
397 else {
398 if (any("<>", op)) {
399 if (c != op)
400 stderror(ERR_NAME | ERR_UNKNOWNOP);
401 c = *p++;
402 stderror(ERR_NAME | ERR_SYNTAX);
404 if (c != '=')
405 stderror(ERR_NAME | ERR_UNKNOWNOP);
406 p = xset(p, &v);
409 if (op == '=') {
410 if (hadsub)
411 asx(vp, subscr, p);
412 else
413 set(vp, p, VAR_READWRITE);
415 else if (hadsub) {
416 struct varent *gv = getvx(vp, subscr);
418 asx(vp, subscr, operate(op, gv->vec[subscr - 1], p));
420 else
421 set(vp, operate(op, varval(vp), p), VAR_READWRITE);
422 update_vars(vp);
423 xfree((ptr_t) vp);
424 if (c != '=')
425 xfree((ptr_t) p);
426 } while ((p = *v++) != NULL);
429 static Char *
430 xset(cp, vp)
431 Char *cp, ***vp;
433 register Char *dp;
435 if (*cp) {
436 dp = Strsave(cp);
437 --(*vp);
438 xfree((ptr_t) ** vp);
439 **vp = dp;
441 return (putn(expr(vp)));
444 static Char *
445 operate(op, vp, p)
446 int op;
447 Char *vp, *p;
449 Char opr[2];
450 Char *vec[5];
451 register Char **v = vec;
452 Char **vecp = v;
453 register int i;
455 if (op != '=') {
456 if (*vp)
457 *v++ = vp;
458 opr[0] = (Char) op;
459 opr[1] = 0;
460 *v++ = opr;
461 if (op == '<' || op == '>')
462 *v++ = opr;
464 *v++ = p;
465 *v++ = 0;
466 i = expr(&vecp);
467 if (*vecp)
468 stderror(ERR_NAME | ERR_EXPRESSION);
469 return (putn(i));
472 static Char *putp, nbuf[50];
474 Char *
475 putn(n)
476 register int n;
478 int num;
480 putp = nbuf;
481 if (n < 0) {
482 n = -n;
483 *putp++ = '-';
485 num = 2; /* confuse lint */
486 if (sizeof(int) == num && ((unsigned int) n) == 0x8000) {
487 *putp++ = '3';
488 n = 2768;
489 #ifdef pdp11
491 #else /* !pdp11 */
493 else {
494 num = 4; /* confuse lint */
495 if (sizeof(int) == num && ((unsigned int) n) == 0x80000000) {
496 *putp++ = '2';
497 n = 147483648;
500 #endif /* pdp11 */
501 putn1(n);
502 *putp = 0;
503 return (Strsave(nbuf));
506 static void
507 putn1(n)
508 register int n;
510 if (n > 9)
511 putn1(n / 10);
512 *putp++ = n % 10 + '0';
516 getn(cp)
517 register Char *cp;
519 register int n;
520 int sign;
522 if (!cp) /* PWP: extra error checking */
523 stderror(ERR_NAME | ERR_BADNUM);
525 sign = 0;
526 if (cp[0] == '+' && cp[1])
527 cp++;
528 if (*cp == '-') {
529 sign++;
530 cp++;
531 if (!Isdigit(*cp))
532 stderror(ERR_NAME | ERR_BADNUM);
534 n = 0;
535 while (Isdigit(*cp))
536 n = n * 10 + *cp++ - '0';
537 if (*cp)
538 stderror(ERR_NAME | ERR_BADNUM);
539 return (sign ? -n : n);
542 Char *
543 value1(var, head)
544 Char *var;
545 struct varent *head;
547 register struct varent *vp;
549 if (!var || !head) /* PWP: extra error checking */
550 return (STRNULL);
552 vp = adrof1(var, head);
553 return ((vp == NULL || vp->vec == NULL || vp->vec[0] == NULL) ?
554 STRNULL : vp->vec[0]);
557 static struct varent *
558 madrof(pat, vp)
559 Char *pat;
560 register struct varent *vp;
562 register struct varent *vp1;
564 for (vp = vp->v_left; vp; vp = vp->v_right) {
565 if (vp->v_left && (vp1 = madrof(pat, vp)) != NULL)
566 return vp1;
567 if (Gmatch(vp->v_name, pat))
568 return vp;
570 return vp;
573 struct varent *
574 adrof1(name, v)
575 register Char *name;
576 register struct varent *v;
578 int cmp;
580 v = v->v_left;
581 while (v && ((cmp = *name - *v->v_name) != 0 ||
582 (cmp = Strcmp(name, v->v_name)) != 0))
583 if (cmp < 0)
584 v = v->v_left;
585 else
586 v = v->v_right;
587 return v;
591 * The caller is responsible for putting value in a safe place
593 void
594 set(var, val, flags)
595 Char *var, *val;
596 int flags;
598 register Char **vec = (Char **) xmalloc((size_t) (2 * sizeof(Char **)));
600 vec[0] = val;
601 vec[1] = 0;
602 set1(var, vec, &shvhed, flags);
605 void
606 set1(var, vec, head, flags)
607 Char *var, **vec;
608 struct varent *head;
609 int flags;
611 register Char **oldv = vec;
613 if ((flags & VAR_NOGLOB) == 0) {
614 gflag = 0;
615 tglob(oldv);
616 if (gflag) {
617 vec = globall(oldv);
618 if (vec == 0) {
619 blkfree(oldv);
620 stderror(ERR_NAME | ERR_NOMATCH);
621 return;
623 blkfree(oldv);
624 gargv = 0;
628 * Uniqueness addition from: Michael Veksler <mveksler@vnet.ibm.com>
630 if ( flags & (VAR_FIRST | VAR_LAST) ) {
632 * Code for -f (VAR_FIRST) and -l (VAR_LAST) options.
633 * Method:
634 * Delete all duplicate words leaving "holes" in the word array (vec).
635 * Then remove the "holes", keeping the order of the words unchanged.
637 if (vec && vec[0] && vec[1]) { /* more than one word ? */
638 int i, j;
639 int num_items;
641 for (num_items = 0; vec[num_items]; num_items++)
642 continue;
643 if (flags & VAR_FIRST) {
644 /* delete duplications, keeping first occurance */
645 for (i = 1; i < num_items; i++)
646 for (j = 0; j < i; j++)
647 /* If have earlier identical item, remove i'th item */
648 if (vec[i] && vec[j] && Strcmp(vec[j], vec[i]) == 0) {
649 free(vec[i]);
650 vec[i] = NULL;
651 break;
653 } else if (flags & VAR_LAST) {
654 /* delete duplications, keeping last occurance */
655 for (i = 0; i < num_items - 1; i++)
656 for (j = i + 1; j < num_items; j++)
657 /* If have later identical item, remove i'th item */
658 if (vec[i] && vec[j] && Strcmp(vec[j], vec[i]) == 0) {
659 /* remove identical item (the first) */
660 free(vec[i]);
661 vec[i] = NULL;
664 /* Compress items - remove empty items */
665 for (j = i = 0; i < num_items; i++)
666 if (vec[i])
667 vec[j++] = vec[i];
669 /* NULL-fy remaining items */
670 for (; j < num_items; j++)
671 vec[j] = NULL;
673 /* don't let the attribute propagate */
674 flags &= ~(VAR_FIRST|VAR_LAST);
676 setq(var, vec, head, flags);
680 void
681 setq(name, vec, p, flags)
682 Char *name, **vec;
683 register struct varent *p;
684 int flags;
686 register struct varent *c;
687 register int f;
689 f = 0; /* tree hangs off the header's left link */
690 while ((c = p->v_link[f]) != 0) {
691 if ((f = *name - *c->v_name) == 0 &&
692 (f = Strcmp(name, c->v_name)) == 0) {
693 if (c->v_flags & VAR_READONLY)
694 stderror(ERR_READONLY|ERR_NAME, c->v_name);
695 blkfree(c->vec);
696 c->v_flags = flags;
697 trim(c->vec = vec);
698 return;
700 p = c;
701 f = f > 0;
703 p->v_link[f] = c = (struct varent *) xmalloc((size_t)sizeof(struct varent));
704 c->v_name = Strsave(name);
705 c->v_flags = flags;
706 c->v_bal = 0;
707 c->v_left = c->v_right = 0;
708 c->v_parent = p;
709 balance(p, f, 0);
710 trim(c->vec = vec);
713 /*ARGSUSED*/
714 void
715 unset(v, c)
716 Char **v;
717 struct command *c;
719 bool did_roe, did_edit;
721 USE(c);
722 did_roe = adrof(STRrecognize_only_executables) != NULL;
723 did_edit = adrof(STRedit) != NULL;
724 unset1(v, &shvhed);
726 #if defined(FILEC) && defined(TIOCSTI)
727 if (adrof(STRfilec) == 0)
728 filec = 0;
729 #endif /* FILEC && TIOCSTI */
731 if (adrof(STRhistchars) == 0) {
732 HIST = '!';
733 HISTSUB = '^';
735 if (adrof(STRpromptchars) == 0) {
736 PRCH = '>';
737 PRCHROOT = '#';
739 if (adrof(STRhistlit) == 0)
740 HistLit = 0;
741 if (adrof(STRloginsh) == 0)
742 loginsh = 0;
743 if (adrof(STRwordchars) == 0)
744 word_chars = STR_WORD_CHARS;
745 if (adrof(STRedit) == 0)
746 editing = 0;
747 if (adrof(STRbackslash_quote) == 0)
748 bslash_quote = 0;
749 if (adrof(STRsymlinks) == 0)
750 symlinks = 0;
751 if (adrof(STRimplicitcd) == 0)
752 implicit_cd = 0;
753 if (adrof(STRkillring) == 0)
754 SetKillRing(0);
755 if (did_edit && noediting && adrof(STRedit) == 0)
756 noediting = 0;
757 if (did_roe && adrof(STRrecognize_only_executables) == 0)
758 tw_cmd_free();
759 #ifdef COLOR_LS_F
760 if (adrof(STRcolor) == 0)
761 set_color_context();
762 #endif /* COLOR_LS_F */
763 #if defined(KANJI) && defined(SHORT_STRINGS) && defined(DSPMBYTE)
764 update_dspmbyte_vars();
765 #endif
766 #ifdef NLS_CATALOGS
767 (void) catclose(catd);
768 nlsinit();
769 #endif /* NLS_CATALOGS */
772 void
773 unset1(v, head)
774 register Char *v[];
775 struct varent *head;
777 register struct varent *vp;
778 register int cnt;
780 while (*++v) {
781 cnt = 0;
782 while ((vp = madrof(*v, head)) != NULL)
783 if (vp->v_flags & VAR_READONLY)
784 stderror(ERR_READONLY|ERR_NAME, vp->v_name);
785 else
786 unsetv1(vp), cnt++;
787 if (cnt == 0)
788 setname(short2str(*v));
792 void
793 unsetv(var)
794 Char *var;
796 register struct varent *vp;
798 if ((vp = adrof1(var, &shvhed)) == 0)
799 udvar(var);
800 unsetv1(vp);
803 static void
804 unsetv1(p)
805 register struct varent *p;
807 register struct varent *c, *pp;
808 register int f;
811 * Free associated memory first to avoid complications.
813 blkfree(p->vec);
814 xfree((ptr_t) p->v_name);
816 * If p is missing one child, then we can move the other into where p is.
817 * Otherwise, we find the predecessor of p, which is guaranteed to have no
818 * right child, copy it into p, and move it's left child into it.
820 if (p->v_right == 0)
821 c = p->v_left;
822 else if (p->v_left == 0)
823 c = p->v_right;
824 else {
825 for (c = p->v_left; c->v_right; c = c->v_right)
826 continue;
827 p->v_name = c->v_name;
828 p->v_flags = c->v_flags;
829 p->vec = c->vec;
830 p = c;
831 c = p->v_left;
835 * Move c into where p is.
837 pp = p->v_parent;
838 f = pp->v_right == p;
839 if ((pp->v_link[f] = c) != 0)
840 c->v_parent = pp;
842 * Free the deleted node, and rebalance.
844 xfree((ptr_t) p);
845 balance(pp, f, 1);
848 void
849 setNS(cp)
850 Char *cp;
852 set(cp, Strsave(STRNULL), VAR_READWRITE);
855 /*ARGSUSED*/
856 void
857 shift(v, c)
858 register Char **v;
859 struct command *c;
861 register struct varent *argv;
862 register Char *name;
864 USE(c);
865 v++;
866 name = *v;
867 if (name == 0)
868 name = STRargv;
869 else
870 (void) strip(name);
871 argv = adrof(name);
872 if (argv == NULL || argv->vec == NULL)
873 udvar(name);
874 if (argv->vec[0] == 0)
875 stderror(ERR_NAME | ERR_NOMORE);
876 lshift(argv->vec, 1);
877 update_vars(name);
880 static Char STRsep[2] = { PATHSEP, '\0' };
882 static void
883 exportpath(val)
884 Char **val;
886 Char *exppath;
887 size_t exppath_size = BUFSIZE;
888 exppath = (Char *)xmalloc(sizeof(Char)*exppath_size);
890 exppath[0] = 0;
891 if (val)
892 while (*val) {
893 while (Strlen(*val) + Strlen(exppath) + 2 > exppath_size) {
894 if ((exppath
895 = (Char *)xrealloc(exppath, sizeof(Char)*(exppath_size *= 2)))
896 == NULL) {
897 xprintf(CGETS(18, 1,
898 "Warning: ridiculously long PATH truncated\n"));
899 break;
902 (void) Strcat(exppath, *val++);
903 if (*val == 0 || eq(*val, STRRparen))
904 break;
905 (void) Strcat(exppath, STRsep);
907 tsetenv(STRKPATH, exppath);
908 free(exppath);
911 #ifndef lint
913 * Lint thinks these have null effect
915 /* macros to do single rotations on node p */
916 # define rright(p) (\
917 t = (p)->v_left,\
918 (t)->v_parent = (p)->v_parent,\
919 (((p)->v_left = t->v_right) != NULL) ?\
920 (t->v_right->v_parent = (p)) : 0,\
921 (t->v_right = (p))->v_parent = t,\
922 (p) = t)
923 # define rleft(p) (\
924 t = (p)->v_right,\
925 ((t)->v_parent = (p)->v_parent,\
926 ((p)->v_right = t->v_left) != NULL) ? \
927 (t->v_left->v_parent = (p)) : 0,\
928 (t->v_left = (p))->v_parent = t,\
929 (p) = t)
930 #else
931 static struct varent *
932 rleft(p)
933 struct varent *p;
935 return (p);
937 static struct varent *
938 rright(p)
939 struct varent *p;
941 return (p);
944 #endif /* ! lint */
948 * Rebalance a tree, starting at p and up.
949 * F == 0 means we've come from p's left child.
950 * D == 1 means we've just done a delete, otherwise an insert.
952 static void
953 balance(p, f, d)
954 register struct varent *p;
955 register int f, d;
957 register struct varent *pp;
959 #ifndef lint
960 register struct varent *t; /* used by the rotate macros */
961 #endif /* !lint */
962 register int ff;
963 #ifdef lint
964 ff = 0; /* Sun's lint is dumb! */
965 #endif
968 * Ok, from here on, p is the node we're operating on; pp is it's parent; f
969 * is the branch of p from which we have come; ff is the branch of pp which
970 * is p.
972 for (; (pp = p->v_parent) != 0; p = pp, f = ff) {
973 ff = pp->v_right == p;
974 if (f ^ d) { /* right heavy */
975 switch (p->v_bal) {
976 case -1: /* was left heavy */
977 p->v_bal = 0;
978 break;
979 case 0: /* was balanced */
980 p->v_bal = 1;
981 break;
982 case 1: /* was already right heavy */
983 switch (p->v_right->v_bal) {
984 case 1: /* sigle rotate */
985 pp->v_link[ff] = rleft(p);
986 p->v_left->v_bal = 0;
987 p->v_bal = 0;
988 break;
989 case 0: /* single rotate */
990 pp->v_link[ff] = rleft(p);
991 p->v_left->v_bal = 1;
992 p->v_bal = -1;
993 break;
994 case -1: /* double rotate */
995 (void) rright(p->v_right);
996 pp->v_link[ff] = rleft(p);
997 p->v_left->v_bal =
998 p->v_bal < 1 ? 0 : -1;
999 p->v_right->v_bal =
1000 p->v_bal > -1 ? 0 : 1;
1001 p->v_bal = 0;
1002 break;
1003 default:
1004 break;
1006 break;
1007 default:
1008 break;
1011 else { /* left heavy */
1012 switch (p->v_bal) {
1013 case 1: /* was right heavy */
1014 p->v_bal = 0;
1015 break;
1016 case 0: /* was balanced */
1017 p->v_bal = -1;
1018 break;
1019 case -1: /* was already left heavy */
1020 switch (p->v_left->v_bal) {
1021 case -1: /* single rotate */
1022 pp->v_link[ff] = rright(p);
1023 p->v_right->v_bal = 0;
1024 p->v_bal = 0;
1025 break;
1026 case 0: /* signle rotate */
1027 pp->v_link[ff] = rright(p);
1028 p->v_right->v_bal = -1;
1029 p->v_bal = 1;
1030 break;
1031 case 1: /* double rotate */
1032 (void) rleft(p->v_left);
1033 pp->v_link[ff] = rright(p);
1034 p->v_left->v_bal =
1035 p->v_bal < 1 ? 0 : -1;
1036 p->v_right->v_bal =
1037 p->v_bal > -1 ? 0 : 1;
1038 p->v_bal = 0;
1039 break;
1040 default:
1041 break;
1043 break;
1044 default:
1045 break;
1049 * If from insert, then we terminate when p is balanced. If from
1050 * delete, then we terminate when p is unbalanced.
1052 if ((p->v_bal == 0) ^ d)
1053 break;
1057 void
1058 plist(p, what)
1059 register struct varent *p;
1060 int what;
1062 register struct varent *c;
1063 register int len;
1065 if (setintr)
1066 #ifdef BSDSIGS
1067 (void) sigsetmask(sigblock((sigmask_t) 0) & ~sigmask(SIGINT));
1068 #else /* !BSDSIGS */
1069 (void) sigrelse(SIGINT);
1070 #endif /* BSDSIGS */
1072 for (;;) {
1073 while (p->v_left)
1074 p = p->v_left;
1076 if (p->v_parent == 0) /* is it the header? */
1077 return;
1078 if ((p->v_flags & what) != 0) {
1079 len = blklen(p->vec);
1080 xprintf("%S\t", p->v_name);
1081 if (len != 1)
1082 xputchar('(');
1083 blkpr(p->vec);
1084 if (len != 1)
1085 xputchar(')');
1086 xputchar('\n');
1088 if (p->v_right) {
1089 p = p->v_right;
1090 continue;
1092 do {
1093 c = p;
1094 p = p->v_parent;
1095 } while (p->v_right == c);
1096 goto x;
1100 #if defined(KANJI) && defined(SHORT_STRINGS) && defined(DSPMBYTE)
1101 bool dspmbyte_ls;
1103 void
1104 update_dspmbyte_vars()
1106 int lp, iskcode;
1107 Char *dstr1;
1108 struct varent *vp;
1110 /* if variable "nokanji" is set, multi-byte display is disabled */
1111 if ((vp = adrof(CHECK_MBYTEVAR)) && !adrof(STRnokanji)) {
1112 _enable_mbdisp = 1;
1113 dstr1 = vp->vec[0];
1114 if(eq (dstr1, STRKSJIS))
1115 iskcode = 1;
1116 else if (eq(dstr1, STRKEUC))
1117 iskcode = 2;
1118 else if (eq(dstr1, STRKBIG5))
1119 iskcode = 3;
1120 else if (eq(dstr1, STRKUTF8))
1121 iskcode = 4;
1122 else if ((dstr1[0] - '0') >= 0 && (dstr1[0] - '0') <= 3) {
1123 iskcode = 0;
1125 else {
1126 xprintf(CGETS(18, 2,
1127 "Warning: unknown multibyte display; using default(euc(JP))\n"));
1128 iskcode = 2;
1130 if (dstr1 && vp->vec[1] && eq(vp->vec[1], STRls))
1131 dspmbyte_ls = 1;
1132 else
1133 dspmbyte_ls = 0;
1134 for (lp = 0; lp < 256 && iskcode > 0; lp++) {
1135 switch (iskcode) {
1136 case 1:
1137 /* Shift-JIS */
1138 _cmap[lp] = _cmap_mbyte[lp];
1139 _mbmap[lp] = _mbmap_sjis[lp];
1140 break;
1141 case 2:
1142 /* 2 ... euc */
1143 _cmap[lp] = _cmap_mbyte[lp];
1144 _mbmap[lp] = _mbmap_euc[lp];
1145 break;
1146 case 3:
1147 /* 3 ... big5 */
1148 _cmap[lp] = _cmap_mbyte[lp];
1149 _mbmap[lp] = _mbmap_big5[lp];
1150 break;
1151 case 4:
1152 /* 4 ... utf8 */
1153 _cmap[lp] = _cmap_mbyte[lp];
1154 _mbmap[lp] = _mbmap_utf8[lp];
1155 break;
1156 default:
1157 xprintf(CGETS(18, 3,
1158 "Warning: unknown multibyte code %d; multibyte disabled\n"),
1159 iskcode);
1160 _cmap[lp] = _cmap_c[lp];
1161 _mbmap[lp] = 0; /* Default map all 0 */
1162 _enable_mbdisp = 0;
1163 break;
1166 if (iskcode == 0) {
1167 /* check original table */
1168 if (Strlen(dstr1) != 256) {
1169 xprintf(CGETS(18, 4,
1170 "Warning: Invalid multibyte table length (%d); multibyte disabled\n"),
1171 Strlen(dstr1));
1172 _enable_mbdisp = 0;
1174 for (lp = 0; lp < 256 && _enable_mbdisp == 1; lp++) {
1175 if (!((dstr1[lp] - '0') >= 0 && (dstr1[lp] - '0') <= 3)) {
1176 xprintf(CGETS(18, 4,
1177 "Warning: bad multibyte code at offset +%d; multibyte diabled\n"),
1178 lp);
1179 _enable_mbdisp = 0;
1180 break;
1183 /* set original table */
1184 for (lp = 0; lp < 256; lp++) {
1185 if (_enable_mbdisp == 1) {
1186 _cmap[lp] = _cmap_mbyte[lp];
1187 _mbmap[lp] = (unsigned short) ((dstr1[lp] - '0') & 0x0f);
1189 else {
1190 _cmap[lp] = _cmap_c[lp];
1191 _mbmap[lp] = 0; /* Default map all 0 */
1196 else {
1197 for (lp = 0; lp < 256; lp++) {
1198 _cmap[lp] = _cmap_c[lp];
1199 _mbmap[lp] = 0; /* Default map all 0 */
1201 _enable_mbdisp = 0;
1202 dspmbyte_ls = 0;
1204 #ifdef MBYTEDEBUG /* Sorry, use for beta testing */
1206 Char mbmapstr[300];
1207 for (lp = 0; lp < 256; lp++) {
1208 mbmapstr[lp] = _mbmap[lp] + '0';
1209 mbmapstr[lp+1] = 0;
1211 set(STRmbytemap, Strsave(mbmapstr), VAR_READWRITE);
1213 #endif /* MBYTEMAP */
1216 /* dspkanji/dspmbyte autosetting */
1217 /* PATCH IDEA FROM Issei.Suzuki VERY THANKS */
1218 void
1219 autoset_dspmbyte(pcp)
1220 Char *pcp;
1222 int i;
1223 struct dspm_autoset_Table {
1224 Char *n;
1225 Char *v;
1226 } dspmt[] = {
1227 { STRLANGEUCJP, STRKEUC },
1228 { STRLANGEUCKR, STRKEUC },
1229 { STRLANGEUCZH, STRKEUC },
1230 { STRLANGEUCJPB, STRKEUC },
1231 { STRLANGEUCKRB, STRKEUC },
1232 { STRLANGEUCZHB, STRKEUC },
1233 { STRLANGSJIS, STRKSJIS },
1234 { STRLANGSJISB, STRKSJIS },
1235 { STRLANGBIG5, STRKBIG5 },
1236 { NULL, NULL }
1239 if (*pcp == '\0')
1240 return;
1242 for (i = 0; dspmt[i].n; i++) {
1243 if (eq(pcp, dspmt[i].n)) {
1244 set(CHECK_MBYTEVAR, Strsave(dspmt[i].v), VAR_READWRITE);
1245 update_dspmbyte_vars();
1246 break;
1250 #endif