xref: /freebsd/contrib/tcsh/sh.set.c (revision 19d2e3de755b7c9ca2f5c90b5902fc8f214b2490)
1*19d2e3deSDmitry Chagin /* $Header: /p/tcsh/cvsroot/tcsh/sh.set.c,v 3.89 2015/09/08 15:49:53 christos Exp $ */
2c80476e4SDavid E. O'Brien /*
3c80476e4SDavid E. O'Brien  * sh.set.c: Setting and Clearing of variables
4c80476e4SDavid E. O'Brien  */
5c80476e4SDavid E. O'Brien /*-
6c80476e4SDavid E. O'Brien  * Copyright (c) 1980, 1991 The Regents of the University of California.
7c80476e4SDavid E. O'Brien  * All rights reserved.
8c80476e4SDavid E. O'Brien  *
9c80476e4SDavid E. O'Brien  * Redistribution and use in source and binary forms, with or without
10c80476e4SDavid E. O'Brien  * modification, are permitted provided that the following conditions
11c80476e4SDavid E. O'Brien  * are met:
12c80476e4SDavid E. O'Brien  * 1. Redistributions of source code must retain the above copyright
13c80476e4SDavid E. O'Brien  *    notice, this list of conditions and the following disclaimer.
14c80476e4SDavid E. O'Brien  * 2. Redistributions in binary form must reproduce the above copyright
15c80476e4SDavid E. O'Brien  *    notice, this list of conditions and the following disclaimer in the
16c80476e4SDavid E. O'Brien  *    documentation and/or other materials provided with the distribution.
1729301572SMark Peek  * 3. Neither the name of the University nor the names of its contributors
18c80476e4SDavid E. O'Brien  *    may be used to endorse or promote products derived from this software
19c80476e4SDavid E. O'Brien  *    without specific prior written permission.
20c80476e4SDavid E. O'Brien  *
21c80476e4SDavid E. O'Brien  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22c80476e4SDavid E. O'Brien  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23c80476e4SDavid E. O'Brien  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24c80476e4SDavid E. O'Brien  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25c80476e4SDavid E. O'Brien  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26c80476e4SDavid E. O'Brien  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27c80476e4SDavid E. O'Brien  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28c80476e4SDavid E. O'Brien  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29c80476e4SDavid E. O'Brien  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30c80476e4SDavid E. O'Brien  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31c80476e4SDavid E. O'Brien  * SUCH DAMAGE.
32c80476e4SDavid E. O'Brien  */
33c80476e4SDavid E. O'Brien #include "sh.h"
34c80476e4SDavid E. O'Brien 
35*19d2e3deSDmitry Chagin RCSID("$tcsh: sh.set.c,v 3.89 2015/09/08 15:49:53 christos Exp $")
36c80476e4SDavid E. O'Brien 
37c80476e4SDavid E. O'Brien #include "ed.h"
38c80476e4SDavid E. O'Brien #include "tw.h"
39c80476e4SDavid E. O'Brien 
4023338178SMark Peek #ifdef HAVE_NL_LANGINFO
4123338178SMark Peek #include <langinfo.h>
4223338178SMark Peek #endif
4323338178SMark Peek 
4423338178SMark Peek extern int GotTermCaps;
45b2d5d167SMark Peek int numeof = 0;
46c80476e4SDavid E. O'Brien 
4745e5710bSMark Peek static	void		 update_vars	(Char *);
4845e5710bSMark Peek static	Char		*getinx		(Char *, int *);
4945e5710bSMark Peek static	void		 asx		(Char *, int, Char *);
5045e5710bSMark Peek static	struct varent 	*getvx		(Char *, int);
5145e5710bSMark Peek static	Char		*xset		(Char *, Char ***);
5245e5710bSMark Peek static	Char		*operate	(int, Char *, Char *);
539ccc37e3SMark Peek static	void	 	 putn1		(tcsh_number_t);
5445e5710bSMark Peek static	struct varent	*madrof		(Char *, struct varent *);
5545e5710bSMark Peek static	void		 unsetv1	(struct varent *);
5645e5710bSMark Peek static	void		 exportpath	(Char **);
5745e5710bSMark Peek static	void		 balance	(struct varent *, int, int);
58*19d2e3deSDmitry Chagin static	int		 set_noclobber  (Char **);
59c80476e4SDavid E. O'Brien 
60c80476e4SDavid E. O'Brien /*
61c80476e4SDavid E. O'Brien  * C Shell
62c80476e4SDavid E. O'Brien  */
63c80476e4SDavid E. O'Brien 
64c80476e4SDavid E. O'Brien static void
6545e5710bSMark Peek update_vars(Char *vp)
66c80476e4SDavid E. O'Brien {
67c80476e4SDavid E. O'Brien     if (eq(vp, STRpath)) {
6845e5710bSMark Peek 	struct varent *p = adrof(STRpath);
6945e5710bSMark Peek 	if (p == NULL)
7045e5710bSMark Peek 	    stderror(ERR_NAME | ERR_UNDVAR);
7145e5710bSMark Peek 	else {
7245e5710bSMark Peek 	    exportpath(p->vec);
73c80476e4SDavid E. O'Brien 	    dohash(NULL, NULL);
74c80476e4SDavid E. O'Brien 	}
7545e5710bSMark Peek     }
76*19d2e3deSDmitry Chagin     else if (eq(vp, STRnoclobber)) {
77*19d2e3deSDmitry Chagin 	struct varent *p = adrof(STRnoclobber);
78*19d2e3deSDmitry Chagin 	if (p == NULL)
79*19d2e3deSDmitry Chagin 	    stderror(ERR_NAME | ERR_UNDVAR);
80*19d2e3deSDmitry Chagin 	else
81*19d2e3deSDmitry Chagin 	    no_clobber = set_noclobber(p->vec);
82*19d2e3deSDmitry Chagin     }
83c80476e4SDavid E. O'Brien     else if (eq(vp, STRhistchars)) {
8423338178SMark Peek 	Char *pn = varval(vp);
85c80476e4SDavid E. O'Brien 
86c80476e4SDavid E. O'Brien 	HIST = *pn++;
879ccc37e3SMark Peek 	if (HIST)
88c80476e4SDavid E. O'Brien 	    HISTSUB = *pn;
899ccc37e3SMark Peek 	else
909ccc37e3SMark Peek 	    HISTSUB = HIST;
91c80476e4SDavid E. O'Brien     }
92c80476e4SDavid E. O'Brien     else if (eq(vp, STRpromptchars)) {
9323338178SMark Peek 	Char *pn = varval(vp);
94c80476e4SDavid E. O'Brien 
95c80476e4SDavid E. O'Brien 	PRCH = *pn++;
969ccc37e3SMark Peek 	if (PRCH)
97c80476e4SDavid E. O'Brien 	    PRCHROOT = *pn;
989ccc37e3SMark Peek 	else
999ccc37e3SMark Peek 	    PRCHROOT = PRCH;
100c80476e4SDavid E. O'Brien     }
101c80476e4SDavid E. O'Brien     else if (eq(vp, STRhistlit)) {
102c80476e4SDavid E. O'Brien 	HistLit = 1;
103c80476e4SDavid E. O'Brien     }
104c80476e4SDavid E. O'Brien     else if (eq(vp, STRuser)) {
105c80476e4SDavid E. O'Brien 	tsetenv(STRKUSER, varval(vp));
106c80476e4SDavid E. O'Brien 	tsetenv(STRLOGNAME, varval(vp));
107c80476e4SDavid E. O'Brien     }
108c80476e4SDavid E. O'Brien     else if (eq(vp, STRgroup)) {
109c80476e4SDavid E. O'Brien 	tsetenv(STRKGROUP, varval(vp));
110c80476e4SDavid E. O'Brien     }
111c80476e4SDavid E. O'Brien     else if (eq(vp, STRwordchars)) {
112c80476e4SDavid E. O'Brien 	word_chars = varval(vp);
113c80476e4SDavid E. O'Brien     }
114c80476e4SDavid E. O'Brien     else if (eq(vp, STRloginsh)) {
115c80476e4SDavid E. O'Brien 	loginsh = 1;
116c80476e4SDavid E. O'Brien     }
1179ccc37e3SMark Peek     else if (eq(vp, STRanyerror)) {
1189ccc37e3SMark Peek 	anyerror = 1;
1199ccc37e3SMark Peek     }
120c80476e4SDavid E. O'Brien     else if (eq(vp, STRsymlinks)) {
12123338178SMark Peek 	Char *pn = varval(vp);
122c80476e4SDavid E. O'Brien 
123c80476e4SDavid E. O'Brien 	if (eq(pn, STRignore))
124c80476e4SDavid E. O'Brien 	    symlinks = SYM_IGNORE;
125c80476e4SDavid E. O'Brien 	else if (eq(pn, STRexpand))
126c80476e4SDavid E. O'Brien 	    symlinks = SYM_EXPAND;
127c80476e4SDavid E. O'Brien 	else if (eq(pn, STRchase))
128c80476e4SDavid E. O'Brien 	    symlinks = SYM_CHASE;
129c80476e4SDavid E. O'Brien 	else
130c80476e4SDavid E. O'Brien 	    symlinks = 0;
131c80476e4SDavid E. O'Brien     }
132c80476e4SDavid E. O'Brien     else if (eq(vp, STRterm)) {
133c80476e4SDavid E. O'Brien 	Char *cp = varval(vp);
134c80476e4SDavid E. O'Brien 	tsetenv(STRKTERM, cp);
135c80476e4SDavid E. O'Brien #ifdef DOESNT_WORK_RIGHT
136c80476e4SDavid E. O'Brien 	cp = getenv("TERMCAP");
137c80476e4SDavid E. O'Brien 	if (cp && (*cp != '/'))	/* if TERMCAP and not a path */
138c80476e4SDavid E. O'Brien 	    Unsetenv(STRTERMCAP);
139c80476e4SDavid E. O'Brien #endif /* DOESNT_WORK_RIGHT */
140c80476e4SDavid E. O'Brien 	GotTermCaps = 0;
141c80476e4SDavid E. O'Brien 	if (noediting && Strcmp(cp, STRnetwork) != 0 &&
142c80476e4SDavid E. O'Brien 	    Strcmp(cp, STRunknown) != 0 && Strcmp(cp, STRdumb) != 0) {
143c80476e4SDavid E. O'Brien 	    editing = 1;
144c80476e4SDavid E. O'Brien 	    noediting = 0;
14545e5710bSMark Peek 	    setNS(STRedit);
146c80476e4SDavid E. O'Brien 	}
147c80476e4SDavid E. O'Brien 	ed_Init();		/* reset the editor */
148c80476e4SDavid E. O'Brien     }
149c80476e4SDavid E. O'Brien     else if (eq(vp, STRhome)) {
15045e5710bSMark Peek 	Char *cp, *canon;
151c80476e4SDavid E. O'Brien 
152c80476e4SDavid E. O'Brien 	cp = Strsave(varval(vp));	/* get the old value back */
15345e5710bSMark Peek 	cleanup_push(cp, xfree);
154c80476e4SDavid E. O'Brien 
155c80476e4SDavid E. O'Brien 	/*
156c80476e4SDavid E. O'Brien 	 * convert to cononical pathname (possibly resolving symlinks)
157c80476e4SDavid E. O'Brien 	 */
15845e5710bSMark Peek 	canon = dcanon(cp, cp);
15945e5710bSMark Peek 	cleanup_ignore(cp);
16045e5710bSMark Peek 	cleanup_until(cp);
16145e5710bSMark Peek 	cleanup_push(canon, xfree);
162c80476e4SDavid E. O'Brien 
16345e5710bSMark Peek 	setcopy(vp, canon, VAR_READWRITE);	/* have to save the new val */
164c80476e4SDavid E. O'Brien 
165c80476e4SDavid E. O'Brien 	/* and now mirror home with HOME */
16645e5710bSMark Peek 	tsetenv(STRKHOME, canon);
167c80476e4SDavid E. O'Brien 	/* fix directory stack for new tilde home */
168c80476e4SDavid E. O'Brien 	dtilde();
16945e5710bSMark Peek 	cleanup_until(canon);
170c80476e4SDavid E. O'Brien     }
171c80476e4SDavid E. O'Brien     else if (eq(vp, STRedit)) {
172c80476e4SDavid E. O'Brien 	editing = 1;
173c80476e4SDavid E. O'Brien 	noediting = 0;
174c80476e4SDavid E. O'Brien 	/* PWP: add more stuff in here later */
175c80476e4SDavid E. O'Brien     }
176*19d2e3deSDmitry Chagin     else if (eq(vp, STRvimode)) {
177*19d2e3deSDmitry Chagin 	VImode = 1;
178*19d2e3deSDmitry Chagin 	update_wordchars();
179*19d2e3deSDmitry Chagin     }
180c80476e4SDavid E. O'Brien     else if (eq(vp, STRshlvl)) {
181c80476e4SDavid E. O'Brien 	tsetenv(STRKSHLVL, varval(vp));
182c80476e4SDavid E. O'Brien     }
183b2d5d167SMark Peek     else if (eq(vp, STRignoreeof)) {
184b2d5d167SMark Peek 	Char *cp;
185b2d5d167SMark Peek 	numeof = 0;
186b2d5d167SMark Peek     	for ((cp = varval(STRignoreeof)); cp && *cp; cp++) {
187b2d5d167SMark Peek 	    if (!Isdigit(*cp)) {
188b2d5d167SMark Peek 		numeof = 0;
189b2d5d167SMark Peek 		break;
190b2d5d167SMark Peek 	    }
191b2d5d167SMark Peek 	    numeof = numeof * 10 + *cp - '0';
192b2d5d167SMark Peek 	}
193b2d5d167SMark Peek 	if (numeof <= 0) numeof = 26;	/* Sanity check */
194b2d5d167SMark Peek     }
195c80476e4SDavid E. O'Brien     else if (eq(vp, STRbackslash_quote)) {
196c80476e4SDavid E. O'Brien 	bslash_quote = 1;
197c80476e4SDavid E. O'Brien     }
198a15e6f9aSMark Peek     else if (eq(vp, STRcompat_expr)) {
199a15e6f9aSMark Peek 	compat_expr = 1;
200a15e6f9aSMark Peek     }
201c80476e4SDavid E. O'Brien     else if (eq(vp, STRdirstack)) {
202c80476e4SDavid E. O'Brien 	dsetstack();
203c80476e4SDavid E. O'Brien     }
204c80476e4SDavid E. O'Brien     else if (eq(vp, STRrecognize_only_executables)) {
205c80476e4SDavid E. O'Brien 	tw_cmd_free();
206c80476e4SDavid E. O'Brien     }
2076767bd61SMark Peek     else if (eq(vp, STRkillring)) {
2089ccc37e3SMark Peek 	SetKillRing((int)getn(varval(vp)));
2096767bd61SMark Peek     }
210*19d2e3deSDmitry Chagin     else if (eq(vp, STRhistory)) {
211*19d2e3deSDmitry Chagin 	sethistory((int)getn(varval(vp)));
212*19d2e3deSDmitry Chagin     }
213c80476e4SDavid E. O'Brien #ifndef HAVENOUTMP
214c80476e4SDavid E. O'Brien     else if (eq(vp, STRwatch)) {
215c80476e4SDavid E. O'Brien 	resetwatch();
216c80476e4SDavid E. O'Brien     }
217c80476e4SDavid E. O'Brien #endif /* HAVENOUTMP */
218c80476e4SDavid E. O'Brien     else if (eq(vp, STRimplicitcd)) {
219c80476e4SDavid E. O'Brien 	implicit_cd = ((eq(varval(vp), STRverbose)) ? 2 : 1);
220c80476e4SDavid E. O'Brien     }
221*19d2e3deSDmitry Chagin     else if (eq(vp, STRcdtohome)) {
222*19d2e3deSDmitry Chagin 	cdtohome = 1;
223*19d2e3deSDmitry Chagin     }
224c80476e4SDavid E. O'Brien #ifdef COLOR_LS_F
225c80476e4SDavid E. O'Brien     else if (eq(vp, STRcolor)) {
226c80476e4SDavid E. O'Brien 	set_color_context();
227c80476e4SDavid E. O'Brien     }
228c80476e4SDavid E. O'Brien #endif /* COLOR_LS_F */
229c80476e4SDavid E. O'Brien #if defined(KANJI) && defined(SHORT_STRINGS) && defined(DSPMBYTE)
230c80476e4SDavid E. O'Brien     else if(eq(vp, CHECK_MBYTEVAR) || eq(vp, STRnokanji)) {
231c80476e4SDavid E. O'Brien 	update_dspmbyte_vars();
232c80476e4SDavid E. O'Brien     }
233c80476e4SDavid E. O'Brien #endif
2343b6eaa7bSAndrey A. Chernov #ifdef NLS_CATALOGS
2353b6eaa7bSAndrey A. Chernov     else if (eq(vp, STRcatalog)) {
23623338178SMark Peek 	nlsclose();
2373b6eaa7bSAndrey A. Chernov 	nlsinit();
2383b6eaa7bSAndrey A. Chernov     }
23929301572SMark Peek #if defined(FILEC) && defined(TIOCSTI)
24029301572SMark Peek     else if (eq(vp, STRfilec))
24129301572SMark Peek 	filec = 1;
24229301572SMark Peek #endif
2433b6eaa7bSAndrey A. Chernov #endif /* NLS_CATALOGS */
244c80476e4SDavid E. O'Brien }
245c80476e4SDavid E. O'Brien 
246c80476e4SDavid E. O'Brien 
247c80476e4SDavid E. O'Brien /*ARGSUSED*/
248c80476e4SDavid E. O'Brien void
24945e5710bSMark Peek doset(Char **v, struct command *c)
250c80476e4SDavid E. O'Brien {
25123338178SMark Peek     Char *p;
2529ccc37e3SMark Peek     Char   *vp;
253c80476e4SDavid E. O'Brien     Char  **vecp;
25423338178SMark Peek     int    hadsub;
255c80476e4SDavid E. O'Brien     int     subscr;
256c80476e4SDavid E. O'Brien     int	    flags = VAR_READWRITE;
25723338178SMark Peek     int    first_match = 0;
25823338178SMark Peek     int    last_match = 0;
25923338178SMark Peek     int    changed = 0;
260c80476e4SDavid E. O'Brien 
261c80476e4SDavid E. O'Brien     USE(c);
262c80476e4SDavid E. O'Brien     v++;
263c80476e4SDavid E. O'Brien     do {
264c80476e4SDavid E. O'Brien 	changed = 0;
265c80476e4SDavid E. O'Brien 	/*
266c80476e4SDavid E. O'Brien 	 * Readonly addition From: Tim P. Starrin <noid@cyborg.larc.nasa.gov>
267c80476e4SDavid E. O'Brien 	 */
268c80476e4SDavid E. O'Brien 	if (*v && eq(*v, STRmr)) {
269c80476e4SDavid E. O'Brien 	    flags = VAR_READONLY;
270c80476e4SDavid E. O'Brien 	    v++;
271c80476e4SDavid E. O'Brien 	    changed = 1;
272c80476e4SDavid E. O'Brien 	}
273c80476e4SDavid E. O'Brien 	if (*v && eq(*v, STRmf) && !last_match) {
274c80476e4SDavid E. O'Brien 	    first_match = 1;
275c80476e4SDavid E. O'Brien 	    v++;
276c80476e4SDavid E. O'Brien 	    changed = 1;
277c80476e4SDavid E. O'Brien 	}
278c80476e4SDavid E. O'Brien 	if (*v && eq(*v, STRml) && !first_match) {
279c80476e4SDavid E. O'Brien 	    last_match = 1;
280c80476e4SDavid E. O'Brien 	    v++;
281c80476e4SDavid E. O'Brien 	    changed = 1;
282c80476e4SDavid E. O'Brien 	}
283c80476e4SDavid E. O'Brien     } while(changed);
284c80476e4SDavid E. O'Brien     p = *v++;
285c80476e4SDavid E. O'Brien     if (p == 0) {
286c80476e4SDavid E. O'Brien 	plist(&shvhed, flags);
287c80476e4SDavid E. O'Brien 	return;
288c80476e4SDavid E. O'Brien     }
289c80476e4SDavid E. O'Brien     do {
290c80476e4SDavid E. O'Brien 	hadsub = 0;
291c80476e4SDavid E. O'Brien 	vp = p;
2929ccc37e3SMark Peek 	if (!letter(*p))
293c80476e4SDavid E. O'Brien 	    stderror(ERR_NAME | ERR_VARBEGIN);
2949ccc37e3SMark Peek 	do {
2959ccc37e3SMark Peek 	    p++;
2969ccc37e3SMark Peek 	} while (alnum(*p));
297c80476e4SDavid E. O'Brien 	if (*p == '[') {
298c80476e4SDavid E. O'Brien 	    hadsub++;
299c80476e4SDavid E. O'Brien 	    p = getinx(p, &subscr);
300c80476e4SDavid E. O'Brien 	}
3019ccc37e3SMark Peek 	if (*p != '\0' && *p != '=')
3029ccc37e3SMark Peek 	    stderror(ERR_NAME | ERR_VARALNUM);
3039ccc37e3SMark Peek 	if (*p == '=') {
3049ccc37e3SMark Peek 	    *p++ = '\0';
3059ccc37e3SMark Peek 	    if (*p == '\0' && *v != NULL && **v == '(')
306c80476e4SDavid E. O'Brien 		p = *v++;
307c80476e4SDavid E. O'Brien 	}
308c80476e4SDavid E. O'Brien 	else if (*v && eq(*v, STRequal)) {
3099ccc37e3SMark Peek 	    if (*++v != NULL)
310c80476e4SDavid E. O'Brien 		p = *v++;
311c80476e4SDavid E. O'Brien 	}
312c80476e4SDavid E. O'Brien 	if (eq(p, STRLparen)) {
31323338178SMark Peek 	    Char **e = v;
314c80476e4SDavid E. O'Brien 
315c80476e4SDavid E. O'Brien 	    if (hadsub)
316c80476e4SDavid E. O'Brien 		stderror(ERR_NAME | ERR_SYNTAX);
317c80476e4SDavid E. O'Brien 	    for (;;) {
318c80476e4SDavid E. O'Brien 		if (!*e)
319c80476e4SDavid E. O'Brien 		    stderror(ERR_NAME | ERR_MISSING, ')');
320c80476e4SDavid E. O'Brien 		if (**e == ')')
321c80476e4SDavid E. O'Brien 		    break;
322c80476e4SDavid E. O'Brien 		e++;
323c80476e4SDavid E. O'Brien 	    }
324c80476e4SDavid E. O'Brien 	    p = *e;
325c80476e4SDavid E. O'Brien 	    *e = 0;
326c80476e4SDavid E. O'Brien 	    vecp = saveblk(v);
327c80476e4SDavid E. O'Brien 	    if (first_match)
328c80476e4SDavid E. O'Brien 	       flags |= VAR_FIRST;
329c80476e4SDavid E. O'Brien 	    else if (last_match)
330c80476e4SDavid E. O'Brien 	       flags |= VAR_LAST;
331c80476e4SDavid E. O'Brien 
332c80476e4SDavid E. O'Brien 	    set1(vp, vecp, &shvhed, flags);
333c80476e4SDavid E. O'Brien 	    *e = p;
334c80476e4SDavid E. O'Brien 	    v = e + 1;
335c80476e4SDavid E. O'Brien 	}
33645e5710bSMark Peek 	else if (hadsub) {
33745e5710bSMark Peek 	    Char *copy;
33845e5710bSMark Peek 
33945e5710bSMark Peek 	    copy = Strsave(p);
34045e5710bSMark Peek 	    cleanup_push(copy, xfree);
34145e5710bSMark Peek 	    asx(vp, subscr, copy);
34245e5710bSMark Peek 	    cleanup_ignore(copy);
34345e5710bSMark Peek 	    cleanup_until(copy);
34445e5710bSMark Peek 	}
345c80476e4SDavid E. O'Brien 	else
34645e5710bSMark Peek 	    setv(vp, Strsave(p), flags);
347c80476e4SDavid E. O'Brien 	update_vars(vp);
348c80476e4SDavid E. O'Brien     } while ((p = *v++) != NULL);
349c80476e4SDavid E. O'Brien }
350c80476e4SDavid E. O'Brien 
351c80476e4SDavid E. O'Brien static Char *
35245e5710bSMark Peek getinx(Char *cp, int *ip)
353c80476e4SDavid E. O'Brien {
354c80476e4SDavid E. O'Brien     *ip = 0;
355c80476e4SDavid E. O'Brien     *cp++ = 0;
356c80476e4SDavid E. O'Brien     while (*cp && Isdigit(*cp))
357c80476e4SDavid E. O'Brien 	*ip = *ip * 10 + *cp++ - '0';
358c80476e4SDavid E. O'Brien     if (*cp++ != ']')
359c80476e4SDavid E. O'Brien 	stderror(ERR_NAME | ERR_SUBSCRIPT);
360c80476e4SDavid E. O'Brien     return (cp);
361c80476e4SDavid E. O'Brien }
362c80476e4SDavid E. O'Brien 
363c80476e4SDavid E. O'Brien static void
36445e5710bSMark Peek asx(Char *vp, int subscr, Char *p)
365c80476e4SDavid E. O'Brien {
36623338178SMark Peek     struct varent *v = getvx(vp, subscr);
36745e5710bSMark Peek     Char *prev;
368c80476e4SDavid E. O'Brien 
369c80476e4SDavid E. O'Brien     if (v->v_flags & VAR_READONLY)
370c80476e4SDavid E. O'Brien 	stderror(ERR_READONLY|ERR_NAME, v->v_name);
37145e5710bSMark Peek     prev = v->vec[subscr - 1];
37245e5710bSMark Peek     cleanup_push(prev, xfree);
373c80476e4SDavid E. O'Brien     v->vec[subscr - 1] = globone(p, G_APPEND);
37445e5710bSMark Peek     cleanup_until(prev);
375c80476e4SDavid E. O'Brien }
376c80476e4SDavid E. O'Brien 
377c80476e4SDavid E. O'Brien static struct varent *
37845e5710bSMark Peek getvx(Char *vp, int subscr)
379c80476e4SDavid E. O'Brien {
38023338178SMark Peek     struct varent *v = adrof(vp);
381c80476e4SDavid E. O'Brien 
382c80476e4SDavid E. O'Brien     if (v == 0)
383c80476e4SDavid E. O'Brien 	udvar(vp);
384c80476e4SDavid E. O'Brien     if (subscr < 1 || subscr > blklen(v->vec))
385c80476e4SDavid E. O'Brien 	stderror(ERR_NAME | ERR_RANGE);
386c80476e4SDavid E. O'Brien     return (v);
387c80476e4SDavid E. O'Brien }
388c80476e4SDavid E. O'Brien 
389c80476e4SDavid E. O'Brien /*ARGSUSED*/
390c80476e4SDavid E. O'Brien void
39145e5710bSMark Peek dolet(Char **v, struct command *dummy)
392c80476e4SDavid E. O'Brien {
39323338178SMark Peek     Char *p;
394c80476e4SDavid E. O'Brien     Char   *vp, c, op;
39523338178SMark Peek     int    hadsub;
396c80476e4SDavid E. O'Brien     int     subscr;
397c80476e4SDavid E. O'Brien 
398c80476e4SDavid E. O'Brien     USE(dummy);
399c80476e4SDavid E. O'Brien     v++;
400c80476e4SDavid E. O'Brien     p = *v++;
401c80476e4SDavid E. O'Brien     if (p == 0) {
402c80476e4SDavid E. O'Brien 	prvars();
403c80476e4SDavid E. O'Brien 	return;
404c80476e4SDavid E. O'Brien     }
405c80476e4SDavid E. O'Brien     do {
406c80476e4SDavid E. O'Brien 	hadsub = 0;
407c80476e4SDavid E. O'Brien 	vp = p;
408c80476e4SDavid E. O'Brien 	if (letter(*p))
409c80476e4SDavid E. O'Brien 	    for (; alnum(*p); p++)
410c80476e4SDavid E. O'Brien 		continue;
411c80476e4SDavid E. O'Brien 	if (vp == p || !letter(*vp))
412c80476e4SDavid E. O'Brien 	    stderror(ERR_NAME | ERR_VARBEGIN);
413c80476e4SDavid E. O'Brien 	if (*p == '[') {
414c80476e4SDavid E. O'Brien 	    hadsub++;
415c80476e4SDavid E. O'Brien 	    p = getinx(p, &subscr);
416c80476e4SDavid E. O'Brien 	}
417c80476e4SDavid E. O'Brien 	if (*p == 0 && *v)
418c80476e4SDavid E. O'Brien 	    p = *v++;
419c80476e4SDavid E. O'Brien 	if ((op = *p) != 0)
420c80476e4SDavid E. O'Brien 	    *p++ = 0;
421c80476e4SDavid E. O'Brien 	else
422c80476e4SDavid E. O'Brien 	    stderror(ERR_NAME | ERR_ASSIGN);
423c80476e4SDavid E. O'Brien 
424c80476e4SDavid E. O'Brien 	/*
425c80476e4SDavid E. O'Brien 	 * if there is no expression after the '=' then print a "Syntax Error"
426c80476e4SDavid E. O'Brien 	 * message - strike
427c80476e4SDavid E. O'Brien 	 */
428c80476e4SDavid E. O'Brien 	if (*p == '\0' && *v == NULL)
429c80476e4SDavid E. O'Brien 	    stderror(ERR_NAME | ERR_ASSIGN);
430c80476e4SDavid E. O'Brien 
431c80476e4SDavid E. O'Brien 	vp = Strsave(vp);
43245e5710bSMark Peek 	cleanup_push(vp, xfree);
433c80476e4SDavid E. O'Brien 	if (op == '=') {
434c80476e4SDavid E. O'Brien 	    c = '=';
435c80476e4SDavid E. O'Brien 	    p = xset(p, &v);
436c80476e4SDavid E. O'Brien 	}
437c80476e4SDavid E. O'Brien 	else {
438c80476e4SDavid E. O'Brien 	    c = *p++;
439c80476e4SDavid E. O'Brien 	    if (any("+-", c)) {
440c80476e4SDavid E. O'Brien 		if (c != op || *p)
441c80476e4SDavid E. O'Brien 		    stderror(ERR_NAME | ERR_UNKNOWNOP);
442c80476e4SDavid E. O'Brien 		p = Strsave(STR1);
443c80476e4SDavid E. O'Brien 	    }
444c80476e4SDavid E. O'Brien 	    else {
445c80476e4SDavid E. O'Brien 		if (any("<>", op)) {
446c80476e4SDavid E. O'Brien 		    if (c != op)
447c80476e4SDavid E. O'Brien 			stderror(ERR_NAME | ERR_UNKNOWNOP);
448c80476e4SDavid E. O'Brien 		    stderror(ERR_NAME | ERR_SYNTAX);
449c80476e4SDavid E. O'Brien 		}
450c80476e4SDavid E. O'Brien 		if (c != '=')
451c80476e4SDavid E. O'Brien 		    stderror(ERR_NAME | ERR_UNKNOWNOP);
452c80476e4SDavid E. O'Brien 		p = xset(p, &v);
453c80476e4SDavid E. O'Brien 	    }
454c80476e4SDavid E. O'Brien 	}
45545e5710bSMark Peek 	cleanup_push(p, xfree);
456c80476e4SDavid E. O'Brien 	if (op == '=') {
457c80476e4SDavid E. O'Brien 	    if (hadsub)
458c80476e4SDavid E. O'Brien 		asx(vp, subscr, p);
459c80476e4SDavid E. O'Brien 	    else
46045e5710bSMark Peek 		setv(vp, p, VAR_READWRITE);
46145e5710bSMark Peek 	    cleanup_ignore(p);
462c80476e4SDavid E. O'Brien 	}
463c80476e4SDavid E. O'Brien 	else if (hadsub) {
464c80476e4SDavid E. O'Brien 	    struct varent *gv = getvx(vp, subscr);
46545e5710bSMark Peek 	    Char *val;
466c80476e4SDavid E. O'Brien 
46745e5710bSMark Peek 	    val = operate(op, gv->vec[subscr - 1], p);
46845e5710bSMark Peek 	    cleanup_push(val, xfree);
46945e5710bSMark Peek 	    asx(vp, subscr, val);
47045e5710bSMark Peek 	    cleanup_ignore(val);
47145e5710bSMark Peek 	    cleanup_until(val);
472c80476e4SDavid E. O'Brien 	}
47345e5710bSMark Peek 	else {
47445e5710bSMark Peek 	    Char *val;
47545e5710bSMark Peek 
47645e5710bSMark Peek 	    val = operate(op, varval(vp), p);
47745e5710bSMark Peek 	    cleanup_push(val, xfree);
47845e5710bSMark Peek 	    setv(vp, val, VAR_READWRITE);
47945e5710bSMark Peek 	    cleanup_ignore(val);
48045e5710bSMark Peek 	    cleanup_until(val);
48145e5710bSMark Peek 	}
482c80476e4SDavid E. O'Brien 	update_vars(vp);
48345e5710bSMark Peek 	cleanup_until(vp);
484c80476e4SDavid E. O'Brien     } while ((p = *v++) != NULL);
485c80476e4SDavid E. O'Brien }
486c80476e4SDavid E. O'Brien 
487c80476e4SDavid E. O'Brien static Char *
48845e5710bSMark Peek xset(Char *cp, Char ***vp)
489c80476e4SDavid E. O'Brien {
49023338178SMark Peek     Char *dp;
491c80476e4SDavid E. O'Brien 
492c80476e4SDavid E. O'Brien     if (*cp) {
493c80476e4SDavid E. O'Brien 	dp = Strsave(cp);
494c80476e4SDavid E. O'Brien 	--(*vp);
49545e5710bSMark Peek 	xfree(** vp);
496c80476e4SDavid E. O'Brien 	**vp = dp;
497c80476e4SDavid E. O'Brien     }
498c80476e4SDavid E. O'Brien     return (putn(expr(vp)));
499c80476e4SDavid E. O'Brien }
500c80476e4SDavid E. O'Brien 
501c80476e4SDavid E. O'Brien static Char *
50245e5710bSMark Peek operate(int op, Char *vp, Char *p)
503c80476e4SDavid E. O'Brien {
504c80476e4SDavid E. O'Brien     Char    opr[2];
505c80476e4SDavid E. O'Brien     Char   *vec[5];
50623338178SMark Peek     Char **v = vec;
507c80476e4SDavid E. O'Brien     Char  **vecp = v;
5089ccc37e3SMark Peek     tcsh_number_t i;
509c80476e4SDavid E. O'Brien 
510c80476e4SDavid E. O'Brien     if (op != '=') {
511c80476e4SDavid E. O'Brien 	if (*vp)
512c80476e4SDavid E. O'Brien 	    *v++ = vp;
51345e5710bSMark Peek 	opr[0] = op;
514c80476e4SDavid E. O'Brien 	opr[1] = 0;
515c80476e4SDavid E. O'Brien 	*v++ = opr;
516c80476e4SDavid E. O'Brien 	if (op == '<' || op == '>')
517c80476e4SDavid E. O'Brien 	    *v++ = opr;
518c80476e4SDavid E. O'Brien     }
519c80476e4SDavid E. O'Brien     *v++ = p;
520c80476e4SDavid E. O'Brien     *v++ = 0;
521c80476e4SDavid E. O'Brien     i = expr(&vecp);
522c80476e4SDavid E. O'Brien     if (*vecp)
523c80476e4SDavid E. O'Brien 	stderror(ERR_NAME | ERR_EXPRESSION);
524c80476e4SDavid E. O'Brien     return (putn(i));
525c80476e4SDavid E. O'Brien }
526c80476e4SDavid E. O'Brien 
52745e5710bSMark Peek static Char *putp;
528c80476e4SDavid E. O'Brien 
529c80476e4SDavid E. O'Brien Char *
5309ccc37e3SMark Peek putn(tcsh_number_t n)
531c80476e4SDavid E. O'Brien {
5329ccc37e3SMark Peek     Char nbuf[1024]; /* Enough even for octal */
533c80476e4SDavid E. O'Brien 
534c80476e4SDavid E. O'Brien     putp = nbuf;
535c80476e4SDavid E. O'Brien     if (n < 0) {
536c80476e4SDavid E. O'Brien 	n = -n;
537c80476e4SDavid E. O'Brien 	*putp++ = '-';
538c80476e4SDavid E. O'Brien     }
539c80476e4SDavid E. O'Brien     putn1(n);
540c80476e4SDavid E. O'Brien     *putp = 0;
541c80476e4SDavid E. O'Brien     return (Strsave(nbuf));
542c80476e4SDavid E. O'Brien }
543c80476e4SDavid E. O'Brien 
544c80476e4SDavid E. O'Brien static void
5459ccc37e3SMark Peek putn1(tcsh_number_t n)
546c80476e4SDavid E. O'Brien {
547c80476e4SDavid E. O'Brien     if (n > 9)
548c80476e4SDavid E. O'Brien 	putn1(n / 10);
5499ccc37e3SMark Peek     *putp++ = (Char)(n % 10 + '0');
550c80476e4SDavid E. O'Brien }
551c80476e4SDavid E. O'Brien 
5529ccc37e3SMark Peek tcsh_number_t
5539ccc37e3SMark Peek getn(const Char *cp)
554c80476e4SDavid E. O'Brien {
5559ccc37e3SMark Peek     tcsh_number_t n;
556c80476e4SDavid E. O'Brien     int     sign;
557a15e6f9aSMark Peek     int base;
558c80476e4SDavid E. O'Brien 
559c80476e4SDavid E. O'Brien     if (!cp)			/* PWP: extra error checking */
560c80476e4SDavid E. O'Brien 	stderror(ERR_NAME | ERR_BADNUM);
561c80476e4SDavid E. O'Brien 
562c80476e4SDavid E. O'Brien     sign = 0;
563c80476e4SDavid E. O'Brien     if (cp[0] == '+' && cp[1])
564c80476e4SDavid E. O'Brien 	cp++;
565c80476e4SDavid E. O'Brien     if (*cp == '-') {
566c80476e4SDavid E. O'Brien 	sign++;
567c80476e4SDavid E. O'Brien 	cp++;
568c80476e4SDavid E. O'Brien 	if (!Isdigit(*cp))
569c80476e4SDavid E. O'Brien 	    stderror(ERR_NAME | ERR_BADNUM);
570c80476e4SDavid E. O'Brien     }
571a15e6f9aSMark Peek 
5729ccc37e3SMark Peek     if (cp[0] == '0' && cp[1] && is_set(STRparseoctal))
573a15e6f9aSMark Peek 	base = 8;
574a15e6f9aSMark Peek     else
575a15e6f9aSMark Peek 	base = 10;
576a15e6f9aSMark Peek 
577c80476e4SDavid E. O'Brien     n = 0;
578c80476e4SDavid E. O'Brien     while (Isdigit(*cp))
579a15e6f9aSMark Peek     {
580a15e6f9aSMark Peek 	if (base == 8 && *cp >= '8')
581a15e6f9aSMark Peek 	    stderror(ERR_NAME | ERR_BADNUM);
582a15e6f9aSMark Peek 	n = n * base + *cp++ - '0';
583a15e6f9aSMark Peek     }
584c80476e4SDavid E. O'Brien     if (*cp)
585c80476e4SDavid E. O'Brien 	stderror(ERR_NAME | ERR_BADNUM);
586c80476e4SDavid E. O'Brien     return (sign ? -n : n);
587c80476e4SDavid E. O'Brien }
588c80476e4SDavid E. O'Brien 
589c80476e4SDavid E. O'Brien Char   *
59045e5710bSMark Peek value1(Char *var, struct varent *head)
591c80476e4SDavid E. O'Brien {
59223338178SMark Peek     struct varent *vp;
593c80476e4SDavid E. O'Brien 
594c80476e4SDavid E. O'Brien     if (!var || !head)		/* PWP: extra error checking */
595c80476e4SDavid E. O'Brien 	return (STRNULL);
596c80476e4SDavid E. O'Brien 
597c80476e4SDavid E. O'Brien     vp = adrof1(var, head);
59829301572SMark Peek     return ((vp == NULL || vp->vec == NULL || vp->vec[0] == NULL) ?
59929301572SMark Peek 	STRNULL : vp->vec[0]);
600c80476e4SDavid E. O'Brien }
601c80476e4SDavid E. O'Brien 
602c80476e4SDavid E. O'Brien static struct varent *
60345e5710bSMark Peek madrof(Char *pat, struct varent *vp)
604c80476e4SDavid E. O'Brien {
60523338178SMark Peek     struct varent *vp1;
606c80476e4SDavid E. O'Brien 
607c80476e4SDavid E. O'Brien     for (vp = vp->v_left; vp; vp = vp->v_right) {
608c80476e4SDavid E. O'Brien 	if (vp->v_left && (vp1 = madrof(pat, vp)) != NULL)
609c80476e4SDavid E. O'Brien 	    return vp1;
610c80476e4SDavid E. O'Brien 	if (Gmatch(vp->v_name, pat))
611c80476e4SDavid E. O'Brien 	    return vp;
612c80476e4SDavid E. O'Brien     }
613c80476e4SDavid E. O'Brien     return vp;
614c80476e4SDavid E. O'Brien }
615c80476e4SDavid E. O'Brien 
616c80476e4SDavid E. O'Brien struct varent *
61745e5710bSMark Peek adrof1(const Char *name, struct varent *v)
618c80476e4SDavid E. O'Brien {
619c80476e4SDavid E. O'Brien     int cmp;
620c80476e4SDavid E. O'Brien 
621c80476e4SDavid E. O'Brien     v = v->v_left;
622c80476e4SDavid E. O'Brien     while (v && ((cmp = *name - *v->v_name) != 0 ||
623c80476e4SDavid E. O'Brien 		 (cmp = Strcmp(name, v->v_name)) != 0))
624c80476e4SDavid E. O'Brien 	if (cmp < 0)
625c80476e4SDavid E. O'Brien 	    v = v->v_left;
626c80476e4SDavid E. O'Brien 	else
627c80476e4SDavid E. O'Brien 	    v = v->v_right;
628c80476e4SDavid E. O'Brien     return v;
629c80476e4SDavid E. O'Brien }
630c80476e4SDavid E. O'Brien 
63145e5710bSMark Peek void
63245e5710bSMark Peek setcopy(const Char *var, const Char *val, int flags)
63345e5710bSMark Peek {
63445e5710bSMark Peek     Char *copy;
63545e5710bSMark Peek 
63645e5710bSMark Peek     copy = Strsave(val);
63745e5710bSMark Peek     cleanup_push(copy, xfree);
63845e5710bSMark Peek     setv(var, copy, flags);
63945e5710bSMark Peek     cleanup_ignore(copy);
64045e5710bSMark Peek     cleanup_until(copy);
64145e5710bSMark Peek }
64245e5710bSMark Peek 
643c80476e4SDavid E. O'Brien /*
644c80476e4SDavid E. O'Brien  * The caller is responsible for putting value in a safe place
645c80476e4SDavid E. O'Brien  */
646c80476e4SDavid E. O'Brien void
64745e5710bSMark Peek setv(const Char *var, Char *val, int flags)
648c80476e4SDavid E. O'Brien {
64945e5710bSMark Peek     Char **vec = xmalloc(2 * sizeof(Char **));
650c80476e4SDavid E. O'Brien 
651c80476e4SDavid E. O'Brien     vec[0] = val;
652c80476e4SDavid E. O'Brien     vec[1] = 0;
653c80476e4SDavid E. O'Brien     set1(var, vec, &shvhed, flags);
654c80476e4SDavid E. O'Brien }
655c80476e4SDavid E. O'Brien 
656c80476e4SDavid E. O'Brien void
65745e5710bSMark Peek set1(const Char *var, Char **vec, struct varent *head, int flags)
658c80476e4SDavid E. O'Brien {
65923338178SMark Peek     Char **oldv = vec;
660c80476e4SDavid E. O'Brien 
661c80476e4SDavid E. O'Brien     if ((flags & VAR_NOGLOB) == 0) {
66245e5710bSMark Peek 	int gflag;
66345e5710bSMark Peek 
66445e5710bSMark Peek 	gflag = tglob(oldv);
665c80476e4SDavid E. O'Brien 	if (gflag) {
66645e5710bSMark Peek 	    vec = globall(oldv, gflag);
667c80476e4SDavid E. O'Brien 	    if (vec == 0) {
668c80476e4SDavid E. O'Brien 		blkfree(oldv);
669c80476e4SDavid E. O'Brien 		stderror(ERR_NAME | ERR_NOMATCH);
670c80476e4SDavid E. O'Brien 	    }
671c80476e4SDavid E. O'Brien 	    blkfree(oldv);
672c80476e4SDavid E. O'Brien 	}
673c80476e4SDavid E. O'Brien     }
674c80476e4SDavid E. O'Brien     /*
675c80476e4SDavid E. O'Brien      * Uniqueness addition from: Michael Veksler <mveksler@vnet.ibm.com>
676c80476e4SDavid E. O'Brien      */
677c80476e4SDavid E. O'Brien     if ( flags & (VAR_FIRST | VAR_LAST) ) {
678c80476e4SDavid E. O'Brien 	/*
679c80476e4SDavid E. O'Brien 	 * Code for -f (VAR_FIRST) and -l (VAR_LAST) options.
680c80476e4SDavid E. O'Brien 	 * Method:
681c80476e4SDavid E. O'Brien 	 *  Delete all duplicate words leaving "holes" in the word array (vec).
682c80476e4SDavid E. O'Brien 	 *  Then remove the "holes", keeping the order of the words unchanged.
683c80476e4SDavid E. O'Brien 	 */
684c80476e4SDavid E. O'Brien 	if (vec && vec[0] && vec[1]) { /* more than one word ? */
685c80476e4SDavid E. O'Brien 	    int i, j;
686c80476e4SDavid E. O'Brien 	    int num_items;
687c80476e4SDavid E. O'Brien 
688c80476e4SDavid E. O'Brien 	    for (num_items = 0; vec[num_items]; num_items++)
689c80476e4SDavid E. O'Brien 	        continue;
690c80476e4SDavid E. O'Brien 	    if (flags & VAR_FIRST) {
691c80476e4SDavid E. O'Brien 		/* delete duplications, keeping first occurance */
692c80476e4SDavid E. O'Brien 		for (i = 1; i < num_items; i++)
693c80476e4SDavid E. O'Brien 		    for (j = 0; j < i; j++)
694c80476e4SDavid E. O'Brien 			/* If have earlier identical item, remove i'th item */
695c80476e4SDavid E. O'Brien 			if (vec[i] && vec[j] && Strcmp(vec[j], vec[i]) == 0) {
69645e5710bSMark Peek 			    xfree(vec[i]);
697c80476e4SDavid E. O'Brien 			    vec[i] = NULL;
698c80476e4SDavid E. O'Brien 			    break;
699c80476e4SDavid E. O'Brien 			}
700c80476e4SDavid E. O'Brien 	    } else if (flags & VAR_LAST) {
701c80476e4SDavid E. O'Brien 	      /* delete duplications, keeping last occurance */
702c80476e4SDavid E. O'Brien 		for (i = 0; i < num_items - 1; i++)
703c80476e4SDavid E. O'Brien 		    for (j = i + 1; j < num_items; j++)
704c80476e4SDavid E. O'Brien 			/* If have later identical item, remove i'th item */
705c80476e4SDavid E. O'Brien 			if (vec[i] && vec[j] && Strcmp(vec[j], vec[i]) == 0) {
706c80476e4SDavid E. O'Brien 			    /* remove identical item (the first) */
70745e5710bSMark Peek 			    xfree(vec[i]);
708c80476e4SDavid E. O'Brien 			    vec[i] = NULL;
709c80476e4SDavid E. O'Brien 			}
710c80476e4SDavid E. O'Brien 	    }
711c80476e4SDavid E. O'Brien 	    /* Compress items - remove empty items */
712c80476e4SDavid E. O'Brien 	    for (j = i = 0; i < num_items; i++)
713c80476e4SDavid E. O'Brien 	       if (vec[i])
714c80476e4SDavid E. O'Brien 		  vec[j++] = vec[i];
715c80476e4SDavid E. O'Brien 
716c80476e4SDavid E. O'Brien 	    /* NULL-fy remaining items */
717c80476e4SDavid E. O'Brien 	    for (; j < num_items; j++)
718c80476e4SDavid E. O'Brien 		 vec[j] = NULL;
719c80476e4SDavid E. O'Brien 	}
720c80476e4SDavid E. O'Brien 	/* don't let the attribute propagate */
721c80476e4SDavid E. O'Brien 	flags &= ~(VAR_FIRST|VAR_LAST);
722c80476e4SDavid E. O'Brien     }
723c80476e4SDavid E. O'Brien     setq(var, vec, head, flags);
724c80476e4SDavid E. O'Brien }
725c80476e4SDavid E. O'Brien 
726c80476e4SDavid E. O'Brien 
727c80476e4SDavid E. O'Brien void
72845e5710bSMark Peek setq(const Char *name, Char **vec, struct varent *p, int flags)
729c80476e4SDavid E. O'Brien {
73023338178SMark Peek     struct varent *c;
73123338178SMark Peek     int f;
732c80476e4SDavid E. O'Brien 
733c80476e4SDavid E. O'Brien     f = 0;			/* tree hangs off the header's left link */
734c80476e4SDavid E. O'Brien     while ((c = p->v_link[f]) != 0) {
735c80476e4SDavid E. O'Brien 	if ((f = *name - *c->v_name) == 0 &&
736c80476e4SDavid E. O'Brien 	    (f = Strcmp(name, c->v_name)) == 0) {
737c80476e4SDavid E. O'Brien 	    if (c->v_flags & VAR_READONLY)
738c80476e4SDavid E. O'Brien 		stderror(ERR_READONLY|ERR_NAME, c->v_name);
739c80476e4SDavid E. O'Brien 	    blkfree(c->vec);
740c80476e4SDavid E. O'Brien 	    c->v_flags = flags;
741c80476e4SDavid E. O'Brien 	    trim(c->vec = vec);
742c80476e4SDavid E. O'Brien 	    return;
743c80476e4SDavid E. O'Brien 	}
744c80476e4SDavid E. O'Brien 	p = c;
745c80476e4SDavid E. O'Brien 	f = f > 0;
746c80476e4SDavid E. O'Brien     }
74745e5710bSMark Peek     p->v_link[f] = c = xmalloc(sizeof(struct varent));
748c80476e4SDavid E. O'Brien     c->v_name = Strsave(name);
749c80476e4SDavid E. O'Brien     c->v_flags = flags;
750c80476e4SDavid E. O'Brien     c->v_bal = 0;
751c80476e4SDavid E. O'Brien     c->v_left = c->v_right = 0;
752c80476e4SDavid E. O'Brien     c->v_parent = p;
753c80476e4SDavid E. O'Brien     balance(p, f, 0);
754c80476e4SDavid E. O'Brien     trim(c->vec = vec);
755c80476e4SDavid E. O'Brien }
756c80476e4SDavid E. O'Brien 
757c80476e4SDavid E. O'Brien /*ARGSUSED*/
758c80476e4SDavid E. O'Brien void
75945e5710bSMark Peek unset(Char **v, struct command *c)
760c80476e4SDavid E. O'Brien {
76123338178SMark Peek     int did_roe, did_edit;
762c80476e4SDavid E. O'Brien 
763c80476e4SDavid E. O'Brien     USE(c);
764c80476e4SDavid E. O'Brien     did_roe = adrof(STRrecognize_only_executables) != NULL;
765c80476e4SDavid E. O'Brien     did_edit = adrof(STRedit) != NULL;
766c80476e4SDavid E. O'Brien     unset1(v, &shvhed);
76729301572SMark Peek 
76829301572SMark Peek #if defined(FILEC) && defined(TIOCSTI)
76929301572SMark Peek     if (adrof(STRfilec) == 0)
77029301572SMark Peek 	filec = 0;
77129301572SMark Peek #endif /* FILEC && TIOCSTI */
77229301572SMark Peek 
773c80476e4SDavid E. O'Brien     if (adrof(STRhistchars) == 0) {
774c80476e4SDavid E. O'Brien 	HIST = '!';
775c80476e4SDavid E. O'Brien 	HISTSUB = '^';
776c80476e4SDavid E. O'Brien     }
777b2d5d167SMark Peek     if (adrof(STRignoreeof) == 0)
778b2d5d167SMark Peek 	numeof = 0;
779c80476e4SDavid E. O'Brien     if (adrof(STRpromptchars) == 0) {
7809ccc37e3SMark Peek 	PRCH = tcsh ? '>' : '%';
781c80476e4SDavid E. O'Brien 	PRCHROOT = '#';
782c80476e4SDavid E. O'Brien     }
783*19d2e3deSDmitry Chagin     if (adrof(STRnoclobber) == 0)
784*19d2e3deSDmitry Chagin 	no_clobber = 0;
785c80476e4SDavid E. O'Brien     if (adrof(STRhistlit) == 0)
786c80476e4SDavid E. O'Brien 	HistLit = 0;
787c80476e4SDavid E. O'Brien     if (adrof(STRloginsh) == 0)
788c80476e4SDavid E. O'Brien 	loginsh = 0;
7899ccc37e3SMark Peek     if (adrof(STRanyerror) == 0)
7909ccc37e3SMark Peek 	anyerror = 0;
791c80476e4SDavid E. O'Brien     if (adrof(STRwordchars) == 0)
792c80476e4SDavid E. O'Brien 	word_chars = STR_WORD_CHARS;
793c80476e4SDavid E. O'Brien     if (adrof(STRedit) == 0)
794c80476e4SDavid E. O'Brien 	editing = 0;
795c80476e4SDavid E. O'Brien     if (adrof(STRbackslash_quote) == 0)
796c80476e4SDavid E. O'Brien 	bslash_quote = 0;
797a15e6f9aSMark Peek     if (adrof(STRcompat_expr) == 0)
798a15e6f9aSMark Peek 	compat_expr = 0;
799c80476e4SDavid E. O'Brien     if (adrof(STRsymlinks) == 0)
800c80476e4SDavid E. O'Brien 	symlinks = 0;
801c80476e4SDavid E. O'Brien     if (adrof(STRimplicitcd) == 0)
802c80476e4SDavid E. O'Brien 	implicit_cd = 0;
803*19d2e3deSDmitry Chagin     if (adrof(STRcdtohome) == 0)
804*19d2e3deSDmitry Chagin 	cdtohome = 0;
8056767bd61SMark Peek     if (adrof(STRkillring) == 0)
8066767bd61SMark Peek 	SetKillRing(0);
807c80476e4SDavid E. O'Brien     if (did_edit && noediting && adrof(STRedit) == 0)
808c80476e4SDavid E. O'Brien 	noediting = 0;
809*19d2e3deSDmitry Chagin     if (adrof(STRvimode) == 0)
810*19d2e3deSDmitry Chagin 	VImode = 0;
811c80476e4SDavid E. O'Brien     if (did_roe && adrof(STRrecognize_only_executables) == 0)
812c80476e4SDavid E. O'Brien 	tw_cmd_free();
813*19d2e3deSDmitry Chagin     if (adrof(STRhistory) == 0)
814*19d2e3deSDmitry Chagin 	sethistory(0);
815c80476e4SDavid E. O'Brien #ifdef COLOR_LS_F
816c80476e4SDavid E. O'Brien     if (adrof(STRcolor) == 0)
817c80476e4SDavid E. O'Brien 	set_color_context();
818c80476e4SDavid E. O'Brien #endif /* COLOR_LS_F */
819c80476e4SDavid E. O'Brien #if defined(KANJI) && defined(SHORT_STRINGS) && defined(DSPMBYTE)
820c80476e4SDavid E. O'Brien     update_dspmbyte_vars();
821c80476e4SDavid E. O'Brien #endif
822*19d2e3deSDmitry Chagin     update_wordchars();
8233b6eaa7bSAndrey A. Chernov #ifdef NLS_CATALOGS
82423338178SMark Peek     nlsclose();
8253b6eaa7bSAndrey A. Chernov     nlsinit();
8263b6eaa7bSAndrey A. Chernov #endif /* NLS_CATALOGS */
827c80476e4SDavid E. O'Brien }
828c80476e4SDavid E. O'Brien 
829c80476e4SDavid E. O'Brien void
83045e5710bSMark Peek unset1(Char *v[], struct varent *head)
831c80476e4SDavid E. O'Brien {
83223338178SMark Peek     struct varent *vp;
83323338178SMark Peek     int cnt;
834c80476e4SDavid E. O'Brien 
835c80476e4SDavid E. O'Brien     while (*++v) {
836c80476e4SDavid E. O'Brien 	cnt = 0;
837c80476e4SDavid E. O'Brien 	while ((vp = madrof(*v, head)) != NULL)
838c80476e4SDavid E. O'Brien 	    if (vp->v_flags & VAR_READONLY)
839c80476e4SDavid E. O'Brien 		stderror(ERR_READONLY|ERR_NAME, vp->v_name);
840c80476e4SDavid E. O'Brien 	    else
841c80476e4SDavid E. O'Brien 		unsetv1(vp), cnt++;
842c80476e4SDavid E. O'Brien 	if (cnt == 0)
843c80476e4SDavid E. O'Brien 	    setname(short2str(*v));
844c80476e4SDavid E. O'Brien     }
845c80476e4SDavid E. O'Brien }
846c80476e4SDavid E. O'Brien 
847c80476e4SDavid E. O'Brien void
84845e5710bSMark Peek unsetv(Char *var)
849c80476e4SDavid E. O'Brien {
85023338178SMark Peek     struct varent *vp;
851c80476e4SDavid E. O'Brien 
852c80476e4SDavid E. O'Brien     if ((vp = adrof1(var, &shvhed)) == 0)
853c80476e4SDavid E. O'Brien 	udvar(var);
854c80476e4SDavid E. O'Brien     unsetv1(vp);
855c80476e4SDavid E. O'Brien }
856c80476e4SDavid E. O'Brien 
857c80476e4SDavid E. O'Brien static void
85845e5710bSMark Peek unsetv1(struct varent *p)
859c80476e4SDavid E. O'Brien {
86023338178SMark Peek     struct varent *c, *pp;
86123338178SMark Peek     int f;
862c80476e4SDavid E. O'Brien 
863c80476e4SDavid E. O'Brien     /*
864c80476e4SDavid E. O'Brien      * Free associated memory first to avoid complications.
865c80476e4SDavid E. O'Brien      */
866c80476e4SDavid E. O'Brien     blkfree(p->vec);
86745e5710bSMark Peek     xfree(p->v_name);
868c80476e4SDavid E. O'Brien     /*
869c80476e4SDavid E. O'Brien      * If p is missing one child, then we can move the other into where p is.
870c80476e4SDavid E. O'Brien      * Otherwise, we find the predecessor of p, which is guaranteed to have no
871c80476e4SDavid E. O'Brien      * right child, copy it into p, and move it's left child into it.
872c80476e4SDavid E. O'Brien      */
873c80476e4SDavid E. O'Brien     if (p->v_right == 0)
874c80476e4SDavid E. O'Brien 	c = p->v_left;
875c80476e4SDavid E. O'Brien     else if (p->v_left == 0)
876c80476e4SDavid E. O'Brien 	c = p->v_right;
877c80476e4SDavid E. O'Brien     else {
878c80476e4SDavid E. O'Brien 	for (c = p->v_left; c->v_right; c = c->v_right)
879c80476e4SDavid E. O'Brien 	    continue;
880c80476e4SDavid E. O'Brien 	p->v_name = c->v_name;
881c80476e4SDavid E. O'Brien 	p->v_flags = c->v_flags;
882c80476e4SDavid E. O'Brien 	p->vec = c->vec;
883c80476e4SDavid E. O'Brien 	p = c;
884c80476e4SDavid E. O'Brien 	c = p->v_left;
885c80476e4SDavid E. O'Brien     }
886c80476e4SDavid E. O'Brien 
887c80476e4SDavid E. O'Brien     /*
888c80476e4SDavid E. O'Brien      * Move c into where p is.
889c80476e4SDavid E. O'Brien      */
890c80476e4SDavid E. O'Brien     pp = p->v_parent;
891c80476e4SDavid E. O'Brien     f = pp->v_right == p;
892c80476e4SDavid E. O'Brien     if ((pp->v_link[f] = c) != 0)
893c80476e4SDavid E. O'Brien 	c->v_parent = pp;
894c80476e4SDavid E. O'Brien     /*
895c80476e4SDavid E. O'Brien      * Free the deleted node, and rebalance.
896c80476e4SDavid E. O'Brien      */
89745e5710bSMark Peek     xfree(p);
898c80476e4SDavid E. O'Brien     balance(pp, f, 1);
899c80476e4SDavid E. O'Brien }
900c80476e4SDavid E. O'Brien 
9019ccc37e3SMark Peek /* Set variable name to NULL. */
902c80476e4SDavid E. O'Brien void
9039ccc37e3SMark Peek setNS(const Char *varName)
904c80476e4SDavid E. O'Brien {
9059ccc37e3SMark Peek     setcopy(varName, STRNULL, VAR_READWRITE);
906c80476e4SDavid E. O'Brien }
907c80476e4SDavid E. O'Brien 
908c80476e4SDavid E. O'Brien /*ARGSUSED*/
909c80476e4SDavid E. O'Brien void
91045e5710bSMark Peek shift(Char **v, struct command *c)
911c80476e4SDavid E. O'Brien {
91223338178SMark Peek     struct varent *argv;
91323338178SMark Peek     Char *name;
914c80476e4SDavid E. O'Brien 
915c80476e4SDavid E. O'Brien     USE(c);
916c80476e4SDavid E. O'Brien     v++;
917c80476e4SDavid E. O'Brien     name = *v;
918c80476e4SDavid E. O'Brien     if (name == 0)
919c80476e4SDavid E. O'Brien 	name = STRargv;
920c80476e4SDavid E. O'Brien     else
921c80476e4SDavid E. O'Brien 	(void) strip(name);
922c80476e4SDavid E. O'Brien     argv = adrof(name);
92329301572SMark Peek     if (argv == NULL || argv->vec == NULL)
924c80476e4SDavid E. O'Brien 	udvar(name);
925c80476e4SDavid E. O'Brien     if (argv->vec[0] == 0)
926c80476e4SDavid E. O'Brien 	stderror(ERR_NAME | ERR_NOMORE);
927c80476e4SDavid E. O'Brien     lshift(argv->vec, 1);
928c80476e4SDavid E. O'Brien     update_vars(name);
929c80476e4SDavid E. O'Brien }
930c80476e4SDavid E. O'Brien 
931c80476e4SDavid E. O'Brien static void
93245e5710bSMark Peek exportpath(Char **val)
933c80476e4SDavid E. O'Brien {
93445e5710bSMark Peek     struct Strbuf buf = Strbuf_INIT;
935c80476e4SDavid E. O'Brien     Char    	*exppath;
936c80476e4SDavid E. O'Brien 
937c80476e4SDavid E. O'Brien     if (val)
938c80476e4SDavid E. O'Brien 	while (*val) {
93945e5710bSMark Peek 	    Strbuf_append(&buf, *val++);
940c80476e4SDavid E. O'Brien 	    if (*val == 0 || eq(*val, STRRparen))
941c80476e4SDavid E. O'Brien 		break;
94245e5710bSMark Peek 	    Strbuf_append1(&buf, PATHSEP);
943c80476e4SDavid E. O'Brien 	}
94445e5710bSMark Peek     exppath = Strbuf_finish(&buf);
94545e5710bSMark Peek     cleanup_push(exppath, xfree);
946c80476e4SDavid E. O'Brien     tsetenv(STRKPATH, exppath);
94745e5710bSMark Peek     cleanup_until(exppath);
948c80476e4SDavid E. O'Brien }
949c80476e4SDavid E. O'Brien 
950*19d2e3deSDmitry Chagin static int
951*19d2e3deSDmitry Chagin set_noclobber(Char **val)
952*19d2e3deSDmitry Chagin {
953*19d2e3deSDmitry Chagin     Char *option;
954*19d2e3deSDmitry Chagin     int nc = NOCLOBBER_DEFAULT;
955*19d2e3deSDmitry Chagin 
956*19d2e3deSDmitry Chagin     if (val == NULL)
957*19d2e3deSDmitry Chagin 	return nc;
958*19d2e3deSDmitry Chagin     while (*val) {
959*19d2e3deSDmitry Chagin 	if (*val == 0 || eq(*val, STRRparen))
960*19d2e3deSDmitry Chagin 	    return nc;
961*19d2e3deSDmitry Chagin 
962*19d2e3deSDmitry Chagin 	option = *val++;
963*19d2e3deSDmitry Chagin 
964*19d2e3deSDmitry Chagin 	if (eq(option, STRnotempty))
965*19d2e3deSDmitry Chagin 	    nc |= NOCLOBBER_NOTEMPTY;
966*19d2e3deSDmitry Chagin 	else if (eq(option, STRask))
967*19d2e3deSDmitry Chagin 	    nc |= NOCLOBBER_ASK;
968*19d2e3deSDmitry Chagin     }
969*19d2e3deSDmitry Chagin     return nc;
970*19d2e3deSDmitry Chagin }
971*19d2e3deSDmitry Chagin 
972c80476e4SDavid E. O'Brien #ifndef lint
973c80476e4SDavid E. O'Brien  /*
974c80476e4SDavid E. O'Brien   * Lint thinks these have null effect
975c80476e4SDavid E. O'Brien   */
976c80476e4SDavid E. O'Brien  /* macros to do single rotations on node p */
977c80476e4SDavid E. O'Brien # define rright(p) (\
978c80476e4SDavid E. O'Brien 	t = (p)->v_left,\
979c80476e4SDavid E. O'Brien 	(t)->v_parent = (p)->v_parent,\
980c80476e4SDavid E. O'Brien 	(((p)->v_left = t->v_right) != NULL) ?\
981c80476e4SDavid E. O'Brien 	    (t->v_right->v_parent = (p)) : 0,\
982c80476e4SDavid E. O'Brien 	(t->v_right = (p))->v_parent = t,\
983c80476e4SDavid E. O'Brien 	(p) = t)
984c80476e4SDavid E. O'Brien # define rleft(p) (\
985c80476e4SDavid E. O'Brien 	t = (p)->v_right,\
986c80476e4SDavid E. O'Brien 	((t)->v_parent = (p)->v_parent,\
987c80476e4SDavid E. O'Brien 	((p)->v_right = t->v_left) != NULL) ? \
988c80476e4SDavid E. O'Brien 		(t->v_left->v_parent = (p)) : 0,\
989c80476e4SDavid E. O'Brien 	(t->v_left = (p))->v_parent = t,\
990c80476e4SDavid E. O'Brien 	(p) = t)
991c80476e4SDavid E. O'Brien #else
992c80476e4SDavid E. O'Brien static struct varent *
99345e5710bSMark Peek rleft(struct varent *p)
994c80476e4SDavid E. O'Brien {
995c80476e4SDavid E. O'Brien     return (p);
996c80476e4SDavid E. O'Brien }
997c80476e4SDavid E. O'Brien static struct varent *
99845e5710bSMark Peek rright(struct varent *p)
999c80476e4SDavid E. O'Brien {
1000c80476e4SDavid E. O'Brien     return (p);
1001c80476e4SDavid E. O'Brien }
1002c80476e4SDavid E. O'Brien 
1003c80476e4SDavid E. O'Brien #endif /* ! lint */
1004c80476e4SDavid E. O'Brien 
1005c80476e4SDavid E. O'Brien 
1006c80476e4SDavid E. O'Brien /*
1007c80476e4SDavid E. O'Brien  * Rebalance a tree, starting at p and up.
1008c80476e4SDavid E. O'Brien  * F == 0 means we've come from p's left child.
1009c80476e4SDavid E. O'Brien  * D == 1 means we've just done a delete, otherwise an insert.
1010c80476e4SDavid E. O'Brien  */
1011c80476e4SDavid E. O'Brien static void
101245e5710bSMark Peek balance(struct varent *p, int f, int d)
1013c80476e4SDavid E. O'Brien {
101423338178SMark Peek     struct varent *pp;
1015c80476e4SDavid E. O'Brien 
1016c80476e4SDavid E. O'Brien #ifndef lint
101723338178SMark Peek     struct varent *t;	/* used by the rotate macros */
1018c80476e4SDavid E. O'Brien #endif /* !lint */
101923338178SMark Peek     int ff;
1020c80476e4SDavid E. O'Brien #ifdef lint
1021c80476e4SDavid E. O'Brien     ff = 0;	/* Sun's lint is dumb! */
1022c80476e4SDavid E. O'Brien #endif
1023c80476e4SDavid E. O'Brien 
1024c80476e4SDavid E. O'Brien     /*
1025c80476e4SDavid E. O'Brien      * Ok, from here on, p is the node we're operating on; pp is it's parent; f
1026c80476e4SDavid E. O'Brien      * is the branch of p from which we have come; ff is the branch of pp which
1027c80476e4SDavid E. O'Brien      * is p.
1028c80476e4SDavid E. O'Brien      */
1029c80476e4SDavid E. O'Brien     for (; (pp = p->v_parent) != 0; p = pp, f = ff) {
1030c80476e4SDavid E. O'Brien 	ff = pp->v_right == p;
1031c80476e4SDavid E. O'Brien 	if (f ^ d) {		/* right heavy */
1032c80476e4SDavid E. O'Brien 	    switch (p->v_bal) {
1033c80476e4SDavid E. O'Brien 	    case -1:		/* was left heavy */
1034c80476e4SDavid E. O'Brien 		p->v_bal = 0;
1035c80476e4SDavid E. O'Brien 		break;
1036c80476e4SDavid E. O'Brien 	    case 0:		/* was balanced */
1037c80476e4SDavid E. O'Brien 		p->v_bal = 1;
1038c80476e4SDavid E. O'Brien 		break;
1039c80476e4SDavid E. O'Brien 	    case 1:		/* was already right heavy */
1040c80476e4SDavid E. O'Brien 		switch (p->v_right->v_bal) {
104145e5710bSMark Peek 		case 1:	/* single rotate */
1042c80476e4SDavid E. O'Brien 		    pp->v_link[ff] = rleft(p);
1043c80476e4SDavid E. O'Brien 		    p->v_left->v_bal = 0;
1044c80476e4SDavid E. O'Brien 		    p->v_bal = 0;
1045c80476e4SDavid E. O'Brien 		    break;
1046c80476e4SDavid E. O'Brien 		case 0:	/* single rotate */
1047c80476e4SDavid E. O'Brien 		    pp->v_link[ff] = rleft(p);
1048c80476e4SDavid E. O'Brien 		    p->v_left->v_bal = 1;
1049c80476e4SDavid E. O'Brien 		    p->v_bal = -1;
1050c80476e4SDavid E. O'Brien 		    break;
1051c80476e4SDavid E. O'Brien 		case -1:	/* double rotate */
1052c80476e4SDavid E. O'Brien 		    (void) rright(p->v_right);
1053c80476e4SDavid E. O'Brien 		    pp->v_link[ff] = rleft(p);
1054c80476e4SDavid E. O'Brien 		    p->v_left->v_bal =
1055c80476e4SDavid E. O'Brien 			p->v_bal < 1 ? 0 : -1;
1056c80476e4SDavid E. O'Brien 		    p->v_right->v_bal =
1057c80476e4SDavid E. O'Brien 			p->v_bal > -1 ? 0 : 1;
1058c80476e4SDavid E. O'Brien 		    p->v_bal = 0;
1059c80476e4SDavid E. O'Brien 		    break;
1060c80476e4SDavid E. O'Brien 		default:
1061c80476e4SDavid E. O'Brien 		    break;
1062c80476e4SDavid E. O'Brien 		}
1063c80476e4SDavid E. O'Brien 		break;
1064c80476e4SDavid E. O'Brien 	    default:
1065c80476e4SDavid E. O'Brien 		break;
1066c80476e4SDavid E. O'Brien 	    }
1067c80476e4SDavid E. O'Brien 	}
1068c80476e4SDavid E. O'Brien 	else {			/* left heavy */
1069c80476e4SDavid E. O'Brien 	    switch (p->v_bal) {
1070c80476e4SDavid E. O'Brien 	    case 1:		/* was right heavy */
1071c80476e4SDavid E. O'Brien 		p->v_bal = 0;
1072c80476e4SDavid E. O'Brien 		break;
1073c80476e4SDavid E. O'Brien 	    case 0:		/* was balanced */
1074c80476e4SDavid E. O'Brien 		p->v_bal = -1;
1075c80476e4SDavid E. O'Brien 		break;
1076c80476e4SDavid E. O'Brien 	    case -1:		/* was already left heavy */
1077c80476e4SDavid E. O'Brien 		switch (p->v_left->v_bal) {
1078c80476e4SDavid E. O'Brien 		case -1:	/* single rotate */
1079c80476e4SDavid E. O'Brien 		    pp->v_link[ff] = rright(p);
1080c80476e4SDavid E. O'Brien 		    p->v_right->v_bal = 0;
1081c80476e4SDavid E. O'Brien 		    p->v_bal = 0;
1082c80476e4SDavid E. O'Brien 		    break;
108345e5710bSMark Peek 		case 0:	/* single rotate */
1084c80476e4SDavid E. O'Brien 		    pp->v_link[ff] = rright(p);
1085c80476e4SDavid E. O'Brien 		    p->v_right->v_bal = -1;
1086c80476e4SDavid E. O'Brien 		    p->v_bal = 1;
1087c80476e4SDavid E. O'Brien 		    break;
1088c80476e4SDavid E. O'Brien 		case 1:	/* double rotate */
1089c80476e4SDavid E. O'Brien 		    (void) rleft(p->v_left);
1090c80476e4SDavid E. O'Brien 		    pp->v_link[ff] = rright(p);
1091c80476e4SDavid E. O'Brien 		    p->v_left->v_bal =
1092c80476e4SDavid E. O'Brien 			p->v_bal < 1 ? 0 : -1;
1093c80476e4SDavid E. O'Brien 		    p->v_right->v_bal =
1094c80476e4SDavid E. O'Brien 			p->v_bal > -1 ? 0 : 1;
1095c80476e4SDavid E. O'Brien 		    p->v_bal = 0;
1096c80476e4SDavid E. O'Brien 		    break;
1097c80476e4SDavid E. O'Brien 		default:
1098c80476e4SDavid E. O'Brien 		    break;
1099c80476e4SDavid E. O'Brien 		}
1100c80476e4SDavid E. O'Brien 		break;
1101c80476e4SDavid E. O'Brien 	    default:
1102c80476e4SDavid E. O'Brien 		break;
1103c80476e4SDavid E. O'Brien 	    }
1104c80476e4SDavid E. O'Brien 	}
1105c80476e4SDavid E. O'Brien 	/*
1106c80476e4SDavid E. O'Brien 	 * If from insert, then we terminate when p is balanced. If from
1107c80476e4SDavid E. O'Brien 	 * delete, then we terminate when p is unbalanced.
1108c80476e4SDavid E. O'Brien 	 */
1109c80476e4SDavid E. O'Brien 	if ((p->v_bal == 0) ^ d)
1110c80476e4SDavid E. O'Brien 	    break;
1111c80476e4SDavid E. O'Brien     }
1112c80476e4SDavid E. O'Brien }
1113c80476e4SDavid E. O'Brien 
1114c80476e4SDavid E. O'Brien void
111545e5710bSMark Peek plist(struct varent *p, int what)
1116c80476e4SDavid E. O'Brien {
111723338178SMark Peek     struct varent *c;
111823338178SMark Peek     int len;
1119c80476e4SDavid E. O'Brien 
1120c80476e4SDavid E. O'Brien     for (;;) {
1121c80476e4SDavid E. O'Brien 	while (p->v_left)
1122c80476e4SDavid E. O'Brien 	    p = p->v_left;
1123c80476e4SDavid E. O'Brien x:
1124c80476e4SDavid E. O'Brien 	if (p->v_parent == 0)	/* is it the header? */
112545e5710bSMark Peek 	    break;
1126c80476e4SDavid E. O'Brien 	if ((p->v_flags & what) != 0) {
112745e5710bSMark Peek 	    if (setintr) {
112845e5710bSMark Peek 		int old_pintr_disabled;
112945e5710bSMark Peek 
113045e5710bSMark Peek 		pintr_push_enable(&old_pintr_disabled);
113145e5710bSMark Peek 		cleanup_until(&old_pintr_disabled);
113245e5710bSMark Peek 	    }
1133c80476e4SDavid E. O'Brien 	    len = blklen(p->vec);
1134c80476e4SDavid E. O'Brien 	    xprintf("%S\t", p->v_name);
1135c80476e4SDavid E. O'Brien 	    if (len != 1)
1136c80476e4SDavid E. O'Brien 		xputchar('(');
1137c80476e4SDavid E. O'Brien 	    blkpr(p->vec);
1138c80476e4SDavid E. O'Brien 	    if (len != 1)
1139c80476e4SDavid E. O'Brien 		xputchar(')');
1140c80476e4SDavid E. O'Brien 	    xputchar('\n');
1141c80476e4SDavid E. O'Brien 	}
1142c80476e4SDavid E. O'Brien 	if (p->v_right) {
1143c80476e4SDavid E. O'Brien 	    p = p->v_right;
1144c80476e4SDavid E. O'Brien 	    continue;
1145c80476e4SDavid E. O'Brien 	}
1146c80476e4SDavid E. O'Brien 	do {
1147c80476e4SDavid E. O'Brien 	    c = p;
1148c80476e4SDavid E. O'Brien 	    p = p->v_parent;
1149c80476e4SDavid E. O'Brien 	} while (p->v_right == c);
1150c80476e4SDavid E. O'Brien 	goto x;
1151c80476e4SDavid E. O'Brien     }
1152c80476e4SDavid E. O'Brien }
1153c80476e4SDavid E. O'Brien 
11549ccc37e3SMark Peek #if defined(KANJI)
11559ccc37e3SMark Peek # if defined(SHORT_STRINGS) && defined(DSPMBYTE)
115623338178SMark Peek extern int dspmbyte_ls;
1157c80476e4SDavid E. O'Brien 
1158c80476e4SDavid E. O'Brien void
115945e5710bSMark Peek update_dspmbyte_vars(void)
1160c80476e4SDavid E. O'Brien {
1161c80476e4SDavid E. O'Brien     int lp, iskcode;
1162c80476e4SDavid E. O'Brien     Char *dstr1;
1163c80476e4SDavid E. O'Brien     struct varent *vp;
1164c80476e4SDavid E. O'Brien 
1165c80476e4SDavid E. O'Brien     /* if variable "nokanji" is set, multi-byte display is disabled */
1166c80476e4SDavid E. O'Brien     if ((vp = adrof(CHECK_MBYTEVAR)) && !adrof(STRnokanji)) {
1167c80476e4SDavid E. O'Brien 	_enable_mbdisp = 1;
1168c80476e4SDavid E. O'Brien 	dstr1 = vp->vec[0];
116923338178SMark Peek 	if(eq (dstr1, STRsjis))
1170c80476e4SDavid E. O'Brien 	    iskcode = 1;
117123338178SMark Peek 	else if (eq(dstr1, STReuc))
1172c80476e4SDavid E. O'Brien 	    iskcode = 2;
117323338178SMark Peek 	else if (eq(dstr1, STRbig5))
11746767bd61SMark Peek 	    iskcode = 3;
117523338178SMark Peek 	else if (eq(dstr1, STRutf8))
117629301572SMark Peek 	    iskcode = 4;
1177c80476e4SDavid E. O'Brien 	else if ((dstr1[0] - '0') >= 0 && (dstr1[0] - '0') <= 3) {
1178c80476e4SDavid E. O'Brien 	    iskcode = 0;
1179c80476e4SDavid E. O'Brien 	}
1180c80476e4SDavid E. O'Brien 	else {
1181c80476e4SDavid E. O'Brien 	    xprintf(CGETS(18, 2,
1182c80476e4SDavid E. O'Brien 	       "Warning: unknown multibyte display; using default(euc(JP))\n"));
1183c80476e4SDavid E. O'Brien 	    iskcode = 2;
1184c80476e4SDavid E. O'Brien 	}
1185c80476e4SDavid E. O'Brien 	if (dstr1 && vp->vec[1] && eq(vp->vec[1], STRls))
1186c80476e4SDavid E. O'Brien 	  dspmbyte_ls = 1;
1187c80476e4SDavid E. O'Brien 	else
1188c80476e4SDavid E. O'Brien 	  dspmbyte_ls = 0;
1189c80476e4SDavid E. O'Brien 	for (lp = 0; lp < 256 && iskcode > 0; lp++) {
1190c80476e4SDavid E. O'Brien 	    switch (iskcode) {
1191c80476e4SDavid E. O'Brien 	    case 1:
1192c80476e4SDavid E. O'Brien 		/* Shift-JIS */
1193c80476e4SDavid E. O'Brien 		_cmap[lp] = _cmap_mbyte[lp];
1194c80476e4SDavid E. O'Brien 		_mbmap[lp] = _mbmap_sjis[lp];
1195c80476e4SDavid E. O'Brien 		break;
1196c80476e4SDavid E. O'Brien 	    case 2:
1197c80476e4SDavid E. O'Brien 		/* 2 ... euc */
1198c80476e4SDavid E. O'Brien 		_cmap[lp] = _cmap_mbyte[lp];
1199c80476e4SDavid E. O'Brien 		_mbmap[lp] = _mbmap_euc[lp];
1200c80476e4SDavid E. O'Brien 		break;
12016767bd61SMark Peek 	    case 3:
12026767bd61SMark Peek 		/* 3 ... big5 */
12036767bd61SMark Peek 		_cmap[lp] = _cmap_mbyte[lp];
12046767bd61SMark Peek 		_mbmap[lp] = _mbmap_big5[lp];
12056767bd61SMark Peek 		break;
120629301572SMark Peek 	    case 4:
120729301572SMark Peek 		/* 4 ... utf8 */
120829301572SMark Peek 		_cmap[lp] = _cmap_mbyte[lp];
120929301572SMark Peek 		_mbmap[lp] = _mbmap_utf8[lp];
121029301572SMark Peek 		break;
1211c80476e4SDavid E. O'Brien 	    default:
1212c80476e4SDavid E. O'Brien 		xprintf(CGETS(18, 3,
1213c80476e4SDavid E. O'Brien 		    "Warning: unknown multibyte code %d; multibyte disabled\n"),
1214c80476e4SDavid E. O'Brien 		    iskcode);
1215c80476e4SDavid E. O'Brien 		_cmap[lp] = _cmap_c[lp];
1216c80476e4SDavid E. O'Brien 		_mbmap[lp] = 0;	/* Default map all 0 */
1217c80476e4SDavid E. O'Brien 		_enable_mbdisp = 0;
1218c80476e4SDavid E. O'Brien 		break;
1219c80476e4SDavid E. O'Brien 	    }
1220c80476e4SDavid E. O'Brien 	}
1221c80476e4SDavid E. O'Brien 	if (iskcode == 0) {
1222c80476e4SDavid E. O'Brien 	    /* check original table */
1223c80476e4SDavid E. O'Brien 	    if (Strlen(dstr1) != 256) {
1224c80476e4SDavid E. O'Brien 		xprintf(CGETS(18, 4,
1225c80476e4SDavid E. O'Brien        "Warning: Invalid multibyte table length (%d); multibyte disabled\n"),
1226c80476e4SDavid E. O'Brien 		    Strlen(dstr1));
1227c80476e4SDavid E. O'Brien 		_enable_mbdisp = 0;
1228c80476e4SDavid E. O'Brien 	    }
1229c80476e4SDavid E. O'Brien 	    for (lp = 0; lp < 256 && _enable_mbdisp == 1; lp++) {
1230c80476e4SDavid E. O'Brien 		if (!((dstr1[lp] - '0') >= 0 && (dstr1[lp] - '0') <= 3)) {
1231c80476e4SDavid E. O'Brien 		    xprintf(CGETS(18, 4,
1232c80476e4SDavid E. O'Brien 	   "Warning: bad multibyte code at offset +%d; multibyte diabled\n"),
1233c80476e4SDavid E. O'Brien 			lp);
1234c80476e4SDavid E. O'Brien 		    _enable_mbdisp = 0;
1235c80476e4SDavid E. O'Brien 		    break;
1236c80476e4SDavid E. O'Brien 		}
1237c80476e4SDavid E. O'Brien 	    }
1238c80476e4SDavid E. O'Brien 	    /* set original table */
1239c80476e4SDavid E. O'Brien 	    for (lp = 0; lp < 256; lp++) {
1240c80476e4SDavid E. O'Brien 		if (_enable_mbdisp == 1) {
1241c80476e4SDavid E. O'Brien 		    _cmap[lp] = _cmap_mbyte[lp];
1242c80476e4SDavid E. O'Brien 		    _mbmap[lp] = (unsigned short) ((dstr1[lp] - '0') & 0x0f);
1243c80476e4SDavid E. O'Brien 		}
1244c80476e4SDavid E. O'Brien 		else {
1245c80476e4SDavid E. O'Brien 		    _cmap[lp] = _cmap_c[lp];
1246c80476e4SDavid E. O'Brien 		    _mbmap[lp] = 0;	/* Default map all 0 */
1247c80476e4SDavid E. O'Brien 		}
1248c80476e4SDavid E. O'Brien 	    }
1249c80476e4SDavid E. O'Brien 	}
1250c80476e4SDavid E. O'Brien     }
1251c80476e4SDavid E. O'Brien     else {
1252c80476e4SDavid E. O'Brien 	for (lp = 0; lp < 256; lp++) {
1253c80476e4SDavid E. O'Brien 	    _cmap[lp] = _cmap_c[lp];
1254c80476e4SDavid E. O'Brien 	    _mbmap[lp] = 0;	/* Default map all 0 */
1255c80476e4SDavid E. O'Brien 	}
1256c80476e4SDavid E. O'Brien 	_enable_mbdisp = 0;
1257c80476e4SDavid E. O'Brien 	dspmbyte_ls = 0;
1258c80476e4SDavid E. O'Brien     }
1259c80476e4SDavid E. O'Brien #ifdef MBYTEDEBUG	/* Sorry, use for beta testing */
1260c80476e4SDavid E. O'Brien     {
1261c80476e4SDavid E. O'Brien 	Char mbmapstr[300];
126245e5710bSMark Peek 	for (lp = 0; lp < 256; lp++)
1263c80476e4SDavid E. O'Brien 	    mbmapstr[lp] = _mbmap[lp] + '0';
126445e5710bSMark Peek 	mbmapstr[lp] = 0;
126545e5710bSMark Peek 	setcopy(STRmbytemap, mbmapstr, VAR_READWRITE);
1266c80476e4SDavid E. O'Brien     }
1267c80476e4SDavid E. O'Brien #endif /* MBYTEMAP */
1268c80476e4SDavid E. O'Brien }
1269c80476e4SDavid E. O'Brien 
1270c80476e4SDavid E. O'Brien /* dspkanji/dspmbyte autosetting */
1271c80476e4SDavid E. O'Brien /* PATCH IDEA FROM Issei.Suzuki VERY THANKS */
1272c80476e4SDavid E. O'Brien void
127345e5710bSMark Peek autoset_dspmbyte(const Char *pcp)
1274c80476e4SDavid E. O'Brien {
1275c80476e4SDavid E. O'Brien     int i;
127645e5710bSMark Peek     static const struct dspm_autoset_Table {
1277c80476e4SDavid E. O'Brien 	Char *n;
1278c80476e4SDavid E. O'Brien 	Char *v;
1279c80476e4SDavid E. O'Brien     } dspmt[] = {
128023338178SMark Peek 	{ STRLANGEUCJP, STReuc },
128123338178SMark Peek 	{ STRLANGEUCKR, STReuc },
128223338178SMark Peek 	{ STRLANGEUCZH, STReuc },
128323338178SMark Peek 	{ STRLANGEUCJPB, STReuc },
128423338178SMark Peek 	{ STRLANGEUCKRB, STReuc },
128523338178SMark Peek 	{ STRLANGEUCZHB, STReuc },
12869ccc37e3SMark Peek #ifdef __linux__
128723338178SMark Peek 	{ STRLANGEUCJPC, STReuc },
1288b2d5d167SMark Peek #endif
128923338178SMark Peek 	{ STRLANGSJIS, STRsjis },
129023338178SMark Peek 	{ STRLANGSJISB, STRsjis },
129123338178SMark Peek 	{ STRLANGBIG5, STRbig5 },
129223338178SMark Peek 	{ STRstarutfstar8, STRutf8 },
1293c80476e4SDavid E. O'Brien 	{ NULL, NULL }
1294c80476e4SDavid E. O'Brien     };
129545e5710bSMark Peek #if defined(HAVE_NL_LANGINFO) && defined(CODESET)
129645e5710bSMark Peek     static const struct dspm_autoset_Table dspmc[] = {
129723338178SMark Peek 	{ STRstarutfstar8, STRutf8 },
129823338178SMark Peek 	{ STReuc, STReuc },
129923338178SMark Peek 	{ STRGB2312, STReuc },
130023338178SMark Peek 	{ STRLANGBIG5, STRbig5 },
130123338178SMark Peek 	{ NULL, NULL }
130223338178SMark Peek     };
130323338178SMark Peek     Char *codeset;
130423338178SMark Peek 
130523338178SMark Peek     codeset = str2short(nl_langinfo(CODESET));
130623338178SMark Peek     if (*codeset != '\0') {
130723338178SMark Peek 	for (i = 0; dspmc[i].n; i++) {
130845e5710bSMark Peek 	    const Char *estr;
130923338178SMark Peek 	    if (dspmc[i].n[0] && t_pmatch(pcp, dspmc[i].n, &estr, 0) > 0) {
131045e5710bSMark Peek 		setcopy(CHECK_MBYTEVAR, dspmc[i].v, VAR_READWRITE);
131123338178SMark Peek 		update_dspmbyte_vars();
131223338178SMark Peek 		return;
131323338178SMark Peek 	    }
131423338178SMark Peek 	}
131523338178SMark Peek     }
131623338178SMark Peek #endif
1317c80476e4SDavid E. O'Brien 
1318c80476e4SDavid E. O'Brien     if (*pcp == '\0')
1319c80476e4SDavid E. O'Brien 	return;
1320c80476e4SDavid E. O'Brien 
1321c80476e4SDavid E. O'Brien     for (i = 0; dspmt[i].n; i++) {
132245e5710bSMark Peek 	const Char *estr;
132323338178SMark Peek 	if (dspmt[i].n[0] && t_pmatch(pcp, dspmt[i].n, &estr, 0) > 0) {
132445e5710bSMark Peek 	    setcopy(CHECK_MBYTEVAR, dspmt[i].v, VAR_READWRITE);
1325c80476e4SDavid E. O'Brien 	    update_dspmbyte_vars();
1326c80476e4SDavid E. O'Brien 	    break;
1327c80476e4SDavid E. O'Brien 	}
1328c80476e4SDavid E. O'Brien     }
1329c80476e4SDavid E. O'Brien }
13309ccc37e3SMark Peek # elif defined(AUTOSET_KANJI)
13319ccc37e3SMark Peek void
13329ccc37e3SMark Peek autoset_kanji(void)
13339ccc37e3SMark Peek {
13349ccc37e3SMark Peek     char *codeset = nl_langinfo(CODESET);
13359ccc37e3SMark Peek 
13369ccc37e3SMark Peek     if (*codeset == '\0') {
13379ccc37e3SMark Peek 	if (adrof(STRnokanji) == NULL)
13389ccc37e3SMark Peek 	    setNS(STRnokanji);
13399ccc37e3SMark Peek 	return;
13409ccc37e3SMark Peek     }
13419ccc37e3SMark Peek 
13429ccc37e3SMark Peek     if (strcasestr(codeset, "SHIFT_JIS") == (char*)0) {
13439ccc37e3SMark Peek 	if (adrof(STRnokanji) == NULL)
13449ccc37e3SMark Peek 	    setNS(STRnokanji);
13459ccc37e3SMark Peek 	return;
13469ccc37e3SMark Peek     }
13479ccc37e3SMark Peek 
13489ccc37e3SMark Peek     if (adrof(STRnokanji) != NULL)
13499ccc37e3SMark Peek 	unsetv(STRnokanji);
13509ccc37e3SMark Peek }
13519ccc37e3SMark Peek #endif
1352c80476e4SDavid E. O'Brien #endif
1353*19d2e3deSDmitry Chagin 
1354*19d2e3deSDmitry Chagin void
1355*19d2e3deSDmitry Chagin update_wordchars(void)
1356*19d2e3deSDmitry Chagin {
1357*19d2e3deSDmitry Chagin     if ((word_chars == STR_WORD_CHARS) || (word_chars == STR_WORD_CHARS_VI)) {
1358*19d2e3deSDmitry Chagin 	word_chars = (VImode ? STR_WORD_CHARS_VI : STR_WORD_CHARS);
1359*19d2e3deSDmitry Chagin     }
1360*19d2e3deSDmitry Chagin }
1361