diff options
author | David E. O'Brien <obrien@FreeBSD.org> | 2000-04-15 04:41:27 +0000 |
---|---|---|
committer | David E. O'Brien <obrien@FreeBSD.org> | 2000-04-15 04:41:27 +0000 |
commit | c80476e4c3e6730697b9424f88dfa74d1907cabd (patch) | |
tree | 7679c440a91912ee9586cee3ebab24596c0fe1c4 /contrib/tcsh/sh.set.c | |
download | src-c80476e4c3e6730697b9424f88dfa74d1907cabd.tar.gz src-c80476e4c3e6730697b9424f88dfa74d1907cabd.zip |
Import the latest version of the 44BSD C-shell -- tcsh-6.09.vendor/tcsh/6.09
Notes
Notes:
svn path=/vendor/tcsh/dist/; revision=59243
svn path=/vendor/tcsh/6.09/; revision=59245; tag=vendor/tcsh/6.09
Diffstat (limited to 'contrib/tcsh/sh.set.c')
-rw-r--r-- | contrib/tcsh/sh.set.c | 1209 |
1 files changed, 1209 insertions, 0 deletions
diff --git a/contrib/tcsh/sh.set.c b/contrib/tcsh/sh.set.c new file mode 100644 index 000000000000..76fe77fbb676 --- /dev/null +++ b/contrib/tcsh/sh.set.c @@ -0,0 +1,1209 @@ +/* $Header: /src/pub/tcsh/sh.set.c,v 3.35 1998/10/25 15:10:26 christos Exp $ */ +/* + * sh.set.c: Setting and Clearing of variables + */ +/*- + * Copyright (c) 1980, 1991 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +#include "sh.h" + +RCSID("$Id: sh.set.c,v 3.35 1998/10/25 15:10:26 christos Exp $") + +#include "ed.h" +#include "tw.h" + +extern Char HistLit; +extern bool GotTermCaps; + +static void update_vars __P((Char *)); +static Char *getinx __P((Char *, int *)); +static void asx __P((Char *, int, Char *)); +static struct varent *getvx __P((Char *, int)); +static Char *xset __P((Char *, Char ***)); +static Char *operate __P((int, Char *, Char *)); +static void putn1 __P((int)); +static struct varent *madrof __P((Char *, struct varent *)); +static void unsetv1 __P((struct varent *)); +static void exportpath __P((Char **)); +static void balance __P((struct varent *, int, int)); + +/* + * C Shell + */ + +static void +update_vars(vp) + Char *vp; +{ + if (eq(vp, STRpath)) { + exportpath(adrof(STRpath)->vec); + dohash(NULL, NULL); + } + else if (eq(vp, STRhistchars)) { + register Char *pn = varval(vp); + + HIST = *pn++; + HISTSUB = *pn; + } + else if (eq(vp, STRpromptchars)) { + register Char *pn = varval(vp); + + PRCH = *pn++; + PRCHROOT = *pn; + } + else if (eq(vp, STRhistlit)) { + HistLit = 1; + } + else if (eq(vp, STRuser)) { + tsetenv(STRKUSER, varval(vp)); + tsetenv(STRLOGNAME, varval(vp)); + } + else if (eq(vp, STRgroup)) { + tsetenv(STRKGROUP, varval(vp)); + } + else if (eq(vp, STRwordchars)) { + word_chars = varval(vp); + } + else if (eq(vp, STRloginsh)) { + loginsh = 1; + } + else if (eq(vp, STRsymlinks)) { + register Char *pn = varval(vp); + + if (eq(pn, STRignore)) + symlinks = SYM_IGNORE; + else if (eq(pn, STRexpand)) + symlinks = SYM_EXPAND; + else if (eq(pn, STRchase)) + symlinks = SYM_CHASE; + else + symlinks = 0; + } + else if (eq(vp, STRterm)) { + Char *cp = varval(vp); + tsetenv(STRKTERM, cp); +#ifdef DOESNT_WORK_RIGHT + cp = getenv("TERMCAP"); + if (cp && (*cp != '/')) /* if TERMCAP and not a path */ + Unsetenv(STRTERMCAP); +#endif /* DOESNT_WORK_RIGHT */ + GotTermCaps = 0; + if (noediting && Strcmp(cp, STRnetwork) != 0 && + Strcmp(cp, STRunknown) != 0 && Strcmp(cp, STRdumb) != 0) { + editing = 1; + noediting = 0; + set(STRedit, Strsave(STRNULL), VAR_READWRITE); + } + ed_Init(); /* reset the editor */ + } + else if (eq(vp, STRhome)) { + register Char *cp; + + cp = Strsave(varval(vp)); /* get the old value back */ + + /* + * convert to cononical pathname (possibly resolving symlinks) + */ + cp = dcanon(cp, cp); + + set(vp, Strsave(cp), VAR_READWRITE); /* have to save the new val */ + + /* and now mirror home with HOME */ + tsetenv(STRKHOME, cp); + /* fix directory stack for new tilde home */ + dtilde(); + xfree((ptr_t) cp); + } + else if (eq(vp, STRedit)) { + editing = 1; + noediting = 0; + /* PWP: add more stuff in here later */ + } + else if (eq(vp, STRshlvl)) { + tsetenv(STRKSHLVL, varval(vp)); + } + else if (eq(vp, STRbackslash_quote)) { + bslash_quote = 1; + } + else if (eq(vp, STRdirstack)) { + dsetstack(); + } + else if (eq(vp, STRrecognize_only_executables)) { + tw_cmd_free(); + } +#ifndef HAVENOUTMP + else if (eq(vp, STRwatch)) { + resetwatch(); + } +#endif /* HAVENOUTMP */ + else if (eq(vp, STRimplicitcd)) { + implicit_cd = ((eq(varval(vp), STRverbose)) ? 2 : 1); + } +#ifdef COLOR_LS_F + else if (eq(vp, STRcolor)) { + set_color_context(); + } +#endif /* COLOR_LS_F */ +#if defined(KANJI) && defined(SHORT_STRINGS) && defined(DSPMBYTE) + else if(eq(vp, CHECK_MBYTEVAR) || eq(vp, STRnokanji)) { + update_dspmbyte_vars(); + } +#endif +} + + +/*ARGSUSED*/ +void +doset(v, c) + register Char **v; + struct command *c; +{ + register Char *p; + Char *vp, op; + Char **vecp; + bool hadsub; + int subscr; + int flags = VAR_READWRITE; + bool first_match = 0; + bool last_match = 0; + bool changed = 0; + + USE(c); + v++; + do { + changed = 0; + /* + * Readonly addition From: Tim P. Starrin <noid@cyborg.larc.nasa.gov> + */ + if (*v && eq(*v, STRmr)) { + flags = VAR_READONLY; + v++; + changed = 1; + } + if (*v && eq(*v, STRmf) && !last_match) { + first_match = 1; + v++; + changed = 1; + } + if (*v && eq(*v, STRml) && !first_match) { + last_match = 1; + v++; + changed = 1; + } + } while(changed); + p = *v++; + if (p == 0) { + plist(&shvhed, flags); + return; + } + do { + hadsub = 0; + vp = p; + if (letter(*p)) + for (; alnum(*p); p++) + continue; + if (vp == p || !letter(*vp)) + stderror(ERR_NAME | ERR_VARBEGIN); + if ((p - vp) > MAXVARLEN) { + stderror(ERR_NAME | ERR_VARTOOLONG); + return; + } + if (*p == '[') { + hadsub++; + p = getinx(p, &subscr); + } + if ((op = *p) != 0) { + *p++ = 0; + if (*p == 0 && *v && **v == '(') + p = *v++; + } + else if (*v && eq(*v, STRequal)) { + op = '=', v++; + if (*v) + p = *v++; + } + if (op && op != '=') + stderror(ERR_NAME | ERR_SYNTAX); + if (eq(p, STRLparen)) { + register Char **e = v; + + if (hadsub) + stderror(ERR_NAME | ERR_SYNTAX); + for (;;) { + if (!*e) + stderror(ERR_NAME | ERR_MISSING, ')'); + if (**e == ')') + break; + e++; + } + p = *e; + *e = 0; + vecp = saveblk(v); + if (first_match) + flags |= VAR_FIRST; + else if (last_match) + flags |= VAR_LAST; + + set1(vp, vecp, &shvhed, flags); + *e = p; + v = e + 1; + } + else if (hadsub) + asx(vp, subscr, Strsave(p)); + else + set(vp, Strsave(p), flags); + update_vars(vp); + } while ((p = *v++) != NULL); +} + +static Char * +getinx(cp, ip) + register Char *cp; + register int *ip; +{ + *ip = 0; + *cp++ = 0; + while (*cp && Isdigit(*cp)) + *ip = *ip * 10 + *cp++ - '0'; + if (*cp++ != ']') + stderror(ERR_NAME | ERR_SUBSCRIPT); + return (cp); +} + +static void +asx(vp, subscr, p) + Char *vp; + int subscr; + Char *p; +{ + register struct varent *v = getvx(vp, subscr); + + if (v->v_flags & VAR_READONLY) + stderror(ERR_READONLY|ERR_NAME, v->v_name); + xfree((ptr_t) v->vec[subscr - 1]); + v->vec[subscr - 1] = globone(p, G_APPEND); +} + +static struct varent * +getvx(vp, subscr) + Char *vp; + int subscr; +{ + register struct varent *v = adrof(vp); + + if (v == 0) + udvar(vp); + if (subscr < 1 || subscr > blklen(v->vec)) + stderror(ERR_NAME | ERR_RANGE); + return (v); +} + +/*ARGSUSED*/ +void +dolet(v, dummy) + Char **v; + struct command *dummy; +{ + register Char *p; + Char *vp, c, op; + bool hadsub; + int subscr; + + USE(dummy); + v++; + p = *v++; + if (p == 0) { + prvars(); + return; + } + do { + hadsub = 0; + vp = p; + if (letter(*p)) + for (; alnum(*p); p++) + continue; + if (vp == p || !letter(*vp)) + stderror(ERR_NAME | ERR_VARBEGIN); + if ((p - vp) > MAXVARLEN) + stderror(ERR_NAME | ERR_VARTOOLONG); + if (*p == '[') { + hadsub++; + p = getinx(p, &subscr); + } + if (*p == 0 && *v) + p = *v++; + if ((op = *p) != 0) + *p++ = 0; + else + stderror(ERR_NAME | ERR_ASSIGN); + + /* + * if there is no expression after the '=' then print a "Syntax Error" + * message - strike + */ + if (*p == '\0' && *v == NULL) + stderror(ERR_NAME | ERR_ASSIGN); + + vp = Strsave(vp); + if (op == '=') { + c = '='; + p = xset(p, &v); + } + else { + c = *p++; + if (any("+-", c)) { + if (c != op || *p) + stderror(ERR_NAME | ERR_UNKNOWNOP); + p = Strsave(STR1); + } + else { + if (any("<>", op)) { + if (c != op) + stderror(ERR_NAME | ERR_UNKNOWNOP); + c = *p++; + stderror(ERR_NAME | ERR_SYNTAX); + } + if (c != '=') + stderror(ERR_NAME | ERR_UNKNOWNOP); + p = xset(p, &v); + } + } + if (op == '=') { + if (hadsub) + asx(vp, subscr, p); + else + set(vp, p, VAR_READWRITE); + } + else if (hadsub) { + struct varent *gv = getvx(vp, subscr); + + asx(vp, subscr, operate(op, gv->vec[subscr - 1], p)); + } + else + set(vp, operate(op, varval(vp), p), VAR_READWRITE); + update_vars(vp); + xfree((ptr_t) vp); + if (c != '=') + xfree((ptr_t) p); + } while ((p = *v++) != NULL); +} + +static Char * +xset(cp, vp) + Char *cp, ***vp; +{ + register Char *dp; + + if (*cp) { + dp = Strsave(cp); + --(*vp); + xfree((ptr_t) ** vp); + **vp = dp; + } + return (putn(expr(vp))); +} + +static Char * +operate(op, vp, p) + int op; + Char *vp, *p; +{ + Char opr[2]; + Char *vec[5]; + register Char **v = vec; + Char **vecp = v; + register int i; + + if (op != '=') { + if (*vp) + *v++ = vp; + opr[0] = (Char) op; + opr[1] = 0; + *v++ = opr; + if (op == '<' || op == '>') + *v++ = opr; + } + *v++ = p; + *v++ = 0; + i = expr(&vecp); + if (*vecp) + stderror(ERR_NAME | ERR_EXPRESSION); + return (putn(i)); +} + +static Char *putp, nbuf[50]; + +Char * +putn(n) + register int n; +{ + int num; + + putp = nbuf; + if (n < 0) { + n = -n; + *putp++ = '-'; + } + num = 2; /* confuse lint */ + if (sizeof(int) == num && ((unsigned int) n) == 0x8000) { + *putp++ = '3'; + n = 2768; +#ifdef pdp11 + } +#else /* !pdp11 */ + } + else { + num = 4; /* confuse lint */ + if (sizeof(int) == num && ((unsigned int) n) == 0x80000000) { + *putp++ = '2'; + n = 147483648; + } + } +#endif /* pdp11 */ + putn1(n); + *putp = 0; + return (Strsave(nbuf)); +} + +static void +putn1(n) + register int n; +{ + if (n > 9) + putn1(n / 10); + *putp++ = n % 10 + '0'; +} + +int +getn(cp) + register Char *cp; +{ + register int n; + int sign; + + if (!cp) /* PWP: extra error checking */ + stderror(ERR_NAME | ERR_BADNUM); + + sign = 0; + if (cp[0] == '+' && cp[1]) + cp++; + if (*cp == '-') { + sign++; + cp++; + if (!Isdigit(*cp)) + stderror(ERR_NAME | ERR_BADNUM); + } + n = 0; + while (Isdigit(*cp)) + n = n * 10 + *cp++ - '0'; + if (*cp) + stderror(ERR_NAME | ERR_BADNUM); + return (sign ? -n : n); +} + +Char * +value1(var, head) + Char *var; + struct varent *head; +{ + register struct varent *vp; + + if (!var || !head) /* PWP: extra error checking */ + return (STRNULL); + + vp = adrof1(var, head); + return (vp == 0 || vp->vec[0] == 0 ? STRNULL : vp->vec[0]); +} + +static struct varent * +madrof(pat, vp) + Char *pat; + register struct varent *vp; +{ + register struct varent *vp1; + + for (vp = vp->v_left; vp; vp = vp->v_right) { + if (vp->v_left && (vp1 = madrof(pat, vp)) != NULL) + return vp1; + if (Gmatch(vp->v_name, pat)) + return vp; + } + return vp; +} + +struct varent * +adrof1(name, v) + register Char *name; + register struct varent *v; +{ + int cmp; + + v = v->v_left; + while (v && ((cmp = *name - *v->v_name) != 0 || + (cmp = Strcmp(name, v->v_name)) != 0)) + if (cmp < 0) + v = v->v_left; + else + v = v->v_right; + return v; +} + +/* + * The caller is responsible for putting value in a safe place + */ +void +set(var, val, flags) + Char *var, *val; + int flags; +{ + register Char **vec = (Char **) xmalloc((size_t) (2 * sizeof(Char **))); + + vec[0] = val; + vec[1] = 0; + set1(var, vec, &shvhed, flags); +} + +void +set1(var, vec, head, flags) + Char *var, **vec; + struct varent *head; + int flags; +{ + register Char **oldv = vec; + + if ((flags & VAR_NOGLOB) == 0) { + gflag = 0; + tglob(oldv); + if (gflag) { + vec = globall(oldv); + if (vec == 0) { + blkfree(oldv); + stderror(ERR_NAME | ERR_NOMATCH); + return; + } + blkfree(oldv); + gargv = 0; + } + } + /* + * Uniqueness addition from: Michael Veksler <mveksler@vnet.ibm.com> + */ + if ( flags & (VAR_FIRST | VAR_LAST) ) { + /* + * Code for -f (VAR_FIRST) and -l (VAR_LAST) options. + * Method: + * Delete all duplicate words leaving "holes" in the word array (vec). + * Then remove the "holes", keeping the order of the words unchanged. + */ + if (vec && vec[0] && vec[1]) { /* more than one word ? */ + int i, j; + int num_items; + + for (num_items = 0; vec[num_items]; num_items++) + continue; + if (flags & VAR_FIRST) { + /* delete duplications, keeping first occurance */ + for (i = 1; i < num_items; i++) + for (j = 0; j < i; j++) + /* If have earlier identical item, remove i'th item */ + if (vec[i] && vec[j] && Strcmp(vec[j], vec[i]) == 0) { + free(vec[i]); + vec[i] = NULL; + break; + } + } else if (flags & VAR_LAST) { + /* delete duplications, keeping last occurance */ + for (i = 0; i < num_items - 1; i++) + for (j = i + 1; j < num_items; j++) + /* If have later identical item, remove i'th item */ + if (vec[i] && vec[j] && Strcmp(vec[j], vec[i]) == 0) { + /* remove identical item (the first) */ + free(vec[i]); + vec[i] = NULL; + } + } + /* Compress items - remove empty items */ + for (j = i = 0; i < num_items; i++) + if (vec[i]) + vec[j++] = vec[i]; + + /* NULL-fy remaining items */ + for (; j < num_items; j++) + vec[j] = NULL; + } + /* don't let the attribute propagate */ + flags &= ~(VAR_FIRST|VAR_LAST); + } + setq(var, vec, head, flags); +} + + +void +setq(name, vec, p, flags) + Char *name, **vec; + register struct varent *p; + int flags; +{ + register struct varent *c; + register int f; + + f = 0; /* tree hangs off the header's left link */ + while ((c = p->v_link[f]) != 0) { + if ((f = *name - *c->v_name) == 0 && + (f = Strcmp(name, c->v_name)) == 0) { + if (c->v_flags & VAR_READONLY) + stderror(ERR_READONLY|ERR_NAME, c->v_name); + blkfree(c->vec); + c->v_flags = flags; + trim(c->vec = vec); + return; + } + p = c; + f = f > 0; + } + p->v_link[f] = c = (struct varent *) xmalloc((size_t)sizeof(struct varent)); + c->v_name = Strsave(name); + c->v_flags = flags; + c->v_bal = 0; + c->v_left = c->v_right = 0; + c->v_parent = p; + balance(p, f, 0); + trim(c->vec = vec); +} + +/*ARGSUSED*/ +void +unset(v, c) + Char **v; + struct command *c; +{ + bool did_roe, did_edit; + + USE(c); + did_roe = adrof(STRrecognize_only_executables) != NULL; + did_edit = adrof(STRedit) != NULL; + unset1(v, &shvhed); + if (adrof(STRhistchars) == 0) { + HIST = '!'; + HISTSUB = '^'; + } + if (adrof(STRpromptchars) == 0) { + PRCH = '>'; + PRCHROOT = '#'; + } + if (adrof(STRhistlit) == 0) + HistLit = 0; + if (adrof(STRloginsh) == 0) + loginsh = 0; + if (adrof(STRwordchars) == 0) + word_chars = STR_WORD_CHARS; + if (adrof(STRedit) == 0) + editing = 0; + if (adrof(STRbackslash_quote) == 0) + bslash_quote = 0; + if (adrof(STRsymlinks) == 0) + symlinks = 0; + if (adrof(STRimplicitcd) == 0) + implicit_cd = 0; + if (did_edit && noediting && adrof(STRedit) == 0) + noediting = 0; + if (did_roe && adrof(STRrecognize_only_executables) == 0) + tw_cmd_free(); +#ifdef COLOR_LS_F + if (adrof(STRcolor) == 0) + set_color_context(); +#endif /* COLOR_LS_F */ +#if defined(KANJI) && defined(SHORT_STRINGS) && defined(DSPMBYTE) + update_dspmbyte_vars(); +#endif +} + +void +unset1(v, head) + register Char *v[]; + struct varent *head; +{ + register struct varent *vp; + register int cnt; + + while (*++v) { + cnt = 0; + while ((vp = madrof(*v, head)) != NULL) + if (vp->v_flags & VAR_READONLY) + stderror(ERR_READONLY|ERR_NAME, vp->v_name); + else + unsetv1(vp), cnt++; + if (cnt == 0) + setname(short2str(*v)); + } +} + +void +unsetv(var) + Char *var; +{ + register struct varent *vp; + + if ((vp = adrof1(var, &shvhed)) == 0) + udvar(var); + unsetv1(vp); +} + +static void +unsetv1(p) + register struct varent *p; +{ + register struct varent *c, *pp; + register int f; + + /* + * Free associated memory first to avoid complications. + */ + blkfree(p->vec); + xfree((ptr_t) p->v_name); + /* + * If p is missing one child, then we can move the other into where p is. + * Otherwise, we find the predecessor of p, which is guaranteed to have no + * right child, copy it into p, and move it's left child into it. + */ + if (p->v_right == 0) + c = p->v_left; + else if (p->v_left == 0) + c = p->v_right; + else { + for (c = p->v_left; c->v_right; c = c->v_right) + continue; + p->v_name = c->v_name; + p->v_flags = c->v_flags; + p->vec = c->vec; + p = c; + c = p->v_left; + } + + /* + * Move c into where p is. + */ + pp = p->v_parent; + f = pp->v_right == p; + if ((pp->v_link[f] = c) != 0) + c->v_parent = pp; + /* + * Free the deleted node, and rebalance. + */ + xfree((ptr_t) p); + balance(pp, f, 1); +} + +void +setNS(cp) + Char *cp; +{ + set(cp, Strsave(STRNULL), VAR_READWRITE); +} + +/*ARGSUSED*/ +void +shift(v, c) + register Char **v; + struct command *c; +{ + register struct varent *argv; + register Char *name; + + USE(c); + v++; + name = *v; + if (name == 0) + name = STRargv; + else + (void) strip(name); + argv = adrof(name); + if (argv == 0) + udvar(name); + if (argv->vec[0] == 0) + stderror(ERR_NAME | ERR_NOMORE); + lshift(argv->vec, 1); + update_vars(name); +} + +static Char STRsep[2] = { PATHSEP, '\0' }; + +static void +exportpath(val) + Char **val; +{ + Char *exppath; + size_t exppath_size = BUFSIZE; + exppath = (Char *)xmalloc(sizeof(Char)*exppath_size); + + exppath[0] = 0; + if (val) + while (*val) { + while (Strlen(*val) + Strlen(exppath) + 2 > exppath_size) { + if ((exppath + = (Char *)xrealloc(exppath, sizeof(Char)*(exppath_size *= 2))) + == NULL) { + xprintf(CGETS(18, 1, + "Warning: ridiculously long PATH truncated\n")); + break; + } + } + (void) Strcat(exppath, *val++); + if (*val == 0 || eq(*val, STRRparen)) + break; + (void) Strcat(exppath, STRsep); + } + tsetenv(STRKPATH, exppath); + free(exppath); +} + +#ifndef lint + /* + * Lint thinks these have null effect + */ + /* macros to do single rotations on node p */ +# define rright(p) (\ + t = (p)->v_left,\ + (t)->v_parent = (p)->v_parent,\ + (((p)->v_left = t->v_right) != NULL) ?\ + (t->v_right->v_parent = (p)) : 0,\ + (t->v_right = (p))->v_parent = t,\ + (p) = t) +# define rleft(p) (\ + t = (p)->v_right,\ + ((t)->v_parent = (p)->v_parent,\ + ((p)->v_right = t->v_left) != NULL) ? \ + (t->v_left->v_parent = (p)) : 0,\ + (t->v_left = (p))->v_parent = t,\ + (p) = t) +#else +static struct varent * +rleft(p) + struct varent *p; +{ + return (p); +} +static struct varent * +rright(p) + struct varent *p; +{ + return (p); +} + +#endif /* ! lint */ + + +/* + * Rebalance a tree, starting at p and up. + * F == 0 means we've come from p's left child. + * D == 1 means we've just done a delete, otherwise an insert. + */ +static void +balance(p, f, d) + register struct varent *p; + register int f, d; +{ + register struct varent *pp; + +#ifndef lint + register struct varent *t; /* used by the rotate macros */ +#endif /* !lint */ + register int ff; +#ifdef lint + ff = 0; /* Sun's lint is dumb! */ +#endif + + /* + * Ok, from here on, p is the node we're operating on; pp is it's parent; f + * is the branch of p from which we have come; ff is the branch of pp which + * is p. + */ + for (; (pp = p->v_parent) != 0; p = pp, f = ff) { + ff = pp->v_right == p; + if (f ^ d) { /* right heavy */ + switch (p->v_bal) { + case -1: /* was left heavy */ + p->v_bal = 0; + break; + case 0: /* was balanced */ + p->v_bal = 1; + break; + case 1: /* was already right heavy */ + switch (p->v_right->v_bal) { + case 1: /* sigle rotate */ + pp->v_link[ff] = rleft(p); + p->v_left->v_bal = 0; + p->v_bal = 0; + break; + case 0: /* single rotate */ + pp->v_link[ff] = rleft(p); + p->v_left->v_bal = 1; + p->v_bal = -1; + break; + case -1: /* double rotate */ + (void) rright(p->v_right); + pp->v_link[ff] = rleft(p); + p->v_left->v_bal = + p->v_bal < 1 ? 0 : -1; + p->v_right->v_bal = + p->v_bal > -1 ? 0 : 1; + p->v_bal = 0; + break; + default: + break; + } + break; + default: + break; + } + } + else { /* left heavy */ + switch (p->v_bal) { + case 1: /* was right heavy */ + p->v_bal = 0; + break; + case 0: /* was balanced */ + p->v_bal = -1; + break; + case -1: /* was already left heavy */ + switch (p->v_left->v_bal) { + case -1: /* single rotate */ + pp->v_link[ff] = rright(p); + p->v_right->v_bal = 0; + p->v_bal = 0; + break; + case 0: /* signle rotate */ + pp->v_link[ff] = rright(p); + p->v_right->v_bal = -1; + p->v_bal = 1; + break; + case 1: /* double rotate */ + (void) rleft(p->v_left); + pp->v_link[ff] = rright(p); + p->v_left->v_bal = + p->v_bal < 1 ? 0 : -1; + p->v_right->v_bal = + p->v_bal > -1 ? 0 : 1; + p->v_bal = 0; + break; + default: + break; + } + break; + default: + break; + } + } + /* + * If from insert, then we terminate when p is balanced. If from + * delete, then we terminate when p is unbalanced. + */ + if ((p->v_bal == 0) ^ d) + break; + } +} + +void +plist(p, what) + register struct varent *p; + int what; +{ + register struct varent *c; + register int len; + + if (setintr) +#ifdef BSDSIGS + (void) sigsetmask(sigblock((sigmask_t) 0) & ~sigmask(SIGINT)); +#else /* !BSDSIGS */ + (void) sigrelse(SIGINT); +#endif /* BSDSIGS */ + + for (;;) { + while (p->v_left) + p = p->v_left; +x: + if (p->v_parent == 0) /* is it the header? */ + return; + if ((p->v_flags & what) != 0) { + len = blklen(p->vec); + xprintf("%S\t", p->v_name); + if (len != 1) + xputchar('('); + blkpr(p->vec); + if (len != 1) + xputchar(')'); + xputchar('\n'); + } + if (p->v_right) { + p = p->v_right; + continue; + } + do { + c = p; + p = p->v_parent; + } while (p->v_right == c); + goto x; + } +} + +#if defined(KANJI) && defined(SHORT_STRINGS) && defined(DSPMBYTE) +bool dspmbyte_ls; + +void +update_dspmbyte_vars() +{ + int lp, iskcode; + Char *dstr1; + struct varent *vp; + + /* if variable "nokanji" is set, multi-byte display is disabled */ + if ((vp = adrof(CHECK_MBYTEVAR)) && !adrof(STRnokanji)) { + _enable_mbdisp = 1; + dstr1 = vp->vec[0]; + if(eq (dstr1, STRKSJIS)) + iskcode = 1; + else if (eq(dstr1, STRKEUC)) + iskcode = 2; + else if ((dstr1[0] - '0') >= 0 && (dstr1[0] - '0') <= 3) { + iskcode = 0; + } + else { + xprintf(CGETS(18, 2, + "Warning: unknown multibyte display; using default(euc(JP))\n")); + iskcode = 2; + } + if (dstr1 && vp->vec[1] && eq(vp->vec[1], STRls)) + dspmbyte_ls = 1; + else + dspmbyte_ls = 0; + for (lp = 0; lp < 256 && iskcode > 0; lp++) { + switch (iskcode) { + case 1: + /* Shift-JIS */ + _cmap[lp] = _cmap_mbyte[lp]; + _mbmap[lp] = _mbmap_sjis[lp]; + break; + case 2: + /* 2 ... euc */ + _cmap[lp] = _cmap_mbyte[lp]; + _mbmap[lp] = _mbmap_euc[lp]; + break; + default: + xprintf(CGETS(18, 3, + "Warning: unknown multibyte code %d; multibyte disabled\n"), + iskcode); + _cmap[lp] = _cmap_c[lp]; + _mbmap[lp] = 0; /* Default map all 0 */ + _enable_mbdisp = 0; + break; + } + } + if (iskcode == 0) { + /* check original table */ + if (Strlen(dstr1) != 256) { + xprintf(CGETS(18, 4, + "Warning: Invalid multibyte table length (%d); multibyte disabled\n"), + Strlen(dstr1)); + _enable_mbdisp = 0; + } + for (lp = 0; lp < 256 && _enable_mbdisp == 1; lp++) { + if (!((dstr1[lp] - '0') >= 0 && (dstr1[lp] - '0') <= 3)) { + xprintf(CGETS(18, 4, + "Warning: bad multibyte code at offset +%d; multibyte diabled\n"), + lp); + _enable_mbdisp = 0; + break; + } + } + /* set original table */ + for (lp = 0; lp < 256; lp++) { + if (_enable_mbdisp == 1) { + _cmap[lp] = _cmap_mbyte[lp]; + _mbmap[lp] = (unsigned short) ((dstr1[lp] - '0') & 0x0f); + } + else { + _cmap[lp] = _cmap_c[lp]; + _mbmap[lp] = 0; /* Default map all 0 */ + } + } + } + } + else { + for (lp = 0; lp < 256; lp++) { + _cmap[lp] = _cmap_c[lp]; + _mbmap[lp] = 0; /* Default map all 0 */ + } + _enable_mbdisp = 0; + dspmbyte_ls = 0; + } +#ifdef MBYTEDEBUG /* Sorry, use for beta testing */ + { + Char mbmapstr[300]; + for (lp = 0; lp < 256; lp++) { + mbmapstr[lp] = _mbmap[lp] + '0'; + mbmapstr[lp+1] = 0; + } + set(STRmbytemap, Strsave(mbmapstr), VAR_READWRITE); + } +#endif /* MBYTEMAP */ +} + +/* dspkanji/dspmbyte autosetting */ +/* PATCH IDEA FROM Issei.Suzuki VERY THANKS */ +void +autoset_dspmbyte(pcp) + Char *pcp; +{ + int i; + struct dspm_autoset_Table { + Char *n; + Char *v; + } dspmt[] = { + { STRLANGEUC, STRKEUC }, + { STRLANGEUCB, STRKEUC }, + { STRLANGSJIS, STRKSJIS }, + { STRLANGSJISB, STRKSJIS }, + { NULL, NULL } + }; + + if (*pcp == '\0') + return; + + for (i = 0; dspmt[i].n; i++) { + if (eq(pcp, dspmt[i].n)) { + set(CHECK_MBYTEVAR, Strsave(dspmt[i].v), VAR_READWRITE); + update_dspmbyte_vars(); + break; + } + } +} +#endif |