source: trunk/third/tcsh/sh.set.c @ 12039

Revision 12039, 25.5 KB checked in by danw, 26 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r12038, which included commits to RCS files with non-trunk default branches.
Line 
1/* $Header: /afs/dev.mit.edu/source/repository/third/tcsh/sh.set.c,v 1.1.1.2 1998-10-03 21:10:08 danw 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.
8 *
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. All advertising materials mentioning features or use of this software
18 *    must display the following acknowledgement:
19 *      This product includes software developed by the University of
20 *      California, Berkeley and its contributors.
21 * 4. Neither the name of the University nor the names of its contributors
22 *    may be used to endorse or promote products derived from this software
23 *    without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * SUCH DAMAGE.
36 */
37#include "sh.h"
38
39RCSID("$Id: sh.set.c,v 1.1.1.2 1998-10-03 21:10:08 danw Exp $")
40
41#include "ed.h"
42#include "tw.h"
43
44extern Char HistLit;
45extern bool GotTermCaps;
46
47static  void             update_vars    __P((Char *));
48static  Char            *getinx         __P((Char *, int *));
49static  void             asx            __P((Char *, int, Char *));
50static  struct varent   *getvx          __P((Char *, int));
51static  Char            *xset           __P((Char *, Char ***));
52static  Char            *operate        __P((int, Char *, Char *));
53static  void             putn1          __P((int));
54static  struct varent   *madrof         __P((Char *, struct varent *));
55static  void             unsetv1        __P((struct varent *));
56static  void             exportpath     __P((Char **));
57static  void             balance        __P((struct varent *, int, int));
58
59/*
60 * C Shell
61 */
62
63static void
64update_vars(vp)
65    Char *vp;
66{
67    if (eq(vp, STRpath)) {
68        exportpath(adrof(STRpath)->vec);
69        dohash(NULL, NULL);
70    }
71    else if (eq(vp, STRhistchars)) {
72        register Char *pn = varval(vp);
73
74        HIST = *pn++;
75        HISTSUB = *pn;
76    }
77    else if (eq(vp, STRpromptchars)) {
78        register Char *pn = varval(vp);
79
80        PRCH = *pn++;
81        PRCHROOT = *pn;
82    }
83    else if (eq(vp, STRhistlit)) {
84        HistLit = 1;
85    }
86    else if (eq(vp, STRuser)) {
87        tsetenv(STRKUSER, varval(vp));
88        tsetenv(STRLOGNAME, varval(vp));
89    }
90    else if (eq(vp, STRgroup)) {
91        tsetenv(STRKGROUP, varval(vp));
92    }
93    else if (eq(vp, STRwordchars)) {
94        word_chars = varval(vp);
95    }
96    else if (eq(vp, STRloginsh)) {
97        loginsh = 1;
98    }
99    else if (eq(vp, STRsymlinks)) {
100        register Char *pn = varval(vp);
101
102        if (eq(pn, STRignore))
103            symlinks = SYM_IGNORE;
104        else if (eq(pn, STRexpand))
105            symlinks = SYM_EXPAND;
106        else if (eq(pn, STRchase))
107            symlinks = SYM_CHASE;
108        else
109            symlinks = 0;
110    }
111    else if (eq(vp, STRterm)) {
112        Char *cp = varval(vp);
113        tsetenv(STRKTERM, cp);
114#ifdef DOESNT_WORK_RIGHT
115        cp = getenv("TERMCAP");
116        if (cp && (*cp != '/')) /* if TERMCAP and not a path */
117            Unsetenv(STRTERMCAP);
118#endif /* DOESNT_WORK_RIGHT */
119        GotTermCaps = 0;
120        if (noediting && Strcmp(cp, STRnetwork) != 0 &&
121            Strcmp(cp, STRunknown) != 0 && Strcmp(cp, STRdumb) != 0) {
122            editing = 1;
123            noediting = 0;
124            set(STRedit, Strsave(STRNULL), VAR_READWRITE);
125        }
126        ed_Init();              /* reset the editor */
127    }
128    else if (eq(vp, STRhome)) {
129        register Char *cp;
130
131        cp = Strsave(varval(vp));       /* get the old value back */
132
133        /*
134         * convert to cononical pathname (possibly resolving symlinks)
135         */
136        cp = dcanon(cp, cp);
137
138        set(vp, Strsave(cp), VAR_READWRITE);    /* have to save the new val */
139
140        /* and now mirror home with HOME */
141        tsetenv(STRKHOME, cp);
142        /* fix directory stack for new tilde home */
143        dtilde();
144        xfree((ptr_t) cp);
145    }
146    else if (eq(vp, STRedit)) {
147        editing = 1;
148        noediting = 0;
149        /* PWP: add more stuff in here later */
150    }
151    else if (eq(vp, STRshlvl)) {
152        tsetenv(STRKSHLVL, varval(vp));
153    }
154    else if (eq(vp, STRbackslash_quote)) {
155        bslash_quote = 1;
156    }
157    else if (eq(vp, STRdirstack)) {
158        dsetstack();
159    }
160    else if (eq(vp, STRrecognize_only_executables)) {
161        tw_cmd_free();
162    }
163#ifndef HAVENOUTMP
164    else if (eq(vp, STRwatch)) {
165        resetwatch();
166    }
167#endif /* HAVENOUTMP */
168    else if (eq(vp, STRimplicitcd)) {
169        implicit_cd = ((eq(varval(vp), STRverbose)) ? 2 : 1);
170    }
171#ifdef COLOR_LS_F
172    else if (eq(vp, STRcolor)) {
173        set_color_context();
174    }
175#endif /* COLOR_LS_F */
176#if defined(KANJI) && defined(SHORT_STRINGS) && defined(DSPMBYTE)
177    else if(eq(vp, CHECK_MBYTEVAR) || eq(vp, STRnokanji)) {
178        update_dspmbyte_vars();
179    }
180#endif
181}
182
183
184/*ARGSUSED*/
185void
186doset(v, c)
187    register Char **v;
188    struct command *c;
189{
190    register Char *p;
191    Char   *vp, op;
192    Char  **vecp;
193    bool    hadsub;
194    int     subscr;
195    int     flags = VAR_READWRITE;
196    bool    first_match = 0;
197    bool    last_match = 0;
198    bool    changed = 0;
199
200    USE(c);
201    v++;
202    do {
203        changed = 0;
204        /*
205         * Readonly addition From: Tim P. Starrin <noid@cyborg.larc.nasa.gov>
206         */
207        if (*v && eq(*v, STRmr)) {
208            flags = VAR_READONLY;
209            v++;
210            changed = 1;
211        }
212        if (*v && eq(*v, STRmf) && !last_match) {
213            first_match = 1;
214            v++;
215            changed = 1;
216        }
217        if (*v && eq(*v, STRml) && !first_match) {
218            last_match = 1;
219            v++;
220            changed = 1;
221        }
222    } while(changed);
223    p = *v++;
224    if (p == 0) {
225        plist(&shvhed, flags);
226        return;
227    }
228    do {
229        hadsub = 0;
230        vp = p;
231        if (letter(*p))
232            for (; alnum(*p); p++)
233                continue;
234        if (vp == p || !letter(*vp))
235            stderror(ERR_NAME | ERR_VARBEGIN);
236        if ((p - vp) > MAXVARLEN) {
237            stderror(ERR_NAME | ERR_VARTOOLONG);
238            return;
239        }
240        if (*p == '[') {
241            hadsub++;
242            p = getinx(p, &subscr);
243        }
244        if ((op = *p) != 0) {
245            *p++ = 0;
246            if (*p == 0 && *v && **v == '(')
247                p = *v++;
248        }
249        else if (*v && eq(*v, STRequal)) {
250            op = '=', v++;
251            if (*v)
252                p = *v++;
253        }
254        if (op && op != '=')
255            stderror(ERR_NAME | ERR_SYNTAX);
256        if (eq(p, STRLparen)) {
257            register Char **e = v;
258
259            if (hadsub)
260                stderror(ERR_NAME | ERR_SYNTAX);
261            for (;;) {
262                if (!*e)
263                    stderror(ERR_NAME | ERR_MISSING, ')');
264                if (**e == ')')
265                    break;
266                e++;
267            }
268            p = *e;
269            *e = 0;
270            vecp = saveblk(v);
271            if (first_match)
272               flags |= VAR_FIRST;
273            else if (last_match)
274               flags |= VAR_LAST;
275
276            set1(vp, vecp, &shvhed, flags);
277            *e = p;
278            v = e + 1;
279        }
280        else if (hadsub)
281            asx(vp, subscr, Strsave(p));
282        else
283            set(vp, Strsave(p), flags);
284        update_vars(vp);
285    } while ((p = *v++) != NULL);
286}
287
288static Char *
289getinx(cp, ip)
290    register Char *cp;
291    register int *ip;
292{
293    *ip = 0;
294    *cp++ = 0;
295    while (*cp && Isdigit(*cp))
296        *ip = *ip * 10 + *cp++ - '0';
297    if (*cp++ != ']')
298        stderror(ERR_NAME | ERR_SUBSCRIPT);
299    return (cp);
300}
301
302static void
303asx(vp, subscr, p)
304    Char   *vp;
305    int     subscr;
306    Char   *p;
307{
308    register struct varent *v = getvx(vp, subscr);
309
310    if (v->v_flags & VAR_READONLY)
311        stderror(ERR_READONLY|ERR_NAME, v->v_name);
312    xfree((ptr_t) v->vec[subscr - 1]);
313    v->vec[subscr - 1] = globone(p, G_APPEND);
314}
315
316static struct varent *
317getvx(vp, subscr)
318    Char   *vp;
319    int     subscr;
320{
321    register struct varent *v = adrof(vp);
322
323    if (v == 0)
324        udvar(vp);
325    if (subscr < 1 || subscr > blklen(v->vec))
326        stderror(ERR_NAME | ERR_RANGE);
327    return (v);
328}
329
330/*ARGSUSED*/
331void
332dolet(v, dummy)
333    Char  **v;
334    struct command *dummy;
335{
336    register Char *p;
337    Char   *vp, c, op;
338    bool    hadsub;
339    int     subscr;
340
341    USE(dummy);
342    v++;
343    p = *v++;
344    if (p == 0) {
345        prvars();
346        return;
347    }
348    do {
349        hadsub = 0;
350        vp = p;
351        if (letter(*p))
352            for (; alnum(*p); p++)
353                continue;
354        if (vp == p || !letter(*vp))
355            stderror(ERR_NAME | ERR_VARBEGIN);
356        if ((p - vp) > MAXVARLEN)
357            stderror(ERR_NAME | ERR_VARTOOLONG);
358        if (*p == '[') {
359            hadsub++;
360            p = getinx(p, &subscr);
361        }
362        if (*p == 0 && *v)
363            p = *v++;
364        if ((op = *p) != 0)
365            *p++ = 0;
366        else
367            stderror(ERR_NAME | ERR_ASSIGN);
368
369        /*
370         * if there is no expression after the '=' then print a "Syntax Error"
371         * message - strike
372         */
373        if (*p == '\0' && *v == NULL)
374            stderror(ERR_NAME | ERR_ASSIGN);
375
376        vp = Strsave(vp);
377        if (op == '=') {
378            c = '=';
379            p = xset(p, &v);
380        }
381        else {
382            c = *p++;
383            if (any("+-", c)) {
384                if (c != op || *p)
385                    stderror(ERR_NAME | ERR_UNKNOWNOP);
386                p = Strsave(STR1);
387            }
388            else {
389                if (any("<>", op)) {
390                    if (c != op)
391                        stderror(ERR_NAME | ERR_UNKNOWNOP);
392                    c = *p++;
393                    stderror(ERR_NAME | ERR_SYNTAX);
394                }
395                if (c != '=')
396                    stderror(ERR_NAME | ERR_UNKNOWNOP);
397                p = xset(p, &v);
398            }
399        }
400        if (op == '=') {
401            if (hadsub)
402                asx(vp, subscr, p);
403            else
404                set(vp, p, VAR_READWRITE);
405        }
406        else if (hadsub) {
407            struct varent *gv = getvx(vp, subscr);
408
409            asx(vp, subscr, operate(op, gv->vec[subscr - 1], p));
410        }
411        else
412            set(vp, operate(op, varval(vp), p), VAR_READWRITE);
413        update_vars(vp);
414        xfree((ptr_t) vp);
415        if (c != '=')
416            xfree((ptr_t) p);
417    } while ((p = *v++) != NULL);
418}
419
420static Char *
421xset(cp, vp)
422    Char   *cp, ***vp;
423{
424    register Char *dp;
425
426    if (*cp) {
427        dp = Strsave(cp);
428        --(*vp);
429        xfree((ptr_t) ** vp);
430        **vp = dp;
431    }
432    return (putn(expr(vp)));
433}
434
435static Char *
436operate(op, vp, p)
437    int     op;
438    Char    *vp, *p;
439{
440    Char    opr[2];
441    Char   *vec[5];
442    register Char **v = vec;
443    Char  **vecp = v;
444    register int i;
445
446    if (op != '=') {
447        if (*vp)
448            *v++ = vp;
449        opr[0] = (Char) op;
450        opr[1] = 0;
451        *v++ = opr;
452        if (op == '<' || op == '>')
453            *v++ = opr;
454    }
455    *v++ = p;
456    *v++ = 0;
457    i = expr(&vecp);
458    if (*vecp)
459        stderror(ERR_NAME | ERR_EXPRESSION);
460    return (putn(i));
461}
462
463static Char *putp, nbuf[50];
464
465Char   *
466putn(n)
467    register int n;
468{
469    int     num;
470
471    putp = nbuf;
472    if (n < 0) {
473        n = -n;
474        *putp++ = '-';
475    }
476    num = 2;                    /* confuse lint */
477    if (sizeof(int) == num && ((unsigned int) n) == 0x8000) {
478        *putp++ = '3';
479        n = 2768;
480#ifdef pdp11
481    }
482#else /* !pdp11 */
483    }
484    else {
485        num = 4;                /* confuse lint */
486        if (sizeof(int) == num && ((unsigned int) n) == 0x80000000) {
487            *putp++ = '2';
488            n = 147483648;
489        }
490    }
491#endif /* pdp11 */
492    putn1(n);
493    *putp = 0;
494    return (Strsave(nbuf));
495}
496
497static void
498putn1(n)
499    register int n;
500{
501    if (n > 9)
502        putn1(n / 10);
503    *putp++ = n % 10 + '0';
504}
505
506int
507getn(cp)
508    register Char *cp;
509{
510    register int n;
511    int     sign;
512
513    if (!cp)                    /* PWP: extra error checking */
514        stderror(ERR_NAME | ERR_BADNUM);
515
516    sign = 0;
517    if (cp[0] == '+' && cp[1])
518        cp++;
519    if (*cp == '-') {
520        sign++;
521        cp++;
522        if (!Isdigit(*cp))
523            stderror(ERR_NAME | ERR_BADNUM);
524    }
525    n = 0;
526    while (Isdigit(*cp))
527        n = n * 10 + *cp++ - '0';
528    if (*cp)
529        stderror(ERR_NAME | ERR_BADNUM);
530    return (sign ? -n : n);
531}
532
533Char   *
534value1(var, head)
535    Char   *var;
536    struct varent *head;
537{
538    register struct varent *vp;
539
540    if (!var || !head)          /* PWP: extra error checking */
541        return (STRNULL);
542
543    vp = adrof1(var, head);
544    return (vp == 0 || vp->vec[0] == 0 ? STRNULL : vp->vec[0]);
545}
546
547static struct varent *
548madrof(pat, vp)
549    Char   *pat;
550    register struct varent *vp;
551{
552    register struct varent *vp1;
553
554    for (vp = vp->v_left; vp; vp = vp->v_right) {
555        if (vp->v_left && (vp1 = madrof(pat, vp)) != NULL)
556            return vp1;
557        if (Gmatch(vp->v_name, pat))
558            return vp;
559    }
560    return vp;
561}
562
563struct varent *
564adrof1(name, v)
565    register Char *name;
566    register struct varent *v;
567{
568    int cmp;
569
570    v = v->v_left;
571    while (v && ((cmp = *name - *v->v_name) != 0 ||
572                 (cmp = Strcmp(name, v->v_name)) != 0))
573        if (cmp < 0)
574            v = v->v_left;
575        else
576            v = v->v_right;
577    return v;
578}
579
580/*
581 * The caller is responsible for putting value in a safe place
582 */
583void
584set(var, val, flags)
585    Char   *var, *val;
586    int    flags;
587{
588    register Char **vec = (Char **) xmalloc((size_t) (2 * sizeof(Char **)));
589
590    vec[0] = val;
591    vec[1] = 0;
592    set1(var, vec, &shvhed, flags);
593}
594
595void
596set1(var, vec, head, flags)
597    Char   *var, **vec;
598    struct varent *head;
599    int flags;
600{
601    register Char **oldv = vec;
602
603    if ((flags & VAR_NOGLOB) == 0) {
604        gflag = 0;
605        tglob(oldv);
606        if (gflag) {
607            vec = globall(oldv);
608            if (vec == 0) {
609                blkfree(oldv);
610                stderror(ERR_NAME | ERR_NOMATCH);
611                return;
612            }
613            blkfree(oldv);
614            gargv = 0;
615        }
616    }
617    /*
618     * Uniqueness addition from: Michael Veksler <mveksler@vnet.ibm.com>
619     */
620    if ( flags & (VAR_FIRST | VAR_LAST) ) {
621        /*
622         * Code for -f (VAR_FIRST) and -l (VAR_LAST) options.
623         * Method:
624         *  Delete all duplicate words leaving "holes" in the word array (vec).
625         *  Then remove the "holes", keeping the order of the words unchanged.
626         */
627        if (vec && vec[0] && vec[1]) { /* more than one word ? */
628            int i, j;
629            int num_items;
630
631            for (num_items = 0; vec[num_items]; num_items++)
632                continue;
633            if (flags & VAR_FIRST) {
634                /* delete duplications, keeping first occurance */
635                for (i = 1; i < num_items; i++)
636                    for (j = 0; j < i; j++)
637                        /* If have earlier identical item, remove i'th item */
638                        if (vec[i] && vec[j] && Strcmp(vec[j], vec[i]) == 0) {
639                            free(vec[i]);
640                            vec[i] = NULL;
641                            break;
642                        }
643            } else if (flags & VAR_LAST) {
644              /* delete duplications, keeping last occurance */
645                for (i = 0; i < num_items - 1; i++)
646                    for (j = i + 1; j < num_items; j++)
647                        /* If have later identical item, remove i'th item */
648                        if (vec[i] && vec[j] && Strcmp(vec[j], vec[i]) == 0) {
649                            /* remove identical item (the first) */
650                            free(vec[i]);
651                            vec[i] = NULL;
652                        }
653            }
654            /* Compress items - remove empty items */
655            for (j = i = 0; i < num_items; i++)
656               if (vec[i])
657                  vec[j++] = vec[i];
658
659            /* NULL-fy remaining items */
660            for (; j < num_items; j++)
661                 vec[j] = NULL;
662        }
663        /* don't let the attribute propagate */
664        flags &= ~(VAR_FIRST|VAR_LAST);
665    }
666    setq(var, vec, head, flags);
667}
668
669
670void
671setq(name, vec, p, flags)
672    Char   *name, **vec;
673    register struct varent *p;
674    int flags;
675{
676    register struct varent *c;
677    register int f;
678
679    f = 0;                      /* tree hangs off the header's left link */
680    while ((c = p->v_link[f]) != 0) {
681        if ((f = *name - *c->v_name) == 0 &&
682            (f = Strcmp(name, c->v_name)) == 0) {
683            if (c->v_flags & VAR_READONLY)
684                stderror(ERR_READONLY|ERR_NAME, c->v_name);
685            blkfree(c->vec);
686            c->v_flags = flags;
687            trim(c->vec = vec);
688            return;
689        }
690        p = c;
691        f = f > 0;
692    }
693    p->v_link[f] = c = (struct varent *) xmalloc((size_t)sizeof(struct varent));
694    c->v_name = Strsave(name);
695    c->v_flags = flags;
696    c->v_bal = 0;
697    c->v_left = c->v_right = 0;
698    c->v_parent = p;
699    balance(p, f, 0);
700    trim(c->vec = vec);
701}
702
703/*ARGSUSED*/
704void
705unset(v, c)
706    Char   **v;
707    struct command *c;
708{
709    bool did_roe, did_edit;
710
711    USE(c);
712    did_roe = adrof(STRrecognize_only_executables) != NULL;
713    did_edit = adrof(STRedit) != NULL;
714    unset1(v, &shvhed);
715    if (adrof(STRhistchars) == 0) {
716        HIST = '!';
717        HISTSUB = '^';
718    }
719    if (adrof(STRpromptchars) == 0) {
720        PRCH = '>';
721        PRCHROOT = '#';
722    }
723    if (adrof(STRhistlit) == 0)
724        HistLit = 0;
725    if (adrof(STRloginsh) == 0)
726        loginsh = 0;
727    if (adrof(STRwordchars) == 0)
728        word_chars = STR_WORD_CHARS;
729    if (adrof(STRedit) == 0)
730        editing = 0;
731    if (adrof(STRbackslash_quote) == 0)
732        bslash_quote = 0;
733    if (adrof(STRsymlinks) == 0)
734        symlinks = 0;
735    if (adrof(STRimplicitcd) == 0)
736        implicit_cd = 0;
737    if (did_edit && noediting && adrof(STRedit) == 0)
738        noediting = 0;
739    if (did_roe && adrof(STRrecognize_only_executables) == 0)
740        tw_cmd_free();
741#ifdef COLOR_LS_F
742    if (adrof(STRcolor) == 0)
743        set_color_context();
744#endif /* COLOR_LS_F */
745#if defined(KANJI) && defined(SHORT_STRINGS) && defined(DSPMBYTE)
746    update_dspmbyte_vars();
747#endif
748}
749
750void
751unset1(v, head)
752    register Char *v[];
753    struct varent *head;
754{
755    register struct varent *vp;
756    register int cnt;
757
758    while (*++v) {
759        cnt = 0;
760        while ((vp = madrof(*v, head)) != NULL)
761            if (vp->v_flags & VAR_READONLY)
762                stderror(ERR_READONLY|ERR_NAME, vp->v_name);
763            else
764                unsetv1(vp), cnt++;
765        if (cnt == 0)
766            setname(short2str(*v));
767    }
768}
769
770void
771unsetv(var)
772    Char   *var;
773{
774    register struct varent *vp;
775
776    if ((vp = adrof1(var, &shvhed)) == 0)
777        udvar(var);
778    unsetv1(vp);
779}
780
781static void
782unsetv1(p)
783    register struct varent *p;
784{
785    register struct varent *c, *pp;
786    register int f;
787
788    /*
789     * Free associated memory first to avoid complications.
790     */
791    blkfree(p->vec);
792    xfree((ptr_t) p->v_name);
793    /*
794     * If p is missing one child, then we can move the other into where p is.
795     * Otherwise, we find the predecessor of p, which is guaranteed to have no
796     * right child, copy it into p, and move it's left child into it.
797     */
798    if (p->v_right == 0)
799        c = p->v_left;
800    else if (p->v_left == 0)
801        c = p->v_right;
802    else {
803        for (c = p->v_left; c->v_right; c = c->v_right)
804            continue;
805        p->v_name = c->v_name;
806        p->v_flags = c->v_flags;
807        p->vec = c->vec;
808        p = c;
809        c = p->v_left;
810    }
811
812    /*
813     * Move c into where p is.
814     */
815    pp = p->v_parent;
816    f = pp->v_right == p;
817    if ((pp->v_link[f] = c) != 0)
818        c->v_parent = pp;
819    /*
820     * Free the deleted node, and rebalance.
821     */
822    xfree((ptr_t) p);
823    balance(pp, f, 1);
824}
825
826void
827setNS(cp)
828    Char   *cp;
829{
830    set(cp, Strsave(STRNULL), VAR_READWRITE);
831}
832
833/*ARGSUSED*/
834void
835shift(v, c)
836    register Char **v;
837    struct command *c;
838{
839    register struct varent *argv;
840    register Char *name;
841
842    USE(c);
843    v++;
844    name = *v;
845    if (name == 0)
846        name = STRargv;
847    else
848        (void) strip(name);
849    argv = adrof(name);
850    if (argv == 0)
851        udvar(name);
852    if (argv->vec[0] == 0)
853        stderror(ERR_NAME | ERR_NOMORE);
854    lshift(argv->vec, 1);
855    update_vars(name);
856}
857
858static Char STRsep[2] = { PATHSEP, '\0' };
859
860static void
861exportpath(val)
862    Char  **val;
863{
864  Char          *exppath;
865  size_t        exppath_size = BUFSIZE;
866  exppath = (Char *)xmalloc(sizeof(Char)*exppath_size);
867
868    exppath[0] = 0;
869    if (val)
870        while (*val) {
871          while (Strlen(*val) + Strlen(exppath) + 2 > exppath_size) {
872            if ((exppath
873                 = (Char *)xrealloc(exppath, sizeof(Char)*(exppath_size *= 2)))
874                 == NULL) {
875                xprintf(CGETS(18, 1,
876                              "Warning: ridiculously long PATH truncated\n"));
877                break;
878              }
879            }
880            (void) Strcat(exppath, *val++);
881            if (*val == 0 || eq(*val, STRRparen))
882              break;
883            (void) Strcat(exppath, STRsep);
884          }
885  tsetenv(STRKPATH, exppath);
886  free(exppath);
887}
888
889#ifndef lint
890 /*
891  * Lint thinks these have null effect
892  */
893 /* macros to do single rotations on node p */
894# define rright(p) (\
895        t = (p)->v_left,\
896        (t)->v_parent = (p)->v_parent,\
897        (((p)->v_left = t->v_right) != NULL) ?\
898            (t->v_right->v_parent = (p)) : 0,\
899        (t->v_right = (p))->v_parent = t,\
900        (p) = t)
901# define rleft(p) (\
902        t = (p)->v_right,\
903        ((t)->v_parent = (p)->v_parent,\
904        ((p)->v_right = t->v_left) != NULL) ? \
905                (t->v_left->v_parent = (p)) : 0,\
906        (t->v_left = (p))->v_parent = t,\
907        (p) = t)
908#else
909static struct varent *
910rleft(p)
911    struct varent *p;
912{
913    return (p);
914}
915static struct varent *
916rright(p)
917    struct varent *p;
918{
919    return (p);
920}
921
922#endif /* ! lint */
923
924
925/*
926 * Rebalance a tree, starting at p and up.
927 * F == 0 means we've come from p's left child.
928 * D == 1 means we've just done a delete, otherwise an insert.
929 */
930static void
931balance(p, f, d)
932    register struct varent *p;
933    register int f, d;
934{
935    register struct varent *pp;
936
937#ifndef lint
938    register struct varent *t;  /* used by the rotate macros */
939#endif /* !lint */
940    register int ff;
941#ifdef lint
942    ff = 0;     /* Sun's lint is dumb! */
943#endif
944
945    /*
946     * Ok, from here on, p is the node we're operating on; pp is it's parent; f
947     * is the branch of p from which we have come; ff is the branch of pp which
948     * is p.
949     */
950    for (; (pp = p->v_parent) != 0; p = pp, f = ff) {
951        ff = pp->v_right == p;
952        if (f ^ d) {            /* right heavy */
953            switch (p->v_bal) {
954            case -1:            /* was left heavy */
955                p->v_bal = 0;
956                break;
957            case 0:             /* was balanced */
958                p->v_bal = 1;
959                break;
960            case 1:             /* was already right heavy */
961                switch (p->v_right->v_bal) {
962                case 1: /* sigle rotate */
963                    pp->v_link[ff] = rleft(p);
964                    p->v_left->v_bal = 0;
965                    p->v_bal = 0;
966                    break;
967                case 0: /* single rotate */
968                    pp->v_link[ff] = rleft(p);
969                    p->v_left->v_bal = 1;
970                    p->v_bal = -1;
971                    break;
972                case -1:        /* double rotate */
973                    (void) rright(p->v_right);
974                    pp->v_link[ff] = rleft(p);
975                    p->v_left->v_bal =
976                        p->v_bal < 1 ? 0 : -1;
977                    p->v_right->v_bal =
978                        p->v_bal > -1 ? 0 : 1;
979                    p->v_bal = 0;
980                    break;
981                default:
982                    break;
983                }
984                break;
985            default:
986                break;
987            }
988        }
989        else {                  /* left heavy */
990            switch (p->v_bal) {
991            case 1:             /* was right heavy */
992                p->v_bal = 0;
993                break;
994            case 0:             /* was balanced */
995                p->v_bal = -1;
996                break;
997            case -1:            /* was already left heavy */
998                switch (p->v_left->v_bal) {
999                case -1:        /* single rotate */
1000                    pp->v_link[ff] = rright(p);
1001                    p->v_right->v_bal = 0;
1002                    p->v_bal = 0;
1003                    break;
1004                case 0: /* signle rotate */
1005                    pp->v_link[ff] = rright(p);
1006                    p->v_right->v_bal = -1;
1007                    p->v_bal = 1;
1008                    break;
1009                case 1: /* double rotate */
1010                    (void) rleft(p->v_left);
1011                    pp->v_link[ff] = rright(p);
1012                    p->v_left->v_bal =
1013                        p->v_bal < 1 ? 0 : -1;
1014                    p->v_right->v_bal =
1015                        p->v_bal > -1 ? 0 : 1;
1016                    p->v_bal = 0;
1017                    break;
1018                default:
1019                    break;
1020                }
1021                break;
1022            default:
1023                break;
1024            }
1025        }
1026        /*
1027         * If from insert, then we terminate when p is balanced. If from
1028         * delete, then we terminate when p is unbalanced.
1029         */
1030        if ((p->v_bal == 0) ^ d)
1031            break;
1032    }
1033}
1034
1035void
1036plist(p, what)
1037    register struct varent *p;
1038    int what;
1039{
1040    register struct varent *c;
1041    register int len;
1042
1043    if (setintr)
1044#ifdef BSDSIGS
1045        (void) sigsetmask(sigblock((sigmask_t) 0) & ~sigmask(SIGINT));
1046#else /* !BSDSIGS */
1047        (void) sigrelse(SIGINT);
1048#endif /* BSDSIGS */
1049
1050    for (;;) {
1051        while (p->v_left)
1052            p = p->v_left;
1053x:
1054        if (p->v_parent == 0)   /* is it the header? */
1055            return;
1056        if ((p->v_flags & what) != 0) {
1057            len = blklen(p->vec);
1058            xprintf("%S\t", p->v_name);
1059            if (len != 1)
1060                xputchar('(');
1061            blkpr(p->vec);
1062            if (len != 1)
1063                xputchar(')');
1064            xputchar('\n');
1065        }
1066        if (p->v_right) {
1067            p = p->v_right;
1068            continue;
1069        }
1070        do {
1071            c = p;
1072            p = p->v_parent;
1073        } while (p->v_right == c);
1074        goto x;
1075    }
1076}
1077
1078#if defined(KANJI) && defined(SHORT_STRINGS) && defined(DSPMBYTE)
1079void
1080update_dspmbyte_vars()
1081{
1082    int lp, iskcode;
1083    Char *dstr1;
1084
1085    /* if variable "nokanji" is set, multi-byte display is disabled */
1086    if (adrof(CHECK_MBYTEVAR) && !adrof(STRnokanji)) {
1087        _enable_mbdisp = 1;
1088        dstr1 = varval(CHECK_MBYTEVAR);
1089        if(eq (dstr1, STRKSJIS))
1090            iskcode = 1;
1091        else if (eq(dstr1, STRKEUC))
1092            iskcode = 2;
1093        else if ((dstr1[0] - '0') >= 0 && (dstr1[0] - '0') <= 3) {
1094            iskcode = 0;
1095        }
1096        else {
1097            xprintf(CGETS(18, 2,
1098               "Warning: unknown multibyte display; using default(euc(JP))\n"));
1099            iskcode = 2;
1100        }
1101        for (lp = 0; lp < 256 && iskcode > 0; lp++) {
1102            switch (iskcode) {
1103            case 1:
1104                /* Shift-JIS */
1105                _cmap[lp] = _cmap_mbyte[lp];
1106                _mbmap[lp] = _mbmap_sjis[lp];
1107                break;
1108            case 2:
1109                /* 2 ... euc */
1110                _cmap[lp] = _cmap_mbyte[lp];
1111                _mbmap[lp] = _mbmap_euc[lp];
1112                break;
1113            default:
1114                xprintf(CGETS(18, 3,
1115                    "Warning: unknown multibyte code %d; multibyte disabled\n"),
1116                    iskcode);
1117                _cmap[lp] = _cmap_c[lp];
1118                _mbmap[lp] = 0; /* Default map all 0 */
1119                _enable_mbdisp = 0;
1120                break;
1121            }
1122        }
1123        if (iskcode == 0) {
1124            /* check original table */
1125            if (Strlen(dstr1) != 256) {
1126                xprintf(CGETS(18, 4,
1127       "Warning: Invalid multibyte table length (%d); multibyte disabled\n"),
1128                    Strlen(dstr1));
1129                _enable_mbdisp = 0;
1130            }
1131            for (lp = 0; lp < 256 && _enable_mbdisp == 1; lp++) {
1132                if (!((dstr1[lp] - '0') >= 0 && (dstr1[lp] - '0') <= 3)) {
1133                    xprintf(CGETS(18, 4,
1134           "Warning: bad multibyte code at offset +%d; multibyte diabled\n"),
1135                        lp);
1136                    _enable_mbdisp = 0;
1137                    break;
1138                }
1139            }
1140            /* set original table */
1141            for (lp = 0; lp < 256; lp++) {
1142                if (_enable_mbdisp == 1) {
1143                    _cmap[lp] = _cmap_mbyte[lp];
1144                    _mbmap[lp] = (unsigned short) ((dstr1[lp] - '0') & 0x0f);
1145                }
1146                else {
1147                    _cmap[lp] = _cmap_c[lp];
1148                    _mbmap[lp] = 0;     /* Default map all 0 */
1149                }
1150            }
1151        }
1152    }
1153    else {
1154        for (lp = 0; lp < 256; lp++) {
1155            _cmap[lp] = _cmap_c[lp];
1156            _mbmap[lp] = 0;     /* Default map all 0 */
1157        }
1158        _enable_mbdisp = 0;
1159    }
1160#ifdef MBYTEDEBUG       /* Sorry, use for beta testing */
1161    {
1162        Char mbmapstr[300];
1163        for (lp = 0; lp < 256; lp++) {
1164            mbmapstr[lp] = _mbmap[lp] + '0';
1165            mbmapstr[lp+1] = 0;
1166        }
1167        set(STRmbytemap, Strsave(mbmapstr), VAR_READWRITE);
1168    }
1169#endif /* MBYTEMAP */
1170}
1171
1172/* dspkanji/dspmbyte autosetting */
1173/* PATCH IDEA FROM Issei.Suzuki VERY THANKS */
1174void
1175autoset_dspmbyte(pcp)
1176    Char *pcp;
1177{
1178    int i;
1179    struct dspm_autoset_Table {
1180        Char *n;
1181        Char *v;
1182    } dspmt[] = {
1183        { STRLANGEUC, STRKEUC },
1184        { STRLANGEUCB, STRKEUC },
1185        { STRLANGSJIS, STRKSJIS },
1186        { STRLANGSJISB, STRKSJIS },
1187        { NULL, NULL }
1188    };
1189
1190    if (*pcp == '\0')
1191        return;
1192
1193    for (i = 0; dspmt[i].n; i++) {
1194        if (eq(pcp, dspmt[i].n)) {
1195            set(CHECK_MBYTEVAR, Strsave(dspmt[i].v), VAR_READWRITE);
1196            update_dspmbyte_vars();
1197            break;
1198        }
1199    }
1200}
1201#endif
Note: See TracBrowser for help on using the repository browser.