xref: /dragonfly/contrib/tcsh-6/sh.set.c (revision d6ab524c)
17d8fb588SMatthias Schmidt /*
27d8fb588SMatthias Schmidt  * sh.set.c: Setting and Clearing of variables
37d8fb588SMatthias Schmidt  */
47d8fb588SMatthias Schmidt /*-
57d8fb588SMatthias Schmidt  * Copyright (c) 1980, 1991 The Regents of the University of California.
67d8fb588SMatthias Schmidt  * All rights reserved.
77d8fb588SMatthias Schmidt  *
87d8fb588SMatthias Schmidt  * Redistribution and use in source and binary forms, with or without
97d8fb588SMatthias Schmidt  * modification, are permitted provided that the following conditions
107d8fb588SMatthias Schmidt  * are met:
117d8fb588SMatthias Schmidt  * 1. Redistributions of source code must retain the above copyright
127d8fb588SMatthias Schmidt  *    notice, this list of conditions and the following disclaimer.
137d8fb588SMatthias Schmidt  * 2. Redistributions in binary form must reproduce the above copyright
147d8fb588SMatthias Schmidt  *    notice, this list of conditions and the following disclaimer in the
157d8fb588SMatthias Schmidt  *    documentation and/or other materials provided with the distribution.
167d8fb588SMatthias Schmidt  * 3. Neither the name of the University nor the names of its contributors
177d8fb588SMatthias Schmidt  *    may be used to endorse or promote products derived from this software
187d8fb588SMatthias Schmidt  *    without specific prior written permission.
197d8fb588SMatthias Schmidt  *
207d8fb588SMatthias Schmidt  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
217d8fb588SMatthias Schmidt  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
227d8fb588SMatthias Schmidt  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
237d8fb588SMatthias Schmidt  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
247d8fb588SMatthias Schmidt  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
257d8fb588SMatthias Schmidt  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
267d8fb588SMatthias Schmidt  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
277d8fb588SMatthias Schmidt  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
287d8fb588SMatthias Schmidt  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
297d8fb588SMatthias Schmidt  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
307d8fb588SMatthias Schmidt  * SUCH DAMAGE.
317d8fb588SMatthias Schmidt  */
327d8fb588SMatthias Schmidt #include "sh.h"
337d8fb588SMatthias Schmidt #include "ed.h"
347d8fb588SMatthias Schmidt #include "tw.h"
357d8fb588SMatthias Schmidt 
367d8fb588SMatthias Schmidt #ifdef HAVE_NL_LANGINFO
377d8fb588SMatthias Schmidt #include <langinfo.h>
387d8fb588SMatthias Schmidt #endif
397d8fb588SMatthias Schmidt 
407d8fb588SMatthias Schmidt extern int GotTermCaps;
417d8fb588SMatthias Schmidt int numeof = 0;
427d8fb588SMatthias Schmidt 
437d8fb588SMatthias Schmidt static	void		 update_vars	(Char *);
447d8fb588SMatthias Schmidt static	Char		*getinx		(Char *, int *);
457d8fb588SMatthias Schmidt static	void		 asx		(Char *, int, Char *);
467d8fb588SMatthias Schmidt static	struct varent 	*getvx		(Char *, int);
477d8fb588SMatthias Schmidt static	Char		*xset		(Char *, Char ***);
487d8fb588SMatthias Schmidt static	Char		*operate	(int, Char *, Char *);
4994afa86dSJohn Marino static	void	 	 putn1		(tcsh_number_t);
507d8fb588SMatthias Schmidt static	struct varent	*madrof		(Char *, struct varent *);
517d8fb588SMatthias Schmidt static	void		 unsetv1	(struct varent *);
527d8fb588SMatthias Schmidt static	void		 balance	(struct varent *, int, int);
537d8fb588SMatthias Schmidt static	int		 set_noclobber  (Char **);
54653fab9eSSascha Wildner 
557d8fb588SMatthias Schmidt /*
567d8fb588SMatthias Schmidt  * C Shell
577d8fb588SMatthias Schmidt  */
587d8fb588SMatthias Schmidt 
597d8fb588SMatthias Schmidt static void
update_vars(Char * vp)607d8fb588SMatthias Schmidt update_vars(Char *vp)
617d8fb588SMatthias Schmidt {
627d8fb588SMatthias Schmidt     if (eq(vp, STRpath)) {
637d8fb588SMatthias Schmidt 	struct varent *p = adrof(STRpath);
647d8fb588SMatthias Schmidt 	if (p == NULL)
657d8fb588SMatthias Schmidt 	    stderror(ERR_NAME | ERR_UNDVAR);
667d8fb588SMatthias Schmidt 	else {
677d8fb588SMatthias Schmidt 	    exportpath(p->vec);
687d8fb588SMatthias Schmidt 	    dohash(NULL, NULL);
697d8fb588SMatthias Schmidt 	}
707d8fb588SMatthias Schmidt     }
717d8fb588SMatthias Schmidt     else if (eq(vp, STRnoclobber)) {
72653fab9eSSascha Wildner 	struct varent *p = adrof(STRnoclobber);
73653fab9eSSascha Wildner 	if (p == NULL)
74653fab9eSSascha Wildner 	    stderror(ERR_NAME | ERR_UNDVAR);
75653fab9eSSascha Wildner 	else
76653fab9eSSascha Wildner 	    no_clobber = set_noclobber(p->vec);
77653fab9eSSascha Wildner     }
78653fab9eSSascha Wildner     else if (eq(vp, STRhistchars)) {
797d8fb588SMatthias Schmidt 	Char *pn = varval(vp);
807d8fb588SMatthias Schmidt 
817d8fb588SMatthias Schmidt 	HIST = *pn++;
827d8fb588SMatthias Schmidt 	if (HIST)
8394afa86dSJohn Marino 	    HISTSUB = *pn;
847d8fb588SMatthias Schmidt 	else
8594afa86dSJohn Marino 	    HISTSUB = HIST;
8694afa86dSJohn Marino     }
877d8fb588SMatthias Schmidt     else if (eq(vp, STRpromptchars)) {
887d8fb588SMatthias Schmidt 	Char *pn = varval(vp);
897d8fb588SMatthias Schmidt 
907d8fb588SMatthias Schmidt 	PRCH = *pn++;
917d8fb588SMatthias Schmidt 	if (PRCH)
9294afa86dSJohn Marino 	    PRCHROOT = *pn;
937d8fb588SMatthias Schmidt 	else
9494afa86dSJohn Marino 	    PRCHROOT = PRCH;
9594afa86dSJohn Marino     }
967d8fb588SMatthias Schmidt     else if (eq(vp, STRhistlit)) {
977d8fb588SMatthias Schmidt 	HistLit = 1;
987d8fb588SMatthias Schmidt     }
997d8fb588SMatthias Schmidt     else if (eq(vp, STRuser)) {
1007d8fb588SMatthias Schmidt 	tsetenv(STRKUSER, varval(vp));
1017d8fb588SMatthias Schmidt 	tsetenv(STRLOGNAME, varval(vp));
1027d8fb588SMatthias Schmidt     }
1037d8fb588SMatthias Schmidt     else if (eq(vp, STRgroup)) {
1047d8fb588SMatthias Schmidt 	tsetenv(STRKGROUP, varval(vp));
1057d8fb588SMatthias Schmidt     }
1067d8fb588SMatthias Schmidt     else if (eq(vp, STRwordchars)) {
1077d8fb588SMatthias Schmidt 	word_chars = varval(vp);
1087d8fb588SMatthias Schmidt     }
1097d8fb588SMatthias Schmidt     else if (eq(vp, STRloginsh)) {
1107d8fb588SMatthias Schmidt 	loginsh = 1;
1117d8fb588SMatthias Schmidt     }
1127d8fb588SMatthias Schmidt     else if (eq(vp, STRanyerror)) {
11394afa86dSJohn Marino 	anyerror = 1;
11494afa86dSJohn Marino     }
11594afa86dSJohn Marino     else if (eq(vp, STRsymlinks)) {
1167d8fb588SMatthias Schmidt 	Char *pn = varval(vp);
1177d8fb588SMatthias Schmidt 
1187d8fb588SMatthias Schmidt 	if (eq(pn, STRignore))
1197d8fb588SMatthias Schmidt 	    symlinks = SYM_IGNORE;
1207d8fb588SMatthias Schmidt 	else if (eq(pn, STRexpand))
1217d8fb588SMatthias Schmidt 	    symlinks = SYM_EXPAND;
1227d8fb588SMatthias Schmidt 	else if (eq(pn, STRchase))
1237d8fb588SMatthias Schmidt 	    symlinks = SYM_CHASE;
1247d8fb588SMatthias Schmidt 	else
1257d8fb588SMatthias Schmidt 	    symlinks = 0;
1267d8fb588SMatthias Schmidt     }
1277d8fb588SMatthias Schmidt     else if (eq(vp, STRterm)) {
1287d8fb588SMatthias Schmidt 	Char *cp = varval(vp);
1297d8fb588SMatthias Schmidt 	tsetenv(STRKTERM, cp);
1307d8fb588SMatthias Schmidt #ifdef DOESNT_WORK_RIGHT
1317d8fb588SMatthias Schmidt 	cp = getenv("TERMCAP");
1327d8fb588SMatthias Schmidt 	if (cp && (*cp != '/'))	/* if TERMCAP and not a path */
1337d8fb588SMatthias Schmidt 	    Unsetenv(STRTERMCAP);
1347d8fb588SMatthias Schmidt #endif /* DOESNT_WORK_RIGHT */
1357d8fb588SMatthias Schmidt 	GotTermCaps = 0;
1367d8fb588SMatthias Schmidt 	if (noediting && Strcmp(cp, STRnetwork) != 0 &&
1377d8fb588SMatthias Schmidt 	    Strcmp(cp, STRunknown) != 0 && Strcmp(cp, STRdumb) != 0) {
1387d8fb588SMatthias Schmidt 	    editing = 1;
1397d8fb588SMatthias Schmidt 	    noediting = 0;
1407d8fb588SMatthias Schmidt 	    setNS(STRedit);
1417d8fb588SMatthias Schmidt 	}
1427d8fb588SMatthias Schmidt 	ed_Init();		/* reset the editor */
1437d8fb588SMatthias Schmidt     }
1447d8fb588SMatthias Schmidt     else if (eq(vp, STRhome)) {
1457d8fb588SMatthias Schmidt 	Char *cp, *canon;
1467d8fb588SMatthias Schmidt 
1477d8fb588SMatthias Schmidt 	cp = Strsave(varval(vp));	/* get the old value back */
1487d8fb588SMatthias Schmidt 	/*
1497d8fb588SMatthias Schmidt 	 * convert to cononical pathname (possibly resolving symlinks)
1507d8fb588SMatthias Schmidt 	 */
1517d8fb588SMatthias Schmidt 	canon = dcanon(cp, cp);
1527d8fb588SMatthias Schmidt 	cleanup_push(canon, xfree);
1537d8fb588SMatthias Schmidt 
1547d8fb588SMatthias Schmidt 	setcopy(vp, canon, VAR_READWRITE);	/* have to save the new val */
1557d8fb588SMatthias Schmidt 
1567d8fb588SMatthias Schmidt 	/* and now mirror home with HOME */
1577d8fb588SMatthias Schmidt 	tsetenv(STRKHOME, canon);
1587d8fb588SMatthias Schmidt 	/* fix directory stack for new tilde home */
1597d8fb588SMatthias Schmidt 	dtilde();
1607d8fb588SMatthias Schmidt 	cleanup_until(canon);
1617d8fb588SMatthias Schmidt     }
1627d8fb588SMatthias Schmidt     else if (eq(vp, STRedit)) {
1637d8fb588SMatthias Schmidt 	editing = 1;
1647d8fb588SMatthias Schmidt 	noediting = 0;
1657d8fb588SMatthias Schmidt 	/* PWP: add more stuff in here later */
1667d8fb588SMatthias Schmidt     }
1677d8fb588SMatthias Schmidt     else if (eq(vp, STRvimode)) {
168653fab9eSSascha Wildner 	VImode = 1;
169653fab9eSSascha Wildner 	update_wordchars();
170653fab9eSSascha Wildner     }
171653fab9eSSascha Wildner     else if (eq(vp, STRshlvl)) {
1727d8fb588SMatthias Schmidt 	tsetenv(STRKSHLVL, varval(vp));
1737d8fb588SMatthias Schmidt     }
1747d8fb588SMatthias Schmidt     else if (eq(vp, STRignoreeof)) {
1757d8fb588SMatthias Schmidt 	Char *cp;
1767d8fb588SMatthias Schmidt 	numeof = 0;
1777d8fb588SMatthias Schmidt     	for ((cp = varval(STRignoreeof)); cp && *cp; cp++) {
1787d8fb588SMatthias Schmidt 	    if (!Isdigit(*cp)) {
1797d8fb588SMatthias Schmidt 		numeof = 0;
1807d8fb588SMatthias Schmidt 		break;
1817d8fb588SMatthias Schmidt 	    }
1827d8fb588SMatthias Schmidt 	    numeof = numeof * 10 + *cp - '0';
1837d8fb588SMatthias Schmidt 	}
1847d8fb588SMatthias Schmidt 	if (numeof <= 0) numeof = 26;	/* Sanity check */
1857d8fb588SMatthias Schmidt     }
1867d8fb588SMatthias Schmidt     else if (eq(vp, STRbackslash_quote)) {
1877d8fb588SMatthias Schmidt 	bslash_quote = 1;
1887d8fb588SMatthias Schmidt     }
1897d8fb588SMatthias Schmidt     else if (eq(vp, STRcompat_expr)) {
19057e3f2b5SSimon 'corecode' Schubert 	compat_expr = 1;
19157e3f2b5SSimon 'corecode' Schubert     }
19257e3f2b5SSimon 'corecode' Schubert     else if (eq(vp, STRdirstack)) {
1937d8fb588SMatthias Schmidt 	dsetstack();
1947d8fb588SMatthias Schmidt     }
1957d8fb588SMatthias Schmidt     else if (eq(vp, STRrecognize_only_executables)) {
1967d8fb588SMatthias Schmidt 	tw_cmd_free();
1977d8fb588SMatthias Schmidt     }
1987d8fb588SMatthias Schmidt     else if (eq(vp, STRkillring)) {
1997d8fb588SMatthias Schmidt 	SetKillRing((int)getn(varval(vp)));
20094afa86dSJohn Marino     }
2017d8fb588SMatthias Schmidt     else if (eq(vp, STRhistory)) {
20260962bbcSJohn Marino 	sethistory((int)getn(varval(vp)));
20360962bbcSJohn Marino     }
20460962bbcSJohn Marino #ifndef HAVENOUTMP
2057d8fb588SMatthias Schmidt     else if (eq(vp, STRwatch)) {
2067d8fb588SMatthias Schmidt 	resetwatch();
2077d8fb588SMatthias Schmidt     }
2087d8fb588SMatthias Schmidt #endif /* HAVENOUTMP */
2097d8fb588SMatthias Schmidt     else if (eq(vp, STRimplicitcd)) {
2107d8fb588SMatthias Schmidt 	implicit_cd = ((eq(varval(vp), STRverbose)) ? 2 : 1);
2117d8fb588SMatthias Schmidt     }
2127d8fb588SMatthias Schmidt     else if (eq(vp, STRcdtohome)) {
21360962bbcSJohn Marino 	cdtohome = 1;
21460962bbcSJohn Marino     }
21560962bbcSJohn Marino #ifdef COLOR_LS_F
2167d8fb588SMatthias Schmidt     else if (eq(vp, STRcolor)) {
2177d8fb588SMatthias Schmidt 	set_color_context();
2187d8fb588SMatthias Schmidt     }
2197d8fb588SMatthias Schmidt #endif /* COLOR_LS_F */
2207d8fb588SMatthias Schmidt #if defined(KANJI) && defined(SHORT_STRINGS) && defined(DSPMBYTE)
2217d8fb588SMatthias Schmidt     else if (eq(vp, CHECK_MBYTEVAR) || eq(vp, STRnokanji)) {
2227d8fb588SMatthias Schmidt 	update_dspmbyte_vars();
2237d8fb588SMatthias Schmidt     }
2247d8fb588SMatthias Schmidt #endif
2257d8fb588SMatthias Schmidt #ifdef NLS_CATALOGS
2267d8fb588SMatthias Schmidt     else if (eq(vp, STRcatalog)) {
2277d8fb588SMatthias Schmidt 	nlsclose();
2287d8fb588SMatthias Schmidt 	nlsinit();
2297d8fb588SMatthias Schmidt     }
2307d8fb588SMatthias Schmidt #if defined(FILEC) && defined(TIOCSTI)
2317d8fb588SMatthias Schmidt     else if (eq(vp, STRfilec))
2327d8fb588SMatthias Schmidt 	filec = 1;
2337d8fb588SMatthias Schmidt #endif
2347d8fb588SMatthias Schmidt #endif /* NLS_CATALOGS */
2357d8fb588SMatthias Schmidt }
2367d8fb588SMatthias Schmidt 
2377d8fb588SMatthias Schmidt 
2387d8fb588SMatthias Schmidt /*ARGSUSED*/
2397d8fb588SMatthias Schmidt void
doset(Char ** v,struct command * c)2407d8fb588SMatthias Schmidt doset(Char **v, struct command *c)
2417d8fb588SMatthias Schmidt {
2427d8fb588SMatthias Schmidt     Char *p;
2437d8fb588SMatthias Schmidt     Char   *vp;
24494afa86dSJohn Marino     Char  **vecp;
2457d8fb588SMatthias Schmidt     int    hadsub;
2467d8fb588SMatthias Schmidt     int     subscr;
2477d8fb588SMatthias Schmidt     int	    flags = VAR_READWRITE;
2487d8fb588SMatthias Schmidt     int    first_match = 0;
2497d8fb588SMatthias Schmidt     int    last_match = 0;
2507d8fb588SMatthias Schmidt     int    changed = 0;
2517d8fb588SMatthias Schmidt 
2527d8fb588SMatthias Schmidt     USE(c);
2537d8fb588SMatthias Schmidt     v++;
2547d8fb588SMatthias Schmidt     do {
2557d8fb588SMatthias Schmidt 	changed = 0;
2567d8fb588SMatthias Schmidt 	/*
2577d8fb588SMatthias Schmidt 	 * Readonly addition From: Tim P. Starrin <noid@cyborg.larc.nasa.gov>
2587d8fb588SMatthias Schmidt 	 */
2597d8fb588SMatthias Schmidt 	if (*v && eq(*v, STRmr)) {
2607d8fb588SMatthias Schmidt 	    flags = VAR_READONLY;
2617d8fb588SMatthias Schmidt 	    v++;
2627d8fb588SMatthias Schmidt 	    changed = 1;
2637d8fb588SMatthias Schmidt 	}
2647d8fb588SMatthias Schmidt 	if (*v && eq(*v, STRmf) && !last_match) {
2657d8fb588SMatthias Schmidt 	    first_match = 1;
2667d8fb588SMatthias Schmidt 	    v++;
2677d8fb588SMatthias Schmidt 	    changed = 1;
2687d8fb588SMatthias Schmidt 	}
2697d8fb588SMatthias Schmidt 	if (*v && eq(*v, STRml) && !first_match) {
2707d8fb588SMatthias Schmidt 	    last_match = 1;
2717d8fb588SMatthias Schmidt 	    v++;
2727d8fb588SMatthias Schmidt 	    changed = 1;
2737d8fb588SMatthias Schmidt 	}
2747d8fb588SMatthias Schmidt     } while (changed);
2757d8fb588SMatthias Schmidt     p = *v++;
2767d8fb588SMatthias Schmidt     if (p == 0) {
2777d8fb588SMatthias Schmidt 	plist(&shvhed, flags);
2787d8fb588SMatthias Schmidt 	return;
2797d8fb588SMatthias Schmidt     }
2807d8fb588SMatthias Schmidt     do {
2817d8fb588SMatthias Schmidt 	hadsub = 0;
2827d8fb588SMatthias Schmidt 	vp = p;
2837d8fb588SMatthias Schmidt 	if (!letter(*p))
28494afa86dSJohn Marino 	    stderror(ERR_NAME | ERR_VARBEGIN);
2857d8fb588SMatthias Schmidt 	do {
28694afa86dSJohn Marino 	    p++;
28794afa86dSJohn Marino 	} while (alnum(*p));
28894afa86dSJohn Marino 	if (*p == '[') {
2897d8fb588SMatthias Schmidt 	    hadsub++;
2907d8fb588SMatthias Schmidt 	    p = getinx(p, &subscr);
2917d8fb588SMatthias Schmidt 	}
2927d8fb588SMatthias Schmidt 	if (*p != '\0' && *p != '=')
29394afa86dSJohn Marino 	    stderror(ERR_NAME | ERR_VARALNUM);
29494afa86dSJohn Marino 	if (*p == '=') {
29594afa86dSJohn Marino 	    *p++ = '\0';
29694afa86dSJohn Marino 	    if (*p == '\0' && *v != NULL && **v == '(')
29794afa86dSJohn Marino 		p = *v++;
2987d8fb588SMatthias Schmidt 	}
2997d8fb588SMatthias Schmidt 	else if (*v && eq(*v, STRequal)) {
3007d8fb588SMatthias Schmidt 	    if (*++v != NULL)
30194afa86dSJohn Marino 		p = *v++;
3027d8fb588SMatthias Schmidt 	}
3037d8fb588SMatthias Schmidt 	if (eq(p, STRLparen)) {
3047d8fb588SMatthias Schmidt 	    Char **e = v;
3057d8fb588SMatthias Schmidt 
3067d8fb588SMatthias Schmidt 	    if (hadsub)
3077d8fb588SMatthias Schmidt 		stderror(ERR_NAME | ERR_SYNTAX);
3087d8fb588SMatthias Schmidt 	    for (;;) {
3097d8fb588SMatthias Schmidt 		if (!*e)
3107d8fb588SMatthias Schmidt 		    stderror(ERR_NAME | ERR_MISSING, ')');
3117d8fb588SMatthias Schmidt 		if (**e == ')')
3127d8fb588SMatthias Schmidt 		    break;
3137d8fb588SMatthias Schmidt 		e++;
3147d8fb588SMatthias Schmidt 	    }
3157d8fb588SMatthias Schmidt 	    p = *e;
3167d8fb588SMatthias Schmidt 	    *e = 0;
3177d8fb588SMatthias Schmidt 	    vecp = saveblk(v);
3187d8fb588SMatthias Schmidt 	    if (first_match)
3197d8fb588SMatthias Schmidt 	       flags |= VAR_FIRST;
3207d8fb588SMatthias Schmidt 	    else if (last_match)
3217d8fb588SMatthias Schmidt 	       flags |= VAR_LAST;
3227d8fb588SMatthias Schmidt 
3237d8fb588SMatthias Schmidt 	    set1(vp, vecp, &shvhed, flags);
3247d8fb588SMatthias Schmidt 	    *e = p;
3257d8fb588SMatthias Schmidt 	    v = e + 1;
3267d8fb588SMatthias Schmidt 	}
3277d8fb588SMatthias Schmidt 	else if (hadsub) {
3287d8fb588SMatthias Schmidt 	    Char *copy;
3297d8fb588SMatthias Schmidt 
3307d8fb588SMatthias Schmidt 	    copy = Strsave(p);
3317d8fb588SMatthias Schmidt 	    cleanup_push(copy, xfree);
3327d8fb588SMatthias Schmidt 	    asx(vp, subscr, copy);
3337d8fb588SMatthias Schmidt 	    cleanup_ignore(copy);
3347d8fb588SMatthias Schmidt 	    cleanup_until(copy);
3357d8fb588SMatthias Schmidt 	}
3367d8fb588SMatthias Schmidt 	else
3377d8fb588SMatthias Schmidt 	    setv(vp, Strsave(p), flags);
3387d8fb588SMatthias Schmidt 	update_vars(vp);
3397d8fb588SMatthias Schmidt     } while ((p = *v++) != NULL);
3407d8fb588SMatthias Schmidt }
3417d8fb588SMatthias Schmidt 
3427d8fb588SMatthias Schmidt static Char *
getinx(Char * cp,int * ip)3437d8fb588SMatthias Schmidt getinx(Char *cp, int *ip)
3447d8fb588SMatthias Schmidt {
3457d8fb588SMatthias Schmidt     *ip = 0;
3467d8fb588SMatthias Schmidt     *cp++ = 0;
3477d8fb588SMatthias Schmidt     while (*cp && Isdigit(*cp))
3487d8fb588SMatthias Schmidt 	*ip = *ip * 10 + *cp++ - '0';
3497d8fb588SMatthias Schmidt     if (*cp++ != ']')
3507d8fb588SMatthias Schmidt 	stderror(ERR_NAME | ERR_SUBSCRIPT);
3517d8fb588SMatthias Schmidt     return (cp);
3527d8fb588SMatthias Schmidt }
3537d8fb588SMatthias Schmidt 
3547d8fb588SMatthias Schmidt static void
asx(Char * vp,int subscr,Char * p)3557d8fb588SMatthias Schmidt asx(Char *vp, int subscr, Char *p)
3567d8fb588SMatthias Schmidt {
3577d8fb588SMatthias Schmidt     struct varent *v = getvx(vp, subscr);
3587d8fb588SMatthias Schmidt     Char *prev;
3597d8fb588SMatthias Schmidt 
3607d8fb588SMatthias Schmidt     if (v->v_flags & VAR_READONLY)
3617d8fb588SMatthias Schmidt 	stderror(ERR_READONLY|ERR_NAME, v->v_name);
3627d8fb588SMatthias Schmidt     prev = v->vec[subscr - 1];
3637d8fb588SMatthias Schmidt     cleanup_push(prev, xfree);
3647d8fb588SMatthias Schmidt     v->vec[subscr - 1] = globone(p, G_APPEND);
3657d8fb588SMatthias Schmidt     cleanup_until(prev);
3667d8fb588SMatthias Schmidt }
3677d8fb588SMatthias Schmidt 
3687d8fb588SMatthias Schmidt static struct varent *
getvx(Char * vp,int subscr)3697d8fb588SMatthias Schmidt getvx(Char *vp, int subscr)
3707d8fb588SMatthias Schmidt {
3717d8fb588SMatthias Schmidt     struct varent *v = adrof(vp);
3727d8fb588SMatthias Schmidt 
3737d8fb588SMatthias Schmidt     if (v == 0)
3747d8fb588SMatthias Schmidt 	udvar(vp);
3757d8fb588SMatthias Schmidt     if (subscr < 1 || subscr > blklen(v->vec))
3767d8fb588SMatthias Schmidt 	stderror(ERR_NAME | ERR_RANGE);
3777d8fb588SMatthias Schmidt     return (v);
3787d8fb588SMatthias Schmidt }
3797d8fb588SMatthias Schmidt 
3807d8fb588SMatthias Schmidt /*ARGSUSED*/
3817d8fb588SMatthias Schmidt void
dolet(Char ** v,struct command * dummy)3827d8fb588SMatthias Schmidt dolet(Char **v, struct command *dummy)
3837d8fb588SMatthias Schmidt {
3847d8fb588SMatthias Schmidt     Char *p;
3857d8fb588SMatthias Schmidt     Char   *vp, c, op;
3867d8fb588SMatthias Schmidt     int    hadsub;
3877d8fb588SMatthias Schmidt     int     subscr;
3887d8fb588SMatthias Schmidt 
3897d8fb588SMatthias Schmidt     USE(dummy);
3907d8fb588SMatthias Schmidt     v++;
3917d8fb588SMatthias Schmidt     p = *v++;
3927d8fb588SMatthias Schmidt     if (p == 0) {
3937d8fb588SMatthias Schmidt 	prvars();
3947d8fb588SMatthias Schmidt 	return;
3957d8fb588SMatthias Schmidt     }
3967d8fb588SMatthias Schmidt     do {
3977d8fb588SMatthias Schmidt 	hadsub = 0;
3987d8fb588SMatthias Schmidt 	vp = p;
3997d8fb588SMatthias Schmidt 	if (letter(*p))
4007d8fb588SMatthias Schmidt 	    for (; alnum(*p); p++)
4017d8fb588SMatthias Schmidt 		continue;
4027d8fb588SMatthias Schmidt 	if (vp == p || !letter(*vp))
4037d8fb588SMatthias Schmidt 	    stderror(ERR_NAME | ERR_VARBEGIN);
4047d8fb588SMatthias Schmidt 	if (*p == '[') {
4057d8fb588SMatthias Schmidt 	    hadsub++;
4067d8fb588SMatthias Schmidt 	    p = getinx(p, &subscr);
4077d8fb588SMatthias Schmidt 	}
4087d8fb588SMatthias Schmidt 	if (*p == 0 && *v)
4097d8fb588SMatthias Schmidt 	    p = *v++;
4107d8fb588SMatthias Schmidt 	if ((op = *p) != 0)
4117d8fb588SMatthias Schmidt 	    *p++ = 0;
4127d8fb588SMatthias Schmidt 	else
4137d8fb588SMatthias Schmidt 	    stderror(ERR_NAME | ERR_ASSIGN);
4147d8fb588SMatthias Schmidt 
4157d8fb588SMatthias Schmidt 	/*
4167d8fb588SMatthias Schmidt 	 * if there is no expression after the '=' then print a "Syntax Error"
4177d8fb588SMatthias Schmidt 	 * message - strike
4187d8fb588SMatthias Schmidt 	 */
4197d8fb588SMatthias Schmidt 	if (*p == '\0' && *v == NULL)
4207d8fb588SMatthias Schmidt 	    stderror(ERR_NAME | ERR_ASSIGN);
4217d8fb588SMatthias Schmidt 
4227d8fb588SMatthias Schmidt 	vp = Strsave(vp);
4237d8fb588SMatthias Schmidt 	cleanup_push(vp, xfree);
4247d8fb588SMatthias Schmidt 	if (op == '=') {
4257d8fb588SMatthias Schmidt 	    c = '=';
4267d8fb588SMatthias Schmidt 	    p = xset(p, &v);
4277d8fb588SMatthias Schmidt 	}
4287d8fb588SMatthias Schmidt 	else {
4297d8fb588SMatthias Schmidt 	    c = *p++;
4307d8fb588SMatthias Schmidt 	    if (any("+-", c)) {
4317d8fb588SMatthias Schmidt 		if (c != op || *p)
4327d8fb588SMatthias Schmidt 		    stderror(ERR_NAME | ERR_UNKNOWNOP);
4337d8fb588SMatthias Schmidt 		p = Strsave(STR1);
4347d8fb588SMatthias Schmidt 	    }
4357d8fb588SMatthias Schmidt 	    else {
4367d8fb588SMatthias Schmidt 		if (any("<>", op)) {
4377d8fb588SMatthias Schmidt 		    if (c != op)
4387d8fb588SMatthias Schmidt 			stderror(ERR_NAME | ERR_UNKNOWNOP);
4397d8fb588SMatthias Schmidt 		    stderror(ERR_NAME | ERR_SYNTAX);
4407d8fb588SMatthias Schmidt 		}
4417d8fb588SMatthias Schmidt 		if (c != '=')
4427d8fb588SMatthias Schmidt 		    stderror(ERR_NAME | ERR_UNKNOWNOP);
4437d8fb588SMatthias Schmidt 		p = xset(p, &v);
4447d8fb588SMatthias Schmidt 	    }
4457d8fb588SMatthias Schmidt 	}
4467d8fb588SMatthias Schmidt 	cleanup_push(p, xfree);
4477d8fb588SMatthias Schmidt 	if (op == '=') {
4487d8fb588SMatthias Schmidt 	    if (hadsub)
4497d8fb588SMatthias Schmidt 		asx(vp, subscr, p);
4507d8fb588SMatthias Schmidt 	    else
4517d8fb588SMatthias Schmidt 		setv(vp, p, VAR_READWRITE);
4527d8fb588SMatthias Schmidt 	    cleanup_ignore(p);
4537d8fb588SMatthias Schmidt 	}
4547d8fb588SMatthias Schmidt 	else if (hadsub) {
4557d8fb588SMatthias Schmidt 	    struct varent *gv = getvx(vp, subscr);
4567d8fb588SMatthias Schmidt 	    Char *val;
4577d8fb588SMatthias Schmidt 
4587d8fb588SMatthias Schmidt 	    val = operate(op, gv->vec[subscr - 1], p);
4597d8fb588SMatthias Schmidt 	    cleanup_push(val, xfree);
4607d8fb588SMatthias Schmidt 	    asx(vp, subscr, val);
4617d8fb588SMatthias Schmidt 	    cleanup_ignore(val);
4627d8fb588SMatthias Schmidt 	    cleanup_until(val);
4637d8fb588SMatthias Schmidt 	}
4647d8fb588SMatthias Schmidt 	else {
4657d8fb588SMatthias Schmidt 	    Char *val;
4667d8fb588SMatthias Schmidt 
4677d8fb588SMatthias Schmidt 	    val = operate(op, varval(vp), p);
4687d8fb588SMatthias Schmidt 	    cleanup_push(val, xfree);
4697d8fb588SMatthias Schmidt 	    setv(vp, val, VAR_READWRITE);
4707d8fb588SMatthias Schmidt 	    cleanup_ignore(val);
4717d8fb588SMatthias Schmidt 	    cleanup_until(val);
4727d8fb588SMatthias Schmidt 	}
4737d8fb588SMatthias Schmidt 	update_vars(vp);
4747d8fb588SMatthias Schmidt 	cleanup_until(vp);
4757d8fb588SMatthias Schmidt     } while ((p = *v++) != NULL);
4767d8fb588SMatthias Schmidt }
4777d8fb588SMatthias Schmidt 
4787d8fb588SMatthias Schmidt static Char *
xset(Char * cp,Char *** vp)4797d8fb588SMatthias Schmidt xset(Char *cp, Char ***vp)
4807d8fb588SMatthias Schmidt {
4817d8fb588SMatthias Schmidt     Char *dp;
4827d8fb588SMatthias Schmidt 
4837d8fb588SMatthias Schmidt     if (*cp) {
4847d8fb588SMatthias Schmidt 	dp = Strsave(cp);
4857d8fb588SMatthias Schmidt 	--(*vp);
4867d8fb588SMatthias Schmidt 	xfree(** vp);
4877d8fb588SMatthias Schmidt 	**vp = dp;
4887d8fb588SMatthias Schmidt     }
4897d8fb588SMatthias Schmidt     return (putn(expr(vp)));
4907d8fb588SMatthias Schmidt }
4917d8fb588SMatthias Schmidt 
4927d8fb588SMatthias Schmidt static Char *
operate(int op,Char * vp,Char * p)4937d8fb588SMatthias Schmidt operate(int op, Char *vp, Char *p)
4947d8fb588SMatthias Schmidt {
4957d8fb588SMatthias Schmidt     Char    opr[2];
4967d8fb588SMatthias Schmidt     Char   *vec[5];
4977d8fb588SMatthias Schmidt     Char **v = vec;
4987d8fb588SMatthias Schmidt     Char  **vecp = v;
4997d8fb588SMatthias Schmidt     tcsh_number_t i;
50094afa86dSJohn Marino 
5017d8fb588SMatthias Schmidt     if (op != '=') {
5027d8fb588SMatthias Schmidt 	if (*vp)
5037d8fb588SMatthias Schmidt 	    *v++ = vp;
5047d8fb588SMatthias Schmidt 	opr[0] = op;
5057d8fb588SMatthias Schmidt 	opr[1] = 0;
5067d8fb588SMatthias Schmidt 	*v++ = opr;
5077d8fb588SMatthias Schmidt 	if (op == '<' || op == '>')
5087d8fb588SMatthias Schmidt 	    *v++ = opr;
5097d8fb588SMatthias Schmidt     }
5107d8fb588SMatthias Schmidt     *v++ = p;
5117d8fb588SMatthias Schmidt     *v++ = 0;
5127d8fb588SMatthias Schmidt     i = expr(&vecp);
5137d8fb588SMatthias Schmidt     if (*vecp)
5147d8fb588SMatthias Schmidt 	stderror(ERR_NAME | ERR_EXPRESSION);
5157d8fb588SMatthias Schmidt     return (putn(i));
5167d8fb588SMatthias Schmidt }
5177d8fb588SMatthias Schmidt 
5187d8fb588SMatthias Schmidt static Char *putp;
5197d8fb588SMatthias Schmidt 
5207d8fb588SMatthias Schmidt Char *
putn(tcsh_number_t n)5217d8fb588SMatthias Schmidt putn(tcsh_number_t n)
52294afa86dSJohn Marino {
5237d8fb588SMatthias Schmidt     Char nbuf[1024]; /* Enough even for octal */
52494afa86dSJohn Marino 
5257d8fb588SMatthias Schmidt     putp = nbuf;
5267d8fb588SMatthias Schmidt     if (n < 0) {
5277d8fb588SMatthias Schmidt 	n = -n;
5287d8fb588SMatthias Schmidt 	*putp++ = '-';
5297d8fb588SMatthias Schmidt     }
5307d8fb588SMatthias Schmidt     putn1(n);
5317d8fb588SMatthias Schmidt     *putp = 0;
5327d8fb588SMatthias Schmidt     return (Strsave(nbuf));
5337d8fb588SMatthias Schmidt }
5347d8fb588SMatthias Schmidt 
5357d8fb588SMatthias Schmidt static void
putn1(tcsh_number_t n)5367d8fb588SMatthias Schmidt putn1(tcsh_number_t n)
53794afa86dSJohn Marino {
5387d8fb588SMatthias Schmidt     if (n > 9)
5397d8fb588SMatthias Schmidt 	putn1(n / 10);
5407d8fb588SMatthias Schmidt     *putp++ = (Char)(n % 10 + '0');
54194afa86dSJohn Marino }
5427d8fb588SMatthias Schmidt 
5437d8fb588SMatthias Schmidt tcsh_number_t
getn(const Char * cp)54494afa86dSJohn Marino getn(const Char *cp)
54594afa86dSJohn Marino {
5467d8fb588SMatthias Schmidt     tcsh_number_t n;
54794afa86dSJohn Marino     int     sign;
5487d8fb588SMatthias Schmidt     int base;
54957e3f2b5SSimon 'corecode' Schubert 
5507d8fb588SMatthias Schmidt     if (!cp)			/* PWP: extra error checking */
5517d8fb588SMatthias Schmidt 	stderror(ERR_NAME | ERR_BADNUM);
5527d8fb588SMatthias Schmidt 
5537d8fb588SMatthias Schmidt     sign = 0;
5547d8fb588SMatthias Schmidt     if (cp[0] == '+' && cp[1])
5557d8fb588SMatthias Schmidt 	cp++;
5567d8fb588SMatthias Schmidt     if (*cp == '-') {
5577d8fb588SMatthias Schmidt 	sign++;
5587d8fb588SMatthias Schmidt 	cp++;
5597d8fb588SMatthias Schmidt 	if (!Isdigit(*cp))
5607d8fb588SMatthias Schmidt 	    stderror(ERR_NAME | ERR_BADNUM);
5617d8fb588SMatthias Schmidt     }
5627d8fb588SMatthias Schmidt 
56357e3f2b5SSimon 'corecode' Schubert     if (cp[0] == '0' && cp[1] && is_set(STRparseoctal))
56494afa86dSJohn Marino 	base = 8;
56557e3f2b5SSimon 'corecode' Schubert     else
56657e3f2b5SSimon 'corecode' Schubert 	base = 10;
56757e3f2b5SSimon 'corecode' Schubert 
56857e3f2b5SSimon 'corecode' Schubert     n = 0;
5697d8fb588SMatthias Schmidt     while (Isdigit(*cp))
5707d8fb588SMatthias Schmidt     {
57157e3f2b5SSimon 'corecode' Schubert 	if (base == 8 && *cp >= '8')
57257e3f2b5SSimon 'corecode' Schubert 	    stderror(ERR_NAME | ERR_BADNUM);
57357e3f2b5SSimon 'corecode' Schubert 	n = n * base + *cp++ - '0';
57457e3f2b5SSimon 'corecode' Schubert     }
57557e3f2b5SSimon 'corecode' Schubert     if (*cp)
5767d8fb588SMatthias Schmidt 	stderror(ERR_NAME | ERR_BADNUM);
5777d8fb588SMatthias Schmidt     return (sign ? -n : n);
5787d8fb588SMatthias Schmidt }
5797d8fb588SMatthias Schmidt 
5807d8fb588SMatthias Schmidt Char   *
value1(Char * var,struct varent * head)5817d8fb588SMatthias Schmidt value1(Char *var, struct varent *head)
5827d8fb588SMatthias Schmidt {
5837d8fb588SMatthias Schmidt     struct varent *vp;
5847d8fb588SMatthias Schmidt 
5857d8fb588SMatthias Schmidt     if (!var || !head)		/* PWP: extra error checking */
5867d8fb588SMatthias Schmidt 	return (STRNULL);
5877d8fb588SMatthias Schmidt 
5887d8fb588SMatthias Schmidt     vp = adrof1(var, head);
5897d8fb588SMatthias Schmidt     return ((vp == NULL || vp->vec == NULL || vp->vec[0] == NULL) ?
5907d8fb588SMatthias Schmidt 	STRNULL : vp->vec[0]);
5917d8fb588SMatthias Schmidt }
5927d8fb588SMatthias Schmidt 
5937d8fb588SMatthias Schmidt static struct varent *
madrof(Char * pat,struct varent * vp)5947d8fb588SMatthias Schmidt madrof(Char *pat, struct varent *vp)
5957d8fb588SMatthias Schmidt {
5967d8fb588SMatthias Schmidt     struct varent *vp1;
5977d8fb588SMatthias Schmidt 
5987d8fb588SMatthias Schmidt     for (vp = vp->v_left; vp; vp = vp->v_right) {
5997d8fb588SMatthias Schmidt 	if (vp->v_left && (vp1 = madrof(pat, vp)) != NULL)
6007d8fb588SMatthias Schmidt 	    return vp1;
6017d8fb588SMatthias Schmidt 	if (Gmatch(vp->v_name, pat))
6027d8fb588SMatthias Schmidt 	    return vp;
6037d8fb588SMatthias Schmidt     }
6047d8fb588SMatthias Schmidt     return vp;
6057d8fb588SMatthias Schmidt }
6067d8fb588SMatthias Schmidt 
6077d8fb588SMatthias Schmidt struct varent *
adrof1(const Char * name,struct varent * v)6087d8fb588SMatthias Schmidt adrof1(const Char *name, struct varent *v)
6097d8fb588SMatthias Schmidt {
6107d8fb588SMatthias Schmidt     int cmp;
6117d8fb588SMatthias Schmidt 
6127d8fb588SMatthias Schmidt     v = v->v_left;
6137d8fb588SMatthias Schmidt     while (v && ((cmp = *name - *v->v_name) != 0 ||
6147d8fb588SMatthias Schmidt 		 (cmp = Strcmp(name, v->v_name)) != 0))
6157d8fb588SMatthias Schmidt 	if (cmp < 0)
6167d8fb588SMatthias Schmidt 	    v = v->v_left;
6177d8fb588SMatthias Schmidt 	else
6187d8fb588SMatthias Schmidt 	    v = v->v_right;
6197d8fb588SMatthias Schmidt     return v;
6207d8fb588SMatthias Schmidt }
6217d8fb588SMatthias Schmidt 
6227d8fb588SMatthias Schmidt void
setcopy(const Char * var,const Char * val,int flags)6237d8fb588SMatthias Schmidt setcopy(const Char *var, const Char *val, int flags)
6247d8fb588SMatthias Schmidt {
6257d8fb588SMatthias Schmidt     Char *copy;
6267d8fb588SMatthias Schmidt 
6277d8fb588SMatthias Schmidt     copy = Strsave(val);
6287d8fb588SMatthias Schmidt     cleanup_push(copy, xfree);
6297d8fb588SMatthias Schmidt     setv(var, copy, flags);
6307d8fb588SMatthias Schmidt     cleanup_ignore(copy);
6317d8fb588SMatthias Schmidt     cleanup_until(copy);
6327d8fb588SMatthias Schmidt }
6337d8fb588SMatthias Schmidt 
6347d8fb588SMatthias Schmidt /*
6357d8fb588SMatthias Schmidt  * The caller is responsible for putting value in a safe place
6367d8fb588SMatthias Schmidt  */
6377d8fb588SMatthias Schmidt void
setv(const Char * var,Char * val,int flags)6387d8fb588SMatthias Schmidt setv(const Char *var, Char *val, int flags)
6397d8fb588SMatthias Schmidt {
6407d8fb588SMatthias Schmidt     Char **vec = xmalloc(2 * sizeof(Char **));
6417d8fb588SMatthias Schmidt 
6427d8fb588SMatthias Schmidt     vec[0] = val;
6437d8fb588SMatthias Schmidt     vec[1] = 0;
6447d8fb588SMatthias Schmidt     set1(var, vec, &shvhed, flags);
6457d8fb588SMatthias Schmidt }
6467d8fb588SMatthias Schmidt 
6477d8fb588SMatthias Schmidt void
set1(const Char * var,Char ** vec,struct varent * head,int flags)6487d8fb588SMatthias Schmidt set1(const Char *var, Char **vec, struct varent *head, int flags)
6497d8fb588SMatthias Schmidt {
6507d8fb588SMatthias Schmidt     Char **oldv = vec;
6517d8fb588SMatthias Schmidt 
6527d8fb588SMatthias Schmidt     if ((flags & VAR_NOGLOB) == 0) {
6537d8fb588SMatthias Schmidt 	int gflag;
6547d8fb588SMatthias Schmidt 
6557d8fb588SMatthias Schmidt 	gflag = tglob(oldv);
6567d8fb588SMatthias Schmidt 	if (gflag) {
6577d8fb588SMatthias Schmidt 	    vec = globall(oldv, gflag);
6587d8fb588SMatthias Schmidt 	    if (vec == NULL) {
659*d6ab524cSAntonio Huete Jimenez 		blkfree(oldv);
6607d8fb588SMatthias Schmidt 		stderror(ERR_NAME | ERR_NOMATCH);
6617d8fb588SMatthias Schmidt 	    }
6627d8fb588SMatthias Schmidt 	    blkfree(oldv);
6637d8fb588SMatthias Schmidt 	}
6647d8fb588SMatthias Schmidt     }
6657d8fb588SMatthias Schmidt     /*
6667d8fb588SMatthias Schmidt      * Uniqueness addition from: Michael Veksler <mveksler@vnet.ibm.com>
6677d8fb588SMatthias Schmidt      */
6687d8fb588SMatthias Schmidt     if ( flags & (VAR_FIRST | VAR_LAST) ) {
6697d8fb588SMatthias Schmidt 	/*
6707d8fb588SMatthias Schmidt 	 * Code for -f (VAR_FIRST) and -l (VAR_LAST) options.
6717d8fb588SMatthias Schmidt 	 * Method:
6727d8fb588SMatthias Schmidt 	 *  Delete all duplicate words leaving "holes" in the word array (vec).
6737d8fb588SMatthias Schmidt 	 *  Then remove the "holes", keeping the order of the words unchanged.
6747d8fb588SMatthias Schmidt 	 */
6757d8fb588SMatthias Schmidt 	if (vec[0] && vec[1]) { /* more than one word ? */
676*d6ab524cSAntonio Huete Jimenez 	    int i, j;
6777d8fb588SMatthias Schmidt 	    int num_items;
6787d8fb588SMatthias Schmidt 
6797d8fb588SMatthias Schmidt 	    for (num_items = 0; vec[num_items]; num_items++)
6807d8fb588SMatthias Schmidt 	        continue;
6817d8fb588SMatthias Schmidt 	    if (flags & VAR_FIRST) {
6827d8fb588SMatthias Schmidt 		/* delete duplications, keeping first occurance */
6837d8fb588SMatthias Schmidt 		for (i = 1; i < num_items; i++)
6847d8fb588SMatthias Schmidt 		    for (j = 0; j < i; j++)
6857d8fb588SMatthias Schmidt 			/* If have earlier identical item, remove i'th item */
6867d8fb588SMatthias Schmidt 			if (vec[i] && vec[j] && Strcmp(vec[j], vec[i]) == 0) {
6877d8fb588SMatthias Schmidt 			    xfree(vec[i]);
6887d8fb588SMatthias Schmidt 			    vec[i] = NULL;
6897d8fb588SMatthias Schmidt 			    break;
6907d8fb588SMatthias Schmidt 			}
6917d8fb588SMatthias Schmidt 	    } else if (flags & VAR_LAST) {
6927d8fb588SMatthias Schmidt 	      /* delete duplications, keeping last occurance */
6937d8fb588SMatthias Schmidt 		for (i = 0; i < num_items - 1; i++)
6947d8fb588SMatthias Schmidt 		    for (j = i + 1; j < num_items; j++)
6957d8fb588SMatthias Schmidt 			/* If have later identical item, remove i'th item */
6967d8fb588SMatthias Schmidt 			if (vec[i] && vec[j] && Strcmp(vec[j], vec[i]) == 0) {
6977d8fb588SMatthias Schmidt 			    /* remove identical item (the first) */
6987d8fb588SMatthias Schmidt 			    xfree(vec[i]);
6997d8fb588SMatthias Schmidt 			    vec[i] = NULL;
7007d8fb588SMatthias Schmidt 			}
7017d8fb588SMatthias Schmidt 	    }
7027d8fb588SMatthias Schmidt 	    /* Compress items - remove empty items */
7037d8fb588SMatthias Schmidt 	    for (j = i = 0; i < num_items; i++)
7047d8fb588SMatthias Schmidt 	       if (vec[i])
7057d8fb588SMatthias Schmidt 		  vec[j++] = vec[i];
7067d8fb588SMatthias Schmidt 
7077d8fb588SMatthias Schmidt 	    /* NULL-fy remaining items */
7087d8fb588SMatthias Schmidt 	    for (; j < num_items; j++)
7097d8fb588SMatthias Schmidt 		 vec[j] = NULL;
7107d8fb588SMatthias Schmidt 	}
7117d8fb588SMatthias Schmidt 	/* don't let the attribute propagate */
7127d8fb588SMatthias Schmidt 	flags &= ~(VAR_FIRST|VAR_LAST);
7137d8fb588SMatthias Schmidt     }
7147d8fb588SMatthias Schmidt     setq(var, vec, head, flags);
7157d8fb588SMatthias Schmidt }
7167d8fb588SMatthias Schmidt 
7177d8fb588SMatthias Schmidt 
7187d8fb588SMatthias Schmidt void
setq(const Char * name,Char ** vec,struct varent * p,int flags)7197d8fb588SMatthias Schmidt setq(const Char *name, Char **vec, struct varent *p, int flags)
7207d8fb588SMatthias Schmidt {
7217d8fb588SMatthias Schmidt     struct varent *c;
7227d8fb588SMatthias Schmidt     int f;
7237d8fb588SMatthias Schmidt 
7247d8fb588SMatthias Schmidt     f = 0;			/* tree hangs off the header's left link */
7257d8fb588SMatthias Schmidt     while ((c = p->v_link[f]) != 0) {
7267d8fb588SMatthias Schmidt 	if ((f = *name - *c->v_name) == 0 &&
7277d8fb588SMatthias Schmidt 	    (f = Strcmp(name, c->v_name)) == 0) {
7287d8fb588SMatthias Schmidt 	    if (c->v_flags & VAR_READONLY) {
729*d6ab524cSAntonio Huete Jimenez 		if (flags & VAR_NOERROR)
730*d6ab524cSAntonio Huete Jimenez 		    return;
731*d6ab524cSAntonio Huete Jimenez 		stderror(ERR_READONLY|ERR_NAME, c->v_name);
7327d8fb588SMatthias Schmidt 	    }
733*d6ab524cSAntonio Huete Jimenez 	    blkfree(c->vec);
7347d8fb588SMatthias Schmidt 	    c->v_flags = flags;
7357d8fb588SMatthias Schmidt 	    trim(c->vec = vec);
7367d8fb588SMatthias Schmidt 	    return;
7377d8fb588SMatthias Schmidt 	}
7387d8fb588SMatthias Schmidt 	p = c;
7397d8fb588SMatthias Schmidt 	f = f > 0;
7407d8fb588SMatthias Schmidt     }
7417d8fb588SMatthias Schmidt     p->v_link[f] = c = xmalloc(sizeof(struct varent));
7427d8fb588SMatthias Schmidt     c->v_name = Strsave(name);
7437d8fb588SMatthias Schmidt     c->v_flags = flags;
7447d8fb588SMatthias Schmidt     c->v_bal = 0;
7457d8fb588SMatthias Schmidt     c->v_left = c->v_right = 0;
7467d8fb588SMatthias Schmidt     c->v_parent = p;
7477d8fb588SMatthias Schmidt     balance(p, f, 0);
7487d8fb588SMatthias Schmidt     trim(c->vec = vec);
7497d8fb588SMatthias Schmidt }
7507d8fb588SMatthias Schmidt 
7517d8fb588SMatthias Schmidt /*ARGSUSED*/
7527d8fb588SMatthias Schmidt void
unset(Char ** v,struct command * c)7537d8fb588SMatthias Schmidt unset(Char **v, struct command *c)
7547d8fb588SMatthias Schmidt {
7557d8fb588SMatthias Schmidt     int did_roe, did_edit;
7567d8fb588SMatthias Schmidt 
7577d8fb588SMatthias Schmidt     USE(c);
7587d8fb588SMatthias Schmidt     did_roe = adrof(STRrecognize_only_executables) != NULL;
7597d8fb588SMatthias Schmidt     did_edit = adrof(STRedit) != NULL;
7607d8fb588SMatthias Schmidt     unset1(v, &shvhed);
7617d8fb588SMatthias Schmidt 
7627d8fb588SMatthias Schmidt #if defined(FILEC) && defined(TIOCSTI)
7637d8fb588SMatthias Schmidt     if (adrof(STRfilec) == 0)
7647d8fb588SMatthias Schmidt 	filec = 0;
7657d8fb588SMatthias Schmidt #endif /* FILEC && TIOCSTI */
7667d8fb588SMatthias Schmidt 
7677d8fb588SMatthias Schmidt     if (adrof(STRhistchars) == 0) {
7687d8fb588SMatthias Schmidt 	HIST = '!';
7697d8fb588SMatthias Schmidt 	HISTSUB = '^';
7707d8fb588SMatthias Schmidt     }
7717d8fb588SMatthias Schmidt     if (adrof(STRignoreeof) == 0)
7727d8fb588SMatthias Schmidt 	numeof = 0;
7737d8fb588SMatthias Schmidt     if (adrof(STRpromptchars) == 0) {
7747d8fb588SMatthias Schmidt 	PRCH = tcsh ? '>' : '%';
77594afa86dSJohn Marino 	PRCHROOT = '#';
7767d8fb588SMatthias Schmidt     }
7777d8fb588SMatthias Schmidt     if (adrof(STRnoclobber) == 0)
778653fab9eSSascha Wildner 	no_clobber = 0;
779653fab9eSSascha Wildner     if (adrof(STRhistlit) == 0)
7807d8fb588SMatthias Schmidt 	HistLit = 0;
7817d8fb588SMatthias Schmidt     if (adrof(STRloginsh) == 0)
7827d8fb588SMatthias Schmidt 	loginsh = 0;
7837d8fb588SMatthias Schmidt     if (adrof(STRanyerror) == 0)
78494afa86dSJohn Marino 	anyerror = 0;
78594afa86dSJohn Marino     if (adrof(STRwordchars) == 0)
7867d8fb588SMatthias Schmidt 	word_chars = STR_WORD_CHARS;
7877d8fb588SMatthias Schmidt     if (adrof(STRedit) == 0)
7887d8fb588SMatthias Schmidt 	editing = 0;
7897d8fb588SMatthias Schmidt     if (adrof(STRbackslash_quote) == 0)
7907d8fb588SMatthias Schmidt 	bslash_quote = 0;
7917d8fb588SMatthias Schmidt     if (adrof(STRcompat_expr) == 0)
79257e3f2b5SSimon 'corecode' Schubert 	compat_expr = 0;
79357e3f2b5SSimon 'corecode' Schubert     if (adrof(STRsymlinks) == 0)
7947d8fb588SMatthias Schmidt 	symlinks = 0;
7957d8fb588SMatthias Schmidt     if (adrof(STRimplicitcd) == 0)
7967d8fb588SMatthias Schmidt 	implicit_cd = 0;
7977d8fb588SMatthias Schmidt     if (adrof(STRcdtohome) == 0)
79860962bbcSJohn Marino 	cdtohome = 0;
79960962bbcSJohn Marino     if (adrof(STRkillring) == 0)
8007d8fb588SMatthias Schmidt 	SetKillRing(0);
8017d8fb588SMatthias Schmidt     if (did_edit && noediting && adrof(STRedit) == 0)
8027d8fb588SMatthias Schmidt 	noediting = 0;
8037d8fb588SMatthias Schmidt     if (adrof(STRvimode) == 0)
804653fab9eSSascha Wildner 	VImode = 0;
805653fab9eSSascha Wildner     if (did_roe && adrof(STRrecognize_only_executables) == 0)
8067d8fb588SMatthias Schmidt 	tw_cmd_free();
8077d8fb588SMatthias Schmidt     if (adrof(STRhistory) == 0)
80860962bbcSJohn Marino 	sethistory(0);
80960962bbcSJohn Marino #ifdef COLOR_LS_F
8107d8fb588SMatthias Schmidt     if (adrof(STRcolor) == 0)
8117d8fb588SMatthias Schmidt 	set_color_context();
8127d8fb588SMatthias Schmidt #endif /* COLOR_LS_F */
8137d8fb588SMatthias Schmidt #if defined(KANJI) && defined(SHORT_STRINGS) && defined(DSPMBYTE)
8147d8fb588SMatthias Schmidt     update_dspmbyte_vars();
8157d8fb588SMatthias Schmidt #endif
8167d8fb588SMatthias Schmidt     update_wordchars();
817653fab9eSSascha Wildner #ifdef NLS_CATALOGS
8187d8fb588SMatthias Schmidt     nlsclose();
8197d8fb588SMatthias Schmidt     nlsinit();
8207d8fb588SMatthias Schmidt #endif /* NLS_CATALOGS */
8217d8fb588SMatthias Schmidt }
8227d8fb588SMatthias Schmidt 
8237d8fb588SMatthias Schmidt void
unset1(Char * v[],struct varent * head)8247d8fb588SMatthias Schmidt unset1(Char *v[], struct varent *head)
8257d8fb588SMatthias Schmidt {
8267d8fb588SMatthias Schmidt     struct varent *vp;
8277d8fb588SMatthias Schmidt     int cnt;
8287d8fb588SMatthias Schmidt 
8297d8fb588SMatthias Schmidt     while (*++v) {
8307d8fb588SMatthias Schmidt 	cnt = 0;
8317d8fb588SMatthias Schmidt 	while ((vp = madrof(*v, head)) != NULL)
8327d8fb588SMatthias Schmidt 	    if (vp->v_flags & VAR_READONLY)
8337d8fb588SMatthias Schmidt 		stderror(ERR_READONLY|ERR_NAME, vp->v_name);
8347d8fb588SMatthias Schmidt 	    else
8357d8fb588SMatthias Schmidt 		unsetv1(vp), cnt++;
8367d8fb588SMatthias Schmidt 	if (cnt == 0)
8377d8fb588SMatthias Schmidt 	    setname(short2str(*v));
8387d8fb588SMatthias Schmidt     }
8397d8fb588SMatthias Schmidt }
8407d8fb588SMatthias Schmidt 
8417d8fb588SMatthias Schmidt void
unsetv(Char * var)8427d8fb588SMatthias Schmidt unsetv(Char *var)
8437d8fb588SMatthias Schmidt {
8447d8fb588SMatthias Schmidt     struct varent *vp;
8457d8fb588SMatthias Schmidt 
8467d8fb588SMatthias Schmidt     if ((vp = adrof1(var, &shvhed)) == 0)
8477d8fb588SMatthias Schmidt 	udvar(var);
8487d8fb588SMatthias Schmidt     unsetv1(vp);
8497d8fb588SMatthias Schmidt }
8507d8fb588SMatthias Schmidt 
8517d8fb588SMatthias Schmidt static void
unsetv1(struct varent * p)8527d8fb588SMatthias Schmidt unsetv1(struct varent *p)
8537d8fb588SMatthias Schmidt {
8547d8fb588SMatthias Schmidt     struct varent *c, *pp;
8557d8fb588SMatthias Schmidt     int f;
8567d8fb588SMatthias Schmidt 
8577d8fb588SMatthias Schmidt     /*
8587d8fb588SMatthias Schmidt      * Free associated memory first to avoid complications.
8597d8fb588SMatthias Schmidt      */
8607d8fb588SMatthias Schmidt     blkfree(p->vec);
8617d8fb588SMatthias Schmidt     xfree(p->v_name);
8627d8fb588SMatthias Schmidt     /*
8637d8fb588SMatthias Schmidt      * If p is missing one child, then we can move the other into where p is.
8647d8fb588SMatthias Schmidt      * Otherwise, we find the predecessor of p, which is guaranteed to have no
8657d8fb588SMatthias Schmidt      * right child, copy it into p, and move it's left child into it.
8667d8fb588SMatthias Schmidt      */
8677d8fb588SMatthias Schmidt     if (p->v_right == 0)
8687d8fb588SMatthias Schmidt 	c = p->v_left;
8697d8fb588SMatthias Schmidt     else if (p->v_left == 0)
8707d8fb588SMatthias Schmidt 	c = p->v_right;
8717d8fb588SMatthias Schmidt     else {
8727d8fb588SMatthias Schmidt 	for (c = p->v_left; c->v_right; c = c->v_right)
8737d8fb588SMatthias Schmidt 	    continue;
8747d8fb588SMatthias Schmidt 	p->v_name = c->v_name;
8757d8fb588SMatthias Schmidt 	p->v_flags = c->v_flags;
8767d8fb588SMatthias Schmidt 	p->vec = c->vec;
8777d8fb588SMatthias Schmidt 	p = c;
8787d8fb588SMatthias Schmidt 	c = p->v_left;
8797d8fb588SMatthias Schmidt     }
8807d8fb588SMatthias Schmidt 
8817d8fb588SMatthias Schmidt     /*
8827d8fb588SMatthias Schmidt      * Move c into where p is.
8837d8fb588SMatthias Schmidt      */
8847d8fb588SMatthias Schmidt     pp = p->v_parent;
8857d8fb588SMatthias Schmidt     f = pp->v_right == p;
8867d8fb588SMatthias Schmidt     if ((pp->v_link[f] = c) != 0)
8877d8fb588SMatthias Schmidt 	c->v_parent = pp;
8887d8fb588SMatthias Schmidt     /*
8897d8fb588SMatthias Schmidt      * Free the deleted node, and rebalance.
8907d8fb588SMatthias Schmidt      */
8917d8fb588SMatthias Schmidt     xfree(p);
8927d8fb588SMatthias Schmidt     balance(pp, f, 1);
8937d8fb588SMatthias Schmidt }
8947d8fb588SMatthias Schmidt 
8957d8fb588SMatthias Schmidt /* Set variable name to NULL. */
89694afa86dSJohn Marino void
setNS(const Char * varName)8977d8fb588SMatthias Schmidt setNS(const Char *varName)
89894afa86dSJohn Marino {
8997d8fb588SMatthias Schmidt     setcopy(varName, STRNULL, VAR_READWRITE);
90094afa86dSJohn Marino }
9017d8fb588SMatthias Schmidt 
9027d8fb588SMatthias Schmidt /*ARGSUSED*/
9037d8fb588SMatthias Schmidt void
shift(Char ** v,struct command * c)9047d8fb588SMatthias Schmidt shift(Char **v, struct command *c)
9057d8fb588SMatthias Schmidt {
9067d8fb588SMatthias Schmidt     struct varent *argv;
9077d8fb588SMatthias Schmidt     Char *name;
9087d8fb588SMatthias Schmidt 
9097d8fb588SMatthias Schmidt     USE(c);
9107d8fb588SMatthias Schmidt     v++;
9117d8fb588SMatthias Schmidt     name = *v;
9127d8fb588SMatthias Schmidt     if (name == 0)
9137d8fb588SMatthias Schmidt 	name = STRargv;
9147d8fb588SMatthias Schmidt     else
9157d8fb588SMatthias Schmidt 	(void) strip(name);
9167d8fb588SMatthias Schmidt     argv = adrof(name);
9177d8fb588SMatthias Schmidt     if (argv == NULL || argv->vec == NULL)
9187d8fb588SMatthias Schmidt 	udvar(name);
9197d8fb588SMatthias Schmidt     if (argv->vec[0] == 0)
9207d8fb588SMatthias Schmidt 	stderror(ERR_NAME | ERR_NOMORE);
9217d8fb588SMatthias Schmidt     lshift(argv->vec, 1);
9227d8fb588SMatthias Schmidt     update_vars(name);
9237d8fb588SMatthias Schmidt }
9247d8fb588SMatthias Schmidt 
9257d8fb588SMatthias Schmidt void
exportpath(Char ** val)9267d8fb588SMatthias Schmidt exportpath(Char **val)
9277d8fb588SMatthias Schmidt {
9287d8fb588SMatthias Schmidt     struct Strbuf buf = Strbuf_INIT;
9297d8fb588SMatthias Schmidt     Char    	*exppath;
9307d8fb588SMatthias Schmidt 
9317d8fb588SMatthias Schmidt     if (val)
9327d8fb588SMatthias Schmidt 	while (*val) {
9337d8fb588SMatthias Schmidt 	    Strbuf_append(&buf, *val++);
9347d8fb588SMatthias Schmidt 	    if (*val == 0 || eq(*val, STRRparen))
9357d8fb588SMatthias Schmidt 		break;
9367d8fb588SMatthias Schmidt 	    Strbuf_append1(&buf, PATHSEP);
9377d8fb588SMatthias Schmidt 	}
9387d8fb588SMatthias Schmidt     exppath = Strbuf_finish(&buf);
9397d8fb588SMatthias Schmidt     cleanup_push(exppath, xfree);
9407d8fb588SMatthias Schmidt     tsetenv(STRKPATH, exppath);
9417d8fb588SMatthias Schmidt     cleanup_until(exppath);
9427d8fb588SMatthias Schmidt }
9437d8fb588SMatthias Schmidt 
9447d8fb588SMatthias Schmidt static int
set_noclobber(Char ** val)945653fab9eSSascha Wildner set_noclobber(Char **val)
946653fab9eSSascha Wildner {
947653fab9eSSascha Wildner     Char *option;
948653fab9eSSascha Wildner     int nc = NOCLOBBER_DEFAULT;
949653fab9eSSascha Wildner 
950653fab9eSSascha Wildner     if (val == NULL)
951653fab9eSSascha Wildner 	return nc;
952653fab9eSSascha Wildner     while (*val) {
953653fab9eSSascha Wildner 	if (*val == 0 || eq(*val, STRRparen))
954653fab9eSSascha Wildner 	    return nc;
955653fab9eSSascha Wildner 
956653fab9eSSascha Wildner 	option = *val++;
957653fab9eSSascha Wildner 
958653fab9eSSascha Wildner 	if (eq(option, STRnotempty))
959653fab9eSSascha Wildner 	    nc |= NOCLOBBER_NOTEMPTY;
960653fab9eSSascha Wildner 	else if (eq(option, STRask))
961653fab9eSSascha Wildner 	    nc |= NOCLOBBER_ASK;
962653fab9eSSascha Wildner     }
963653fab9eSSascha Wildner     return nc;
964653fab9eSSascha Wildner }
965653fab9eSSascha Wildner 
966653fab9eSSascha Wildner #ifndef lint
9677d8fb588SMatthias Schmidt  /*
9687d8fb588SMatthias Schmidt   * Lint thinks these have null effect
9697d8fb588SMatthias Schmidt   */
9707d8fb588SMatthias Schmidt  /* macros to do single rotations on node p */
9717d8fb588SMatthias Schmidt # define rright(p) (\
9727d8fb588SMatthias Schmidt 	t = (p)->v_left,\
9737d8fb588SMatthias Schmidt 	(t)->v_parent = (p)->v_parent,\
9747d8fb588SMatthias Schmidt 	(((p)->v_left = t->v_right) != NULL) ?\
9757d8fb588SMatthias Schmidt 	    (t->v_right->v_parent = (p)) : 0,\
9767d8fb588SMatthias Schmidt 	(t->v_right = (p))->v_parent = t,\
9777d8fb588SMatthias Schmidt 	(p) = t)
9787d8fb588SMatthias Schmidt # define rleft(p) (\
9797d8fb588SMatthias Schmidt 	t = (p)->v_right,\
9807d8fb588SMatthias Schmidt 	((t)->v_parent = (p)->v_parent,\
9817d8fb588SMatthias Schmidt 	((p)->v_right = t->v_left) != NULL) ? \
9827d8fb588SMatthias Schmidt 		(t->v_left->v_parent = (p)) : 0,\
9837d8fb588SMatthias Schmidt 	(t->v_left = (p))->v_parent = t,\
9847d8fb588SMatthias Schmidt 	(p) = t)
9857d8fb588SMatthias Schmidt #else
9867d8fb588SMatthias Schmidt static struct varent *
rleft(struct varent * p)9877d8fb588SMatthias Schmidt rleft(struct varent *p)
9887d8fb588SMatthias Schmidt {
9897d8fb588SMatthias Schmidt     return (p);
9907d8fb588SMatthias Schmidt }
9917d8fb588SMatthias Schmidt static struct varent *
rright(struct varent * p)9927d8fb588SMatthias Schmidt rright(struct varent *p)
9937d8fb588SMatthias Schmidt {
9947d8fb588SMatthias Schmidt     return (p);
9957d8fb588SMatthias Schmidt }
9967d8fb588SMatthias Schmidt 
9977d8fb588SMatthias Schmidt #endif /* ! lint */
9987d8fb588SMatthias Schmidt 
9997d8fb588SMatthias Schmidt 
10007d8fb588SMatthias Schmidt /*
10017d8fb588SMatthias Schmidt  * Rebalance a tree, starting at p and up.
10027d8fb588SMatthias Schmidt  * F == 0 means we've come from p's left child.
10037d8fb588SMatthias Schmidt  * D == 1 means we've just done a delete, otherwise an insert.
10047d8fb588SMatthias Schmidt  */
10057d8fb588SMatthias Schmidt static void
balance(struct varent * p,int f,int d)10067d8fb588SMatthias Schmidt balance(struct varent *p, int f, int d)
10077d8fb588SMatthias Schmidt {
10087d8fb588SMatthias Schmidt     struct varent *pp;
10097d8fb588SMatthias Schmidt 
10107d8fb588SMatthias Schmidt #ifndef lint
10117d8fb588SMatthias Schmidt     struct varent *t;	/* used by the rotate macros */
10127d8fb588SMatthias Schmidt #endif /* !lint */
10137d8fb588SMatthias Schmidt     int ff;
10147d8fb588SMatthias Schmidt #ifdef lint
10157d8fb588SMatthias Schmidt     ff = 0;	/* Sun's lint is dumb! */
10167d8fb588SMatthias Schmidt #endif
10177d8fb588SMatthias Schmidt 
10187d8fb588SMatthias Schmidt     /*
10197d8fb588SMatthias Schmidt      * Ok, from here on, p is the node we're operating on; pp is it's parent; f
10207d8fb588SMatthias Schmidt      * is the branch of p from which we have come; ff is the branch of pp which
10217d8fb588SMatthias Schmidt      * is p.
10227d8fb588SMatthias Schmidt      */
10237d8fb588SMatthias Schmidt     for (; (pp = p->v_parent) != 0; p = pp, f = ff) {
10247d8fb588SMatthias Schmidt 	ff = pp->v_right == p;
10257d8fb588SMatthias Schmidt 	if (f ^ d) {		/* right heavy */
10267d8fb588SMatthias Schmidt 	    switch (p->v_bal) {
10277d8fb588SMatthias Schmidt 	    case -1:		/* was left heavy */
10287d8fb588SMatthias Schmidt 		p->v_bal = 0;
10297d8fb588SMatthias Schmidt 		break;
10307d8fb588SMatthias Schmidt 	    case 0:		/* was balanced */
10317d8fb588SMatthias Schmidt 		p->v_bal = 1;
10327d8fb588SMatthias Schmidt 		break;
10337d8fb588SMatthias Schmidt 	    case 1:		/* was already right heavy */
10347d8fb588SMatthias Schmidt 		switch (p->v_right->v_bal) {
10357d8fb588SMatthias Schmidt 		case 1:	/* single rotate */
10367d8fb588SMatthias Schmidt 		    pp->v_link[ff] = rleft(p);
10377d8fb588SMatthias Schmidt 		    p->v_left->v_bal = 0;
10387d8fb588SMatthias Schmidt 		    p->v_bal = 0;
10397d8fb588SMatthias Schmidt 		    break;
10407d8fb588SMatthias Schmidt 		case 0:	/* single rotate */
10417d8fb588SMatthias Schmidt 		    pp->v_link[ff] = rleft(p);
10427d8fb588SMatthias Schmidt 		    p->v_left->v_bal = 1;
10437d8fb588SMatthias Schmidt 		    p->v_bal = -1;
10447d8fb588SMatthias Schmidt 		    break;
10457d8fb588SMatthias Schmidt 		case -1:	/* double rotate */
10467d8fb588SMatthias Schmidt 		    (void) rright(p->v_right);
10477d8fb588SMatthias Schmidt 		    pp->v_link[ff] = rleft(p);
10487d8fb588SMatthias Schmidt 		    p->v_left->v_bal =
10497d8fb588SMatthias Schmidt 			p->v_bal < 1 ? 0 : -1;
10507d8fb588SMatthias Schmidt 		    p->v_right->v_bal =
10517d8fb588SMatthias Schmidt 			p->v_bal > -1 ? 0 : 1;
10527d8fb588SMatthias Schmidt 		    p->v_bal = 0;
10537d8fb588SMatthias Schmidt 		    break;
10547d8fb588SMatthias Schmidt 		default:
10557d8fb588SMatthias Schmidt 		    break;
10567d8fb588SMatthias Schmidt 		}
10577d8fb588SMatthias Schmidt 		break;
10587d8fb588SMatthias Schmidt 	    default:
10597d8fb588SMatthias Schmidt 		break;
10607d8fb588SMatthias Schmidt 	    }
10617d8fb588SMatthias Schmidt 	}
10627d8fb588SMatthias Schmidt 	else {			/* left heavy */
10637d8fb588SMatthias Schmidt 	    switch (p->v_bal) {
10647d8fb588SMatthias Schmidt 	    case 1:		/* was right heavy */
10657d8fb588SMatthias Schmidt 		p->v_bal = 0;
10667d8fb588SMatthias Schmidt 		break;
10677d8fb588SMatthias Schmidt 	    case 0:		/* was balanced */
10687d8fb588SMatthias Schmidt 		p->v_bal = -1;
10697d8fb588SMatthias Schmidt 		break;
10707d8fb588SMatthias Schmidt 	    case -1:		/* was already left heavy */
10717d8fb588SMatthias Schmidt 		switch (p->v_left->v_bal) {
10727d8fb588SMatthias Schmidt 		case -1:	/* single rotate */
10737d8fb588SMatthias Schmidt 		    pp->v_link[ff] = rright(p);
10747d8fb588SMatthias Schmidt 		    p->v_right->v_bal = 0;
10757d8fb588SMatthias Schmidt 		    p->v_bal = 0;
10767d8fb588SMatthias Schmidt 		    break;
10777d8fb588SMatthias Schmidt 		case 0:	/* single rotate */
10787d8fb588SMatthias Schmidt 		    pp->v_link[ff] = rright(p);
10797d8fb588SMatthias Schmidt 		    p->v_right->v_bal = -1;
10807d8fb588SMatthias Schmidt 		    p->v_bal = 1;
10817d8fb588SMatthias Schmidt 		    break;
10827d8fb588SMatthias Schmidt 		case 1:	/* double rotate */
10837d8fb588SMatthias Schmidt 		    (void) rleft(p->v_left);
10847d8fb588SMatthias Schmidt 		    pp->v_link[ff] = rright(p);
10857d8fb588SMatthias Schmidt 		    p->v_left->v_bal =
10867d8fb588SMatthias Schmidt 			p->v_bal < 1 ? 0 : -1;
10877d8fb588SMatthias Schmidt 		    p->v_right->v_bal =
10887d8fb588SMatthias Schmidt 			p->v_bal > -1 ? 0 : 1;
10897d8fb588SMatthias Schmidt 		    p->v_bal = 0;
10907d8fb588SMatthias Schmidt 		    break;
10917d8fb588SMatthias Schmidt 		default:
10927d8fb588SMatthias Schmidt 		    break;
10937d8fb588SMatthias Schmidt 		}
10947d8fb588SMatthias Schmidt 		break;
10957d8fb588SMatthias Schmidt 	    default:
10967d8fb588SMatthias Schmidt 		break;
10977d8fb588SMatthias Schmidt 	    }
10987d8fb588SMatthias Schmidt 	}
10997d8fb588SMatthias Schmidt 	/*
11007d8fb588SMatthias Schmidt 	 * If from insert, then we terminate when p is balanced. If from
11017d8fb588SMatthias Schmidt 	 * delete, then we terminate when p is unbalanced.
11027d8fb588SMatthias Schmidt 	 */
11037d8fb588SMatthias Schmidt 	if ((p->v_bal == 0) ^ d)
11047d8fb588SMatthias Schmidt 	    break;
11057d8fb588SMatthias Schmidt     }
11067d8fb588SMatthias Schmidt }
11077d8fb588SMatthias Schmidt 
11087d8fb588SMatthias Schmidt void
plist(struct varent * p,int what)11097d8fb588SMatthias Schmidt plist(struct varent *p, int what)
11107d8fb588SMatthias Schmidt {
11117d8fb588SMatthias Schmidt     struct varent *c;
11127d8fb588SMatthias Schmidt     int len;
11137d8fb588SMatthias Schmidt 
11147d8fb588SMatthias Schmidt     for (;;) {
11157d8fb588SMatthias Schmidt 	while (p->v_left)
11167d8fb588SMatthias Schmidt 	    p = p->v_left;
11177d8fb588SMatthias Schmidt x:
11187d8fb588SMatthias Schmidt 	if (p->v_parent == 0)	/* is it the header? */
11197d8fb588SMatthias Schmidt 	    break;
11207d8fb588SMatthias Schmidt 	if ((p->v_flags & what) != 0) {
11217d8fb588SMatthias Schmidt 	    if (setintr) {
11227d8fb588SMatthias Schmidt 		int old_pintr_disabled;
11237d8fb588SMatthias Schmidt 
11247d8fb588SMatthias Schmidt 		pintr_push_enable(&old_pintr_disabled);
11257d8fb588SMatthias Schmidt 		cleanup_until(&old_pintr_disabled);
11267d8fb588SMatthias Schmidt 	    }
11277d8fb588SMatthias Schmidt 	    len = blklen(p->vec);
11287d8fb588SMatthias Schmidt 	    xprintf("%" TCSH_S "\t", p->v_name);
1129*d6ab524cSAntonio Huete Jimenez 	    if (len != 1)
11307d8fb588SMatthias Schmidt 		xputchar('(');
11317d8fb588SMatthias Schmidt 	    blkpr(p->vec);
11327d8fb588SMatthias Schmidt 	    if (len != 1)
11337d8fb588SMatthias Schmidt 		xputchar(')');
11347d8fb588SMatthias Schmidt 	    xputchar('\n');
11357d8fb588SMatthias Schmidt 	}
11367d8fb588SMatthias Schmidt 	if (p->v_right) {
11377d8fb588SMatthias Schmidt 	    p = p->v_right;
11387d8fb588SMatthias Schmidt 	    continue;
11397d8fb588SMatthias Schmidt 	}
11407d8fb588SMatthias Schmidt 	do {
11417d8fb588SMatthias Schmidt 	    c = p;
11427d8fb588SMatthias Schmidt 	    p = p->v_parent;
11437d8fb588SMatthias Schmidt 	} while (p->v_right == c);
11447d8fb588SMatthias Schmidt 	goto x;
11457d8fb588SMatthias Schmidt     }
11467d8fb588SMatthias Schmidt }
11477d8fb588SMatthias Schmidt 
11487d8fb588SMatthias Schmidt #if defined(KANJI)
114994afa86dSJohn Marino # if defined(SHORT_STRINGS) && defined(DSPMBYTE)
115094afa86dSJohn Marino extern int dspmbyte_ls;
11517d8fb588SMatthias Schmidt 
11527d8fb588SMatthias Schmidt void
update_dspmbyte_vars(void)11537d8fb588SMatthias Schmidt update_dspmbyte_vars(void)
11547d8fb588SMatthias Schmidt {
11557d8fb588SMatthias Schmidt     int lp, iskcode;
11567d8fb588SMatthias Schmidt     Char *dstr1;
11577d8fb588SMatthias Schmidt     struct varent *vp;
11587d8fb588SMatthias Schmidt 
11597d8fb588SMatthias Schmidt     /* if variable "nokanji" is set, multi-byte display is disabled */
11607d8fb588SMatthias Schmidt     if ((vp = adrof(CHECK_MBYTEVAR)) && !adrof(STRnokanji)) {
11617d8fb588SMatthias Schmidt 	_enable_mbdisp = 1;
11627d8fb588SMatthias Schmidt 	dstr1 = vp->vec[0];
11637d8fb588SMatthias Schmidt 	if (eq (dstr1, STRsjis))
11647d8fb588SMatthias Schmidt 	    iskcode = 1;
11657d8fb588SMatthias Schmidt 	else if (eq(dstr1, STReuc))
11667d8fb588SMatthias Schmidt 	    iskcode = 2;
11677d8fb588SMatthias Schmidt 	else if (eq(dstr1, STRbig5))
11687d8fb588SMatthias Schmidt 	    iskcode = 3;
11697d8fb588SMatthias Schmidt 	else if (eq(dstr1, STRutf8))
11707d8fb588SMatthias Schmidt 	    iskcode = 4;
11717d8fb588SMatthias Schmidt 	else if ((dstr1[0] - '0') >= 0 && (dstr1[0] - '0') <= 3) {
11727d8fb588SMatthias Schmidt 	    iskcode = 0;
11737d8fb588SMatthias Schmidt 	}
11747d8fb588SMatthias Schmidt 	else {
11757d8fb588SMatthias Schmidt 	    xprintf(CGETS(18, 2,
11767d8fb588SMatthias Schmidt 	       "Warning: unknown multibyte display; using default(euc(JP))\n"));
11777d8fb588SMatthias Schmidt 	    iskcode = 2;
11787d8fb588SMatthias Schmidt 	}
11797d8fb588SMatthias Schmidt 	if (dstr1 && vp->vec[1] && eq(vp->vec[1], STRls))
11807d8fb588SMatthias Schmidt 	  dspmbyte_ls = 1;
11817d8fb588SMatthias Schmidt 	else
11827d8fb588SMatthias Schmidt 	  dspmbyte_ls = 0;
11837d8fb588SMatthias Schmidt 	for (lp = 0; lp < 256 && iskcode > 0; lp++) {
11847d8fb588SMatthias Schmidt 	    switch (iskcode) {
11857d8fb588SMatthias Schmidt 	    case 1:
11867d8fb588SMatthias Schmidt 		/* Shift-JIS */
11877d8fb588SMatthias Schmidt 		_cmap[lp] = _cmap_mbyte[lp];
11887d8fb588SMatthias Schmidt 		_mbmap[lp] = _mbmap_sjis[lp];
11897d8fb588SMatthias Schmidt 		break;
11907d8fb588SMatthias Schmidt 	    case 2:
11917d8fb588SMatthias Schmidt 		/* 2 ... euc */
11927d8fb588SMatthias Schmidt 		_cmap[lp] = _cmap_mbyte[lp];
11937d8fb588SMatthias Schmidt 		_mbmap[lp] = _mbmap_euc[lp];
11947d8fb588SMatthias Schmidt 		break;
11957d8fb588SMatthias Schmidt 	    case 3:
11967d8fb588SMatthias Schmidt 		/* 3 ... big5 */
11977d8fb588SMatthias Schmidt 		_cmap[lp] = _cmap_mbyte[lp];
11987d8fb588SMatthias Schmidt 		_mbmap[lp] = _mbmap_big5[lp];
11997d8fb588SMatthias Schmidt 		break;
12007d8fb588SMatthias Schmidt 	    case 4:
12017d8fb588SMatthias Schmidt 		/* 4 ... utf8 */
12027d8fb588SMatthias Schmidt 		_cmap[lp] = _cmap_mbyte[lp];
12037d8fb588SMatthias Schmidt 		_mbmap[lp] = _mbmap_utf8[lp];
12047d8fb588SMatthias Schmidt 		break;
12057d8fb588SMatthias Schmidt 	    default:
12067d8fb588SMatthias Schmidt 		xprintf(CGETS(18, 3,
12077d8fb588SMatthias Schmidt 		    "Warning: unknown multibyte code %d; multibyte disabled\n"),
12087d8fb588SMatthias Schmidt 		    iskcode);
12097d8fb588SMatthias Schmidt 		_cmap[lp] = _cmap_c[lp];
12107d8fb588SMatthias Schmidt 		_mbmap[lp] = 0;	/* Default map all 0 */
12117d8fb588SMatthias Schmidt 		_enable_mbdisp = 0;
12127d8fb588SMatthias Schmidt 		break;
12137d8fb588SMatthias Schmidt 	    }
12147d8fb588SMatthias Schmidt 	}
12157d8fb588SMatthias Schmidt 	if (iskcode == 0) {
12167d8fb588SMatthias Schmidt 	    /* check original table */
12177d8fb588SMatthias Schmidt 	    if (Strlen(dstr1) != 256) {
12187d8fb588SMatthias Schmidt 		xprintf(CGETS(18, 4,
12197d8fb588SMatthias Schmidt        "Warning: Invalid multibyte table length (%d); multibyte disabled\n"),
12207d8fb588SMatthias Schmidt 		    Strlen(dstr1));
12217d8fb588SMatthias Schmidt 		_enable_mbdisp = 0;
12227d8fb588SMatthias Schmidt 	    }
12237d8fb588SMatthias Schmidt 	    for (lp = 0; lp < 256 && _enable_mbdisp == 1; lp++) {
12247d8fb588SMatthias Schmidt 		if (!((dstr1[lp] - '0') >= 0 && (dstr1[lp] - '0') <= 3)) {
12257d8fb588SMatthias Schmidt 		    xprintf(CGETS(18, 4,
12267d8fb588SMatthias Schmidt 	   "Warning: bad multibyte code at offset +%d; multibyte diabled\n"),
12277d8fb588SMatthias Schmidt 			lp);
12287d8fb588SMatthias Schmidt 		    _enable_mbdisp = 0;
12297d8fb588SMatthias Schmidt 		    break;
12307d8fb588SMatthias Schmidt 		}
12317d8fb588SMatthias Schmidt 	    }
12327d8fb588SMatthias Schmidt 	    /* set original table */
12337d8fb588SMatthias Schmidt 	    for (lp = 0; lp < 256; lp++) {
12347d8fb588SMatthias Schmidt 		if (_enable_mbdisp == 1) {
12357d8fb588SMatthias Schmidt 		    _cmap[lp] = _cmap_mbyte[lp];
12367d8fb588SMatthias Schmidt 		    _mbmap[lp] = (unsigned short) ((dstr1[lp] - '0') & 0x0f);
12377d8fb588SMatthias Schmidt 		}
12387d8fb588SMatthias Schmidt 		else {
12397d8fb588SMatthias Schmidt 		    _cmap[lp] = _cmap_c[lp];
12407d8fb588SMatthias Schmidt 		    _mbmap[lp] = 0;	/* Default map all 0 */
12417d8fb588SMatthias Schmidt 		}
12427d8fb588SMatthias Schmidt 	    }
12437d8fb588SMatthias Schmidt 	}
12447d8fb588SMatthias Schmidt     }
12457d8fb588SMatthias Schmidt     else {
12467d8fb588SMatthias Schmidt 	for (lp = 0; lp < 256; lp++) {
12477d8fb588SMatthias Schmidt 	    _cmap[lp] = _cmap_c[lp];
12487d8fb588SMatthias Schmidt 	    _mbmap[lp] = 0;	/* Default map all 0 */
12497d8fb588SMatthias Schmidt 	}
12507d8fb588SMatthias Schmidt 	_enable_mbdisp = 0;
12517d8fb588SMatthias Schmidt 	dspmbyte_ls = 0;
12527d8fb588SMatthias Schmidt     }
12537d8fb588SMatthias Schmidt #ifdef MBYTEDEBUG	/* Sorry, use for beta testing */
12547d8fb588SMatthias Schmidt     {
12557d8fb588SMatthias Schmidt 	Char mbmapstr[300];
12567d8fb588SMatthias Schmidt 	for (lp = 0; lp < 256; lp++)
12577d8fb588SMatthias Schmidt 	    mbmapstr[lp] = _mbmap[lp] + '0';
12587d8fb588SMatthias Schmidt 	mbmapstr[lp] = 0;
12597d8fb588SMatthias Schmidt 	setcopy(STRmbytemap, mbmapstr, VAR_READWRITE);
12607d8fb588SMatthias Schmidt     }
12617d8fb588SMatthias Schmidt #endif /* MBYTEMAP */
12627d8fb588SMatthias Schmidt }
12637d8fb588SMatthias Schmidt 
12647d8fb588SMatthias Schmidt /* dspkanji/dspmbyte autosetting */
12657d8fb588SMatthias Schmidt /* PATCH IDEA FROM Issei.Suzuki VERY THANKS */
12667d8fb588SMatthias Schmidt void
autoset_dspmbyte(const Char * pcp)12677d8fb588SMatthias Schmidt autoset_dspmbyte(const Char *pcp)
12687d8fb588SMatthias Schmidt {
12697d8fb588SMatthias Schmidt     int i;
12707d8fb588SMatthias Schmidt     static const struct dspm_autoset_Table {
12717d8fb588SMatthias Schmidt 	Char *n;
12727d8fb588SMatthias Schmidt 	Char *v;
12737d8fb588SMatthias Schmidt     } dspmt[] = {
12747d8fb588SMatthias Schmidt 	{ STRLANGEUCJP, STReuc },
12757d8fb588SMatthias Schmidt 	{ STRLANGEUCKR, STReuc },
12767d8fb588SMatthias Schmidt 	{ STRLANGEUCZH, STReuc },
12777d8fb588SMatthias Schmidt 	{ STRLANGEUCJPB, STReuc },
12787d8fb588SMatthias Schmidt 	{ STRLANGEUCKRB, STReuc },
12797d8fb588SMatthias Schmidt 	{ STRLANGEUCZHB, STReuc },
12807d8fb588SMatthias Schmidt #ifdef __linux__
128194afa86dSJohn Marino 	{ STRLANGEUCJPC, STReuc },
12827d8fb588SMatthias Schmidt #endif
12837d8fb588SMatthias Schmidt 	{ STRLANGSJIS, STRsjis },
12847d8fb588SMatthias Schmidt 	{ STRLANGSJISB, STRsjis },
12857d8fb588SMatthias Schmidt 	{ STRLANGBIG5, STRbig5 },
12867d8fb588SMatthias Schmidt 	{ STRstarutfstar8, STRutf8 },
12877d8fb588SMatthias Schmidt 	{ NULL, NULL }
12887d8fb588SMatthias Schmidt     };
12897d8fb588SMatthias Schmidt #if defined(HAVE_NL_LANGINFO) && defined(CODESET)
12907d8fb588SMatthias Schmidt     static const struct dspm_autoset_Table dspmc[] = {
12917d8fb588SMatthias Schmidt 	{ STRstarutfstar8, STRutf8 },
12927d8fb588SMatthias Schmidt 	{ STReuc, STReuc },
12937d8fb588SMatthias Schmidt 	{ STRGB2312, STReuc },
12947d8fb588SMatthias Schmidt 	{ STRLANGBIG5, STRbig5 },
12957d8fb588SMatthias Schmidt 	{ NULL, NULL }
12967d8fb588SMatthias Schmidt     };
12977d8fb588SMatthias Schmidt     Char *codeset;
12987d8fb588SMatthias Schmidt 
12997d8fb588SMatthias Schmidt     codeset = str2short(nl_langinfo(CODESET));
13007d8fb588SMatthias Schmidt     if (*codeset != '\0') {
13017d8fb588SMatthias Schmidt 	for (i = 0; dspmc[i].n; i++) {
13027d8fb588SMatthias Schmidt 	    const Char *estr;
13037d8fb588SMatthias Schmidt 	    if (dspmc[i].n[0] && t_pmatch(pcp, dspmc[i].n, &estr, 0) > 0) {
13047d8fb588SMatthias Schmidt 		setcopy(CHECK_MBYTEVAR, dspmc[i].v, VAR_READWRITE);
13057d8fb588SMatthias Schmidt 		update_dspmbyte_vars();
13067d8fb588SMatthias Schmidt 		return;
13077d8fb588SMatthias Schmidt 	    }
13087d8fb588SMatthias Schmidt 	}
13097d8fb588SMatthias Schmidt     }
13107d8fb588SMatthias Schmidt #endif
13117d8fb588SMatthias Schmidt 
13127d8fb588SMatthias Schmidt     if (*pcp == '\0')
13137d8fb588SMatthias Schmidt 	return;
13147d8fb588SMatthias Schmidt 
13157d8fb588SMatthias Schmidt     for (i = 0; dspmt[i].n; i++) {
13167d8fb588SMatthias Schmidt 	const Char *estr;
13177d8fb588SMatthias Schmidt 	if (dspmt[i].n[0] && t_pmatch(pcp, dspmt[i].n, &estr, 0) > 0) {
13187d8fb588SMatthias Schmidt 	    setcopy(CHECK_MBYTEVAR, dspmt[i].v, VAR_READWRITE);
13197d8fb588SMatthias Schmidt 	    update_dspmbyte_vars();
13207d8fb588SMatthias Schmidt 	    break;
13217d8fb588SMatthias Schmidt 	}
13227d8fb588SMatthias Schmidt     }
13237d8fb588SMatthias Schmidt }
13247d8fb588SMatthias Schmidt # elif defined(AUTOSET_KANJI)
132594afa86dSJohn Marino void
autoset_kanji(void)132694afa86dSJohn Marino autoset_kanji(void)
132794afa86dSJohn Marino {
132894afa86dSJohn Marino     char *codeset = nl_langinfo(CODESET);
132994afa86dSJohn Marino 
133094afa86dSJohn Marino     if (*codeset == '\0') {
133194afa86dSJohn Marino 	if (adrof(STRnokanji) == NULL)
133294afa86dSJohn Marino 	    setNS(STRnokanji);
133394afa86dSJohn Marino 	return;
133494afa86dSJohn Marino     }
133594afa86dSJohn Marino 
133694afa86dSJohn Marino     if (strcasestr(codeset, "SHIFT_JIS") == (char*)0) {
133794afa86dSJohn Marino 	if (adrof(STRnokanji) == NULL)
133894afa86dSJohn Marino 	    setNS(STRnokanji);
133994afa86dSJohn Marino 	return;
134094afa86dSJohn Marino     }
134194afa86dSJohn Marino 
134294afa86dSJohn Marino     if (adrof(STRnokanji) != NULL)
134394afa86dSJohn Marino 	unsetv(STRnokanji);
134494afa86dSJohn Marino }
134594afa86dSJohn Marino #endif
134694afa86dSJohn Marino #endif
13477d8fb588SMatthias Schmidt 
1348653fab9eSSascha Wildner void
update_wordchars(void)1349653fab9eSSascha Wildner update_wordchars(void)
1350653fab9eSSascha Wildner {
1351653fab9eSSascha Wildner     if ((word_chars == STR_WORD_CHARS) || (word_chars == STR_WORD_CHARS_VI)) {
1352653fab9eSSascha Wildner 	word_chars = (VImode ? STR_WORD_CHARS_VI : STR_WORD_CHARS);
1353653fab9eSSascha Wildner     }
1354653fab9eSSascha Wildner }
1355653fab9eSSascha Wildner 
1356*d6ab524cSAntonio Huete Jimenez void
setstrstatus(Char * str)1357*d6ab524cSAntonio Huete Jimenez setstrstatus(Char *str)
1358*d6ab524cSAntonio Huete Jimenez {
1359*d6ab524cSAntonio Huete Jimenez 	setv(STRstatus, str, VAR_READWRITE|VAR_NOERROR);
1360*d6ab524cSAntonio Huete Jimenez }
1361*d6ab524cSAntonio Huete Jimenez 
1362*d6ab524cSAntonio Huete Jimenez void
setstatus(int n)1363*d6ab524cSAntonio Huete Jimenez setstatus(int n)
1364*d6ab524cSAntonio Huete Jimenez {
1365*d6ab524cSAntonio Huete Jimenez 	setcopy(STRstatus, n ? STR1 : STR0, VAR_READWRITE|VAR_NOERROR);
1366*d6ab524cSAntonio Huete Jimenez }
1367*d6ab524cSAntonio Huete Jimenez 
1368*d6ab524cSAntonio Huete Jimenez int
getstatus(void)1369*d6ab524cSAntonio Huete Jimenez getstatus(void)
1370*d6ab524cSAntonio Huete Jimenez {
1371*d6ab524cSAntonio Huete Jimenez 	return getn(varval(STRstatus));
1372*d6ab524cSAntonio Huete Jimenez }
1373*d6ab524cSAntonio Huete Jimenez