xref: /freebsd/contrib/tcsh/sh.set.c (revision 23338178da74e9862b8abd49eef83ee891027a1e)
123338178SMark Peek /* $Header: /src/pub/tcsh/sh.set.c,v 3.61 2005/03/03 16:57:02 kim 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 
3523338178SMark Peek RCSID("$Id: sh.set.c,v 3.61 2005/03/03 16:57:02 kim 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 
47c80476e4SDavid E. O'Brien static	void		 update_vars	__P((Char *));
48c80476e4SDavid E. O'Brien static	Char		*getinx		__P((Char *, int *));
49c80476e4SDavid E. O'Brien static	void		 asx		__P((Char *, int, Char *));
50c80476e4SDavid E. O'Brien static	struct varent 	*getvx		__P((Char *, int));
51c80476e4SDavid E. O'Brien static	Char		*xset		__P((Char *, Char ***));
52c80476e4SDavid E. O'Brien static	Char		*operate	__P((int, Char *, Char *));
53c80476e4SDavid E. O'Brien static	void	 	 putn1		__P((int));
54c80476e4SDavid E. O'Brien static	struct varent	*madrof		__P((Char *, struct varent *));
55c80476e4SDavid E. O'Brien static	void		 unsetv1	__P((struct varent *));
56c80476e4SDavid E. O'Brien static	void		 exportpath	__P((Char **));
57c80476e4SDavid E. O'Brien static	void		 balance	__P((struct varent *, int, int));
58c80476e4SDavid E. O'Brien 
59c80476e4SDavid E. O'Brien /*
60c80476e4SDavid E. O'Brien  * C Shell
61c80476e4SDavid E. O'Brien  */
62c80476e4SDavid E. O'Brien 
63c80476e4SDavid E. O'Brien static void
64c80476e4SDavid E. O'Brien update_vars(vp)
65c80476e4SDavid E. O'Brien     Char *vp;
66c80476e4SDavid E. O'Brien {
67c80476e4SDavid E. O'Brien     if (eq(vp, STRpath)) {
68c80476e4SDavid E. O'Brien 	exportpath(adrof(STRpath)->vec);
69c80476e4SDavid E. O'Brien 	dohash(NULL, NULL);
70c80476e4SDavid E. O'Brien     }
71c80476e4SDavid E. O'Brien     else if (eq(vp, STRhistchars)) {
7223338178SMark Peek 	Char *pn = varval(vp);
73c80476e4SDavid E. O'Brien 
74c80476e4SDavid E. O'Brien 	HIST = *pn++;
75c80476e4SDavid E. O'Brien 	HISTSUB = *pn;
76c80476e4SDavid E. O'Brien     }
77c80476e4SDavid E. O'Brien     else if (eq(vp, STRpromptchars)) {
7823338178SMark Peek 	Char *pn = varval(vp);
79c80476e4SDavid E. O'Brien 
80c80476e4SDavid E. O'Brien 	PRCH = *pn++;
81c80476e4SDavid E. O'Brien 	PRCHROOT = *pn;
82c80476e4SDavid E. O'Brien     }
83c80476e4SDavid E. O'Brien     else if (eq(vp, STRhistlit)) {
84c80476e4SDavid E. O'Brien 	HistLit = 1;
85c80476e4SDavid E. O'Brien     }
86c80476e4SDavid E. O'Brien     else if (eq(vp, STRuser)) {
87c80476e4SDavid E. O'Brien 	tsetenv(STRKUSER, varval(vp));
88c80476e4SDavid E. O'Brien 	tsetenv(STRLOGNAME, varval(vp));
89c80476e4SDavid E. O'Brien     }
90c80476e4SDavid E. O'Brien     else if (eq(vp, STRgroup)) {
91c80476e4SDavid E. O'Brien 	tsetenv(STRKGROUP, varval(vp));
92c80476e4SDavid E. O'Brien     }
93c80476e4SDavid E. O'Brien     else if (eq(vp, STRwordchars)) {
94c80476e4SDavid E. O'Brien 	word_chars = varval(vp);
95c80476e4SDavid E. O'Brien     }
96c80476e4SDavid E. O'Brien     else if (eq(vp, STRloginsh)) {
97c80476e4SDavid E. O'Brien 	loginsh = 1;
98c80476e4SDavid E. O'Brien     }
99c80476e4SDavid E. O'Brien     else if (eq(vp, STRsymlinks)) {
10023338178SMark Peek 	Char *pn = varval(vp);
101c80476e4SDavid E. O'Brien 
102c80476e4SDavid E. O'Brien 	if (eq(pn, STRignore))
103c80476e4SDavid E. O'Brien 	    symlinks = SYM_IGNORE;
104c80476e4SDavid E. O'Brien 	else if (eq(pn, STRexpand))
105c80476e4SDavid E. O'Brien 	    symlinks = SYM_EXPAND;
106c80476e4SDavid E. O'Brien 	else if (eq(pn, STRchase))
107c80476e4SDavid E. O'Brien 	    symlinks = SYM_CHASE;
108c80476e4SDavid E. O'Brien 	else
109c80476e4SDavid E. O'Brien 	    symlinks = 0;
110c80476e4SDavid E. O'Brien     }
111c80476e4SDavid E. O'Brien     else if (eq(vp, STRterm)) {
112c80476e4SDavid E. O'Brien 	Char *cp = varval(vp);
113c80476e4SDavid E. O'Brien 	tsetenv(STRKTERM, cp);
114c80476e4SDavid E. O'Brien #ifdef DOESNT_WORK_RIGHT
115c80476e4SDavid E. O'Brien 	cp = getenv("TERMCAP");
116c80476e4SDavid E. O'Brien 	if (cp && (*cp != '/'))	/* if TERMCAP and not a path */
117c80476e4SDavid E. O'Brien 	    Unsetenv(STRTERMCAP);
118c80476e4SDavid E. O'Brien #endif /* DOESNT_WORK_RIGHT */
119c80476e4SDavid E. O'Brien 	GotTermCaps = 0;
120c80476e4SDavid E. O'Brien 	if (noediting && Strcmp(cp, STRnetwork) != 0 &&
121c80476e4SDavid E. O'Brien 	    Strcmp(cp, STRunknown) != 0 && Strcmp(cp, STRdumb) != 0) {
122c80476e4SDavid E. O'Brien 	    editing = 1;
123c80476e4SDavid E. O'Brien 	    noediting = 0;
124c80476e4SDavid E. O'Brien 	    set(STRedit, Strsave(STRNULL), VAR_READWRITE);
125c80476e4SDavid E. O'Brien 	}
126c80476e4SDavid E. O'Brien 	ed_Init();		/* reset the editor */
127c80476e4SDavid E. O'Brien     }
128c80476e4SDavid E. O'Brien     else if (eq(vp, STRhome)) {
129b2d5d167SMark Peek 	Char *cp;
130c80476e4SDavid E. O'Brien 
131c80476e4SDavid E. O'Brien 	cp = Strsave(varval(vp));	/* get the old value back */
132c80476e4SDavid E. O'Brien 
133c80476e4SDavid E. O'Brien 	/*
134c80476e4SDavid E. O'Brien 	 * convert to cononical pathname (possibly resolving symlinks)
135c80476e4SDavid E. O'Brien 	 */
136c80476e4SDavid E. O'Brien 	cp = dcanon(cp, cp);
137c80476e4SDavid E. O'Brien 
138c80476e4SDavid E. O'Brien 	set(vp, Strsave(cp), VAR_READWRITE);	/* have to save the new val */
139c80476e4SDavid E. O'Brien 
140c80476e4SDavid E. O'Brien 	/* and now mirror home with HOME */
141c80476e4SDavid E. O'Brien 	tsetenv(STRKHOME, cp);
142c80476e4SDavid E. O'Brien 	/* fix directory stack for new tilde home */
143c80476e4SDavid E. O'Brien 	dtilde();
144c80476e4SDavid E. O'Brien 	xfree((ptr_t) cp);
145c80476e4SDavid E. O'Brien     }
146c80476e4SDavid E. O'Brien     else if (eq(vp, STRedit)) {
147c80476e4SDavid E. O'Brien 	editing = 1;
148c80476e4SDavid E. O'Brien 	noediting = 0;
149c80476e4SDavid E. O'Brien 	/* PWP: add more stuff in here later */
150c80476e4SDavid E. O'Brien     }
151c80476e4SDavid E. O'Brien     else if (eq(vp, STRshlvl)) {
152c80476e4SDavid E. O'Brien 	tsetenv(STRKSHLVL, varval(vp));
153c80476e4SDavid E. O'Brien     }
154b2d5d167SMark Peek     else if (eq(vp, STRignoreeof)) {
155b2d5d167SMark Peek 	Char *cp;
156b2d5d167SMark Peek 	numeof = 0;
157b2d5d167SMark Peek     	for ((cp = varval(STRignoreeof)); cp && *cp; cp++) {
158b2d5d167SMark Peek 	    if (!Isdigit(*cp)) {
159b2d5d167SMark Peek 		numeof = 0;
160b2d5d167SMark Peek 		break;
161b2d5d167SMark Peek 	    }
162b2d5d167SMark Peek 	    numeof = numeof * 10 + *cp - '0';
163b2d5d167SMark Peek 	}
164b2d5d167SMark Peek 	if (numeof <= 0) numeof = 26;	/* Sanity check */
165b2d5d167SMark Peek     }
166c80476e4SDavid E. O'Brien     else if (eq(vp, STRbackslash_quote)) {
167c80476e4SDavid E. O'Brien 	bslash_quote = 1;
168c80476e4SDavid E. O'Brien     }
169c80476e4SDavid E. O'Brien     else if (eq(vp, STRdirstack)) {
170c80476e4SDavid E. O'Brien 	dsetstack();
171c80476e4SDavid E. O'Brien     }
172c80476e4SDavid E. O'Brien     else if (eq(vp, STRrecognize_only_executables)) {
173c80476e4SDavid E. O'Brien 	tw_cmd_free();
174c80476e4SDavid E. O'Brien     }
1756767bd61SMark Peek     else if (eq(vp, STRkillring)) {
1766767bd61SMark Peek 	SetKillRing(getn(varval(vp)));
1776767bd61SMark Peek     }
178c80476e4SDavid E. O'Brien #ifndef HAVENOUTMP
179c80476e4SDavid E. O'Brien     else if (eq(vp, STRwatch)) {
180c80476e4SDavid E. O'Brien 	resetwatch();
181c80476e4SDavid E. O'Brien     }
182c80476e4SDavid E. O'Brien #endif /* HAVENOUTMP */
183c80476e4SDavid E. O'Brien     else if (eq(vp, STRimplicitcd)) {
184c80476e4SDavid E. O'Brien 	implicit_cd = ((eq(varval(vp), STRverbose)) ? 2 : 1);
185c80476e4SDavid E. O'Brien     }
186c80476e4SDavid E. O'Brien #ifdef COLOR_LS_F
187c80476e4SDavid E. O'Brien     else if (eq(vp, STRcolor)) {
188c80476e4SDavid E. O'Brien 	set_color_context();
189c80476e4SDavid E. O'Brien     }
190c80476e4SDavid E. O'Brien #endif /* COLOR_LS_F */
191c80476e4SDavid E. O'Brien #if defined(KANJI) && defined(SHORT_STRINGS) && defined(DSPMBYTE)
192c80476e4SDavid E. O'Brien     else if(eq(vp, CHECK_MBYTEVAR) || eq(vp, STRnokanji)) {
193c80476e4SDavid E. O'Brien 	update_dspmbyte_vars();
194c80476e4SDavid E. O'Brien     }
195c80476e4SDavid E. O'Brien #endif
1963b6eaa7bSAndrey A. Chernov #ifdef NLS_CATALOGS
1973b6eaa7bSAndrey A. Chernov     else if (eq(vp, STRcatalog)) {
19823338178SMark Peek 	nlsclose();
1993b6eaa7bSAndrey A. Chernov 	nlsinit();
2003b6eaa7bSAndrey A. Chernov     }
20129301572SMark Peek #if defined(FILEC) && defined(TIOCSTI)
20229301572SMark Peek     else if (eq(vp, STRfilec))
20329301572SMark Peek 	filec = 1;
20429301572SMark Peek #endif
2053b6eaa7bSAndrey A. Chernov #endif /* NLS_CATALOGS */
206c80476e4SDavid E. O'Brien }
207c80476e4SDavid E. O'Brien 
208c80476e4SDavid E. O'Brien 
209c80476e4SDavid E. O'Brien /*ARGSUSED*/
210c80476e4SDavid E. O'Brien void
211c80476e4SDavid E. O'Brien doset(v, c)
21223338178SMark Peek     Char **v;
213c80476e4SDavid E. O'Brien     struct command *c;
214c80476e4SDavid E. O'Brien {
21523338178SMark Peek     Char *p;
216c80476e4SDavid E. O'Brien     Char   *vp, op;
217c80476e4SDavid E. O'Brien     Char  **vecp;
21823338178SMark Peek     int    hadsub;
219c80476e4SDavid E. O'Brien     int     subscr;
220c80476e4SDavid E. O'Brien     int	    flags = VAR_READWRITE;
22123338178SMark Peek     int    first_match = 0;
22223338178SMark Peek     int    last_match = 0;
22323338178SMark Peek     int    changed = 0;
224c80476e4SDavid E. O'Brien 
225c80476e4SDavid E. O'Brien     USE(c);
226c80476e4SDavid E. O'Brien     v++;
227c80476e4SDavid E. O'Brien     do {
228c80476e4SDavid E. O'Brien 	changed = 0;
229c80476e4SDavid E. O'Brien 	/*
230c80476e4SDavid E. O'Brien 	 * Readonly addition From: Tim P. Starrin <noid@cyborg.larc.nasa.gov>
231c80476e4SDavid E. O'Brien 	 */
232c80476e4SDavid E. O'Brien 	if (*v && eq(*v, STRmr)) {
233c80476e4SDavid E. O'Brien 	    flags = VAR_READONLY;
234c80476e4SDavid E. O'Brien 	    v++;
235c80476e4SDavid E. O'Brien 	    changed = 1;
236c80476e4SDavid E. O'Brien 	}
237c80476e4SDavid E. O'Brien 	if (*v && eq(*v, STRmf) && !last_match) {
238c80476e4SDavid E. O'Brien 	    first_match = 1;
239c80476e4SDavid E. O'Brien 	    v++;
240c80476e4SDavid E. O'Brien 	    changed = 1;
241c80476e4SDavid E. O'Brien 	}
242c80476e4SDavid E. O'Brien 	if (*v && eq(*v, STRml) && !first_match) {
243c80476e4SDavid E. O'Brien 	    last_match = 1;
244c80476e4SDavid E. O'Brien 	    v++;
245c80476e4SDavid E. O'Brien 	    changed = 1;
246c80476e4SDavid E. O'Brien 	}
247c80476e4SDavid E. O'Brien     } while(changed);
248c80476e4SDavid E. O'Brien     p = *v++;
249c80476e4SDavid E. O'Brien     if (p == 0) {
250c80476e4SDavid E. O'Brien 	plist(&shvhed, flags);
251c80476e4SDavid E. O'Brien 	return;
252c80476e4SDavid E. O'Brien     }
253c80476e4SDavid E. O'Brien     do {
254c80476e4SDavid E. O'Brien 	hadsub = 0;
255c80476e4SDavid E. O'Brien 	vp = p;
256c80476e4SDavid E. O'Brien 	if (letter(*p))
257c80476e4SDavid E. O'Brien 	    for (; alnum(*p); p++)
258c80476e4SDavid E. O'Brien 		continue;
259c80476e4SDavid E. O'Brien 	if (vp == p || !letter(*vp))
260c80476e4SDavid E. O'Brien 	    stderror(ERR_NAME | ERR_VARBEGIN);
261c80476e4SDavid E. O'Brien 	if ((p - vp) > MAXVARLEN) {
262c80476e4SDavid E. O'Brien 	    stderror(ERR_NAME | ERR_VARTOOLONG);
263c80476e4SDavid E. O'Brien 	    return;
264c80476e4SDavid E. O'Brien 	}
265c80476e4SDavid E. O'Brien 	if (*p == '[') {
266c80476e4SDavid E. O'Brien 	    hadsub++;
267c80476e4SDavid E. O'Brien 	    p = getinx(p, &subscr);
268c80476e4SDavid E. O'Brien 	}
269c80476e4SDavid E. O'Brien 	if ((op = *p) != 0) {
270c80476e4SDavid E. O'Brien 	    *p++ = 0;
271c80476e4SDavid E. O'Brien 	    if (*p == 0 && *v && **v == '(')
272c80476e4SDavid E. O'Brien 		p = *v++;
273c80476e4SDavid E. O'Brien 	}
274c80476e4SDavid E. O'Brien 	else if (*v && eq(*v, STRequal)) {
275c80476e4SDavid E. O'Brien 	    op = '=', v++;
276c80476e4SDavid E. O'Brien 	    if (*v)
277c80476e4SDavid E. O'Brien 		p = *v++;
278c80476e4SDavid E. O'Brien 	}
279c80476e4SDavid E. O'Brien 	if (op && op != '=')
280c80476e4SDavid E. O'Brien 	    stderror(ERR_NAME | ERR_SYNTAX);
281c80476e4SDavid E. O'Brien 	if (eq(p, STRLparen)) {
28223338178SMark Peek 	    Char **e = v;
283c80476e4SDavid E. O'Brien 
284c80476e4SDavid E. O'Brien 	    if (hadsub)
285c80476e4SDavid E. O'Brien 		stderror(ERR_NAME | ERR_SYNTAX);
286c80476e4SDavid E. O'Brien 	    for (;;) {
287c80476e4SDavid E. O'Brien 		if (!*e)
288c80476e4SDavid E. O'Brien 		    stderror(ERR_NAME | ERR_MISSING, ')');
289c80476e4SDavid E. O'Brien 		if (**e == ')')
290c80476e4SDavid E. O'Brien 		    break;
291c80476e4SDavid E. O'Brien 		e++;
292c80476e4SDavid E. O'Brien 	    }
293c80476e4SDavid E. O'Brien 	    p = *e;
294c80476e4SDavid E. O'Brien 	    *e = 0;
295c80476e4SDavid E. O'Brien 	    vecp = saveblk(v);
296c80476e4SDavid E. O'Brien 	    if (first_match)
297c80476e4SDavid E. O'Brien 	       flags |= VAR_FIRST;
298c80476e4SDavid E. O'Brien 	    else if (last_match)
299c80476e4SDavid E. O'Brien 	       flags |= VAR_LAST;
300c80476e4SDavid E. O'Brien 
301c80476e4SDavid E. O'Brien 	    set1(vp, vecp, &shvhed, flags);
302c80476e4SDavid E. O'Brien 	    *e = p;
303c80476e4SDavid E. O'Brien 	    v = e + 1;
304c80476e4SDavid E. O'Brien 	}
305c80476e4SDavid E. O'Brien 	else if (hadsub)
306c80476e4SDavid E. O'Brien 	    asx(vp, subscr, Strsave(p));
307c80476e4SDavid E. O'Brien 	else
308c80476e4SDavid E. O'Brien 	    set(vp, Strsave(p), flags);
309c80476e4SDavid E. O'Brien 	update_vars(vp);
310c80476e4SDavid E. O'Brien     } while ((p = *v++) != NULL);
311c80476e4SDavid E. O'Brien }
312c80476e4SDavid E. O'Brien 
313c80476e4SDavid E. O'Brien static Char *
314c80476e4SDavid E. O'Brien getinx(cp, ip)
31523338178SMark Peek     Char *cp;
31623338178SMark Peek     int *ip;
317c80476e4SDavid E. O'Brien {
318c80476e4SDavid E. O'Brien     *ip = 0;
319c80476e4SDavid E. O'Brien     *cp++ = 0;
320c80476e4SDavid E. O'Brien     while (*cp && Isdigit(*cp))
321c80476e4SDavid E. O'Brien 	*ip = *ip * 10 + *cp++ - '0';
322c80476e4SDavid E. O'Brien     if (*cp++ != ']')
323c80476e4SDavid E. O'Brien 	stderror(ERR_NAME | ERR_SUBSCRIPT);
324c80476e4SDavid E. O'Brien     return (cp);
325c80476e4SDavid E. O'Brien }
326c80476e4SDavid E. O'Brien 
327c80476e4SDavid E. O'Brien static void
328c80476e4SDavid E. O'Brien asx(vp, subscr, p)
329c80476e4SDavid E. O'Brien     Char   *vp;
330c80476e4SDavid E. O'Brien     int     subscr;
331c80476e4SDavid E. O'Brien     Char   *p;
332c80476e4SDavid E. O'Brien {
33323338178SMark Peek     struct varent *v = getvx(vp, subscr);
334c80476e4SDavid E. O'Brien 
335c80476e4SDavid E. O'Brien     if (v->v_flags & VAR_READONLY)
336c80476e4SDavid E. O'Brien 	stderror(ERR_READONLY|ERR_NAME, v->v_name);
337c80476e4SDavid E. O'Brien     xfree((ptr_t) v->vec[subscr - 1]);
338c80476e4SDavid E. O'Brien     v->vec[subscr - 1] = globone(p, G_APPEND);
339c80476e4SDavid E. O'Brien }
340c80476e4SDavid E. O'Brien 
341c80476e4SDavid E. O'Brien static struct varent *
342c80476e4SDavid E. O'Brien getvx(vp, subscr)
343c80476e4SDavid E. O'Brien     Char   *vp;
344c80476e4SDavid E. O'Brien     int     subscr;
345c80476e4SDavid E. O'Brien {
34623338178SMark Peek     struct varent *v = adrof(vp);
347c80476e4SDavid E. O'Brien 
348c80476e4SDavid E. O'Brien     if (v == 0)
349c80476e4SDavid E. O'Brien 	udvar(vp);
350c80476e4SDavid E. O'Brien     if (subscr < 1 || subscr > blklen(v->vec))
351c80476e4SDavid E. O'Brien 	stderror(ERR_NAME | ERR_RANGE);
352c80476e4SDavid E. O'Brien     return (v);
353c80476e4SDavid E. O'Brien }
354c80476e4SDavid E. O'Brien 
355c80476e4SDavid E. O'Brien /*ARGSUSED*/
356c80476e4SDavid E. O'Brien void
357c80476e4SDavid E. O'Brien dolet(v, dummy)
358c80476e4SDavid E. O'Brien     Char  **v;
359c80476e4SDavid E. O'Brien     struct command *dummy;
360c80476e4SDavid E. O'Brien {
36123338178SMark Peek     Char *p;
362c80476e4SDavid E. O'Brien     Char   *vp, c, op;
36323338178SMark Peek     int    hadsub;
364c80476e4SDavid E. O'Brien     int     subscr;
365c80476e4SDavid E. O'Brien 
366c80476e4SDavid E. O'Brien     USE(dummy);
367c80476e4SDavid E. O'Brien     v++;
368c80476e4SDavid E. O'Brien     p = *v++;
369c80476e4SDavid E. O'Brien     if (p == 0) {
370c80476e4SDavid E. O'Brien 	prvars();
371c80476e4SDavid E. O'Brien 	return;
372c80476e4SDavid E. O'Brien     }
373c80476e4SDavid E. O'Brien     do {
374c80476e4SDavid E. O'Brien 	hadsub = 0;
375c80476e4SDavid E. O'Brien 	vp = p;
376c80476e4SDavid E. O'Brien 	if (letter(*p))
377c80476e4SDavid E. O'Brien 	    for (; alnum(*p); p++)
378c80476e4SDavid E. O'Brien 		continue;
379c80476e4SDavid E. O'Brien 	if (vp == p || !letter(*vp))
380c80476e4SDavid E. O'Brien 	    stderror(ERR_NAME | ERR_VARBEGIN);
381c80476e4SDavid E. O'Brien 	if ((p - vp) > MAXVARLEN)
382c80476e4SDavid E. O'Brien 	    stderror(ERR_NAME | ERR_VARTOOLONG);
383c80476e4SDavid E. O'Brien 	if (*p == '[') {
384c80476e4SDavid E. O'Brien 	    hadsub++;
385c80476e4SDavid E. O'Brien 	    p = getinx(p, &subscr);
386c80476e4SDavid E. O'Brien 	}
387c80476e4SDavid E. O'Brien 	if (*p == 0 && *v)
388c80476e4SDavid E. O'Brien 	    p = *v++;
389c80476e4SDavid E. O'Brien 	if ((op = *p) != 0)
390c80476e4SDavid E. O'Brien 	    *p++ = 0;
391c80476e4SDavid E. O'Brien 	else
392c80476e4SDavid E. O'Brien 	    stderror(ERR_NAME | ERR_ASSIGN);
393c80476e4SDavid E. O'Brien 
394c80476e4SDavid E. O'Brien 	/*
395c80476e4SDavid E. O'Brien 	 * if there is no expression after the '=' then print a "Syntax Error"
396c80476e4SDavid E. O'Brien 	 * message - strike
397c80476e4SDavid E. O'Brien 	 */
398c80476e4SDavid E. O'Brien 	if (*p == '\0' && *v == NULL)
399c80476e4SDavid E. O'Brien 	    stderror(ERR_NAME | ERR_ASSIGN);
400c80476e4SDavid E. O'Brien 
401c80476e4SDavid E. O'Brien 	vp = Strsave(vp);
402c80476e4SDavid E. O'Brien 	if (op == '=') {
403c80476e4SDavid E. O'Brien 	    c = '=';
404c80476e4SDavid E. O'Brien 	    p = xset(p, &v);
405c80476e4SDavid E. O'Brien 	}
406c80476e4SDavid E. O'Brien 	else {
407c80476e4SDavid E. O'Brien 	    c = *p++;
408c80476e4SDavid E. O'Brien 	    if (any("+-", c)) {
409c80476e4SDavid E. O'Brien 		if (c != op || *p)
410c80476e4SDavid E. O'Brien 		    stderror(ERR_NAME | ERR_UNKNOWNOP);
411c80476e4SDavid E. O'Brien 		p = Strsave(STR1);
412c80476e4SDavid E. O'Brien 	    }
413c80476e4SDavid E. O'Brien 	    else {
414c80476e4SDavid E. O'Brien 		if (any("<>", op)) {
415c80476e4SDavid E. O'Brien 		    if (c != op)
416c80476e4SDavid E. O'Brien 			stderror(ERR_NAME | ERR_UNKNOWNOP);
417c80476e4SDavid E. O'Brien 		    c = *p++;
418c80476e4SDavid E. O'Brien 		    stderror(ERR_NAME | ERR_SYNTAX);
419c80476e4SDavid E. O'Brien 		}
420c80476e4SDavid E. O'Brien 		if (c != '=')
421c80476e4SDavid E. O'Brien 		    stderror(ERR_NAME | ERR_UNKNOWNOP);
422c80476e4SDavid E. O'Brien 		p = xset(p, &v);
423c80476e4SDavid E. O'Brien 	    }
424c80476e4SDavid E. O'Brien 	}
425c80476e4SDavid E. O'Brien 	if (op == '=') {
426c80476e4SDavid E. O'Brien 	    if (hadsub)
427c80476e4SDavid E. O'Brien 		asx(vp, subscr, p);
428c80476e4SDavid E. O'Brien 	    else
429c80476e4SDavid E. O'Brien 		set(vp, p, VAR_READWRITE);
430c80476e4SDavid E. O'Brien 	}
431c80476e4SDavid E. O'Brien 	else if (hadsub) {
432c80476e4SDavid E. O'Brien 	    struct varent *gv = getvx(vp, subscr);
433c80476e4SDavid E. O'Brien 
434c80476e4SDavid E. O'Brien 	    asx(vp, subscr, operate(op, gv->vec[subscr - 1], p));
435c80476e4SDavid E. O'Brien 	}
436c80476e4SDavid E. O'Brien 	else
437c80476e4SDavid E. O'Brien 	    set(vp, operate(op, varval(vp), p), VAR_READWRITE);
438c80476e4SDavid E. O'Brien 	update_vars(vp);
439c80476e4SDavid E. O'Brien 	xfree((ptr_t) vp);
440c80476e4SDavid E. O'Brien 	if (c != '=')
441c80476e4SDavid E. O'Brien 	    xfree((ptr_t) p);
442c80476e4SDavid E. O'Brien     } while ((p = *v++) != NULL);
443c80476e4SDavid E. O'Brien }
444c80476e4SDavid E. O'Brien 
445c80476e4SDavid E. O'Brien static Char *
446c80476e4SDavid E. O'Brien xset(cp, vp)
447c80476e4SDavid E. O'Brien     Char   *cp, ***vp;
448c80476e4SDavid E. O'Brien {
44923338178SMark Peek     Char *dp;
450c80476e4SDavid E. O'Brien 
451c80476e4SDavid E. O'Brien     if (*cp) {
452c80476e4SDavid E. O'Brien 	dp = Strsave(cp);
453c80476e4SDavid E. O'Brien 	--(*vp);
454c80476e4SDavid E. O'Brien 	xfree((ptr_t) ** vp);
455c80476e4SDavid E. O'Brien 	**vp = dp;
456c80476e4SDavid E. O'Brien     }
457c80476e4SDavid E. O'Brien     return (putn(expr(vp)));
458c80476e4SDavid E. O'Brien }
459c80476e4SDavid E. O'Brien 
460c80476e4SDavid E. O'Brien static Char *
461c80476e4SDavid E. O'Brien operate(op, vp, p)
462c80476e4SDavid E. O'Brien     int     op;
463c80476e4SDavid E. O'Brien     Char    *vp, *p;
464c80476e4SDavid E. O'Brien {
465c80476e4SDavid E. O'Brien     Char    opr[2];
466c80476e4SDavid E. O'Brien     Char   *vec[5];
46723338178SMark Peek     Char **v = vec;
468c80476e4SDavid E. O'Brien     Char  **vecp = v;
46923338178SMark Peek     int i;
470c80476e4SDavid E. O'Brien 
471c80476e4SDavid E. O'Brien     if (op != '=') {
472c80476e4SDavid E. O'Brien 	if (*vp)
473c80476e4SDavid E. O'Brien 	    *v++ = vp;
474c80476e4SDavid E. O'Brien 	opr[0] = (Char) op;
475c80476e4SDavid E. O'Brien 	opr[1] = 0;
476c80476e4SDavid E. O'Brien 	*v++ = opr;
477c80476e4SDavid E. O'Brien 	if (op == '<' || op == '>')
478c80476e4SDavid E. O'Brien 	    *v++ = opr;
479c80476e4SDavid E. O'Brien     }
480c80476e4SDavid E. O'Brien     *v++ = p;
481c80476e4SDavid E. O'Brien     *v++ = 0;
482c80476e4SDavid E. O'Brien     i = expr(&vecp);
483c80476e4SDavid E. O'Brien     if (*vecp)
484c80476e4SDavid E. O'Brien 	stderror(ERR_NAME | ERR_EXPRESSION);
485c80476e4SDavid E. O'Brien     return (putn(i));
486c80476e4SDavid E. O'Brien }
487c80476e4SDavid E. O'Brien 
488c80476e4SDavid E. O'Brien static Char *putp, nbuf[50];
489c80476e4SDavid E. O'Brien 
490c80476e4SDavid E. O'Brien Char   *
491c80476e4SDavid E. O'Brien putn(n)
49223338178SMark Peek     int n;
493c80476e4SDavid E. O'Brien {
494c80476e4SDavid E. O'Brien     int     num;
495c80476e4SDavid E. O'Brien 
496c80476e4SDavid E. O'Brien     putp = nbuf;
497c80476e4SDavid E. O'Brien     if (n < 0) {
498c80476e4SDavid E. O'Brien 	n = -n;
499c80476e4SDavid E. O'Brien 	*putp++ = '-';
500c80476e4SDavid E. O'Brien     }
501c80476e4SDavid E. O'Brien     num = 2;			/* confuse lint */
502c80476e4SDavid E. O'Brien     if (sizeof(int) == num && ((unsigned int) n) == 0x8000) {
503c80476e4SDavid E. O'Brien 	*putp++ = '3';
504c80476e4SDavid E. O'Brien 	n = 2768;
505c80476e4SDavid E. O'Brien #ifdef pdp11
506c80476e4SDavid E. O'Brien     }
507c80476e4SDavid E. O'Brien #else /* !pdp11 */
508c80476e4SDavid E. O'Brien     }
509c80476e4SDavid E. O'Brien     else {
510c80476e4SDavid E. O'Brien 	num = 4;		/* confuse lint */
511c80476e4SDavid E. O'Brien 	if (sizeof(int) == num && ((unsigned int) n) == 0x80000000) {
512c80476e4SDavid E. O'Brien 	    *putp++ = '2';
513c80476e4SDavid E. O'Brien 	    n = 147483648;
514c80476e4SDavid E. O'Brien 	}
515c80476e4SDavid E. O'Brien     }
516c80476e4SDavid E. O'Brien #endif /* pdp11 */
517c80476e4SDavid E. O'Brien     putn1(n);
518c80476e4SDavid E. O'Brien     *putp = 0;
519c80476e4SDavid E. O'Brien     return (Strsave(nbuf));
520c80476e4SDavid E. O'Brien }
521c80476e4SDavid E. O'Brien 
522c80476e4SDavid E. O'Brien static void
523c80476e4SDavid E. O'Brien putn1(n)
52423338178SMark Peek     int n;
525c80476e4SDavid E. O'Brien {
526c80476e4SDavid E. O'Brien     if (n > 9)
527c80476e4SDavid E. O'Brien 	putn1(n / 10);
528c80476e4SDavid E. O'Brien     *putp++ = n % 10 + '0';
529c80476e4SDavid E. O'Brien }
530c80476e4SDavid E. O'Brien 
531c80476e4SDavid E. O'Brien int
532c80476e4SDavid E. O'Brien getn(cp)
53323338178SMark Peek     Char *cp;
534c80476e4SDavid E. O'Brien {
53523338178SMark Peek     int n;
536c80476e4SDavid E. O'Brien     int     sign;
537c80476e4SDavid E. O'Brien 
538c80476e4SDavid E. O'Brien     if (!cp)			/* PWP: extra error checking */
539c80476e4SDavid E. O'Brien 	stderror(ERR_NAME | ERR_BADNUM);
540c80476e4SDavid E. O'Brien 
541c80476e4SDavid E. O'Brien     sign = 0;
542c80476e4SDavid E. O'Brien     if (cp[0] == '+' && cp[1])
543c80476e4SDavid E. O'Brien 	cp++;
544c80476e4SDavid E. O'Brien     if (*cp == '-') {
545c80476e4SDavid E. O'Brien 	sign++;
546c80476e4SDavid E. O'Brien 	cp++;
547c80476e4SDavid E. O'Brien 	if (!Isdigit(*cp))
548c80476e4SDavid E. O'Brien 	    stderror(ERR_NAME | ERR_BADNUM);
549c80476e4SDavid E. O'Brien     }
550c80476e4SDavid E. O'Brien     n = 0;
551c80476e4SDavid E. O'Brien     while (Isdigit(*cp))
552c80476e4SDavid E. O'Brien 	n = n * 10 + *cp++ - '0';
553c80476e4SDavid E. O'Brien     if (*cp)
554c80476e4SDavid E. O'Brien 	stderror(ERR_NAME | ERR_BADNUM);
555c80476e4SDavid E. O'Brien     return (sign ? -n : n);
556c80476e4SDavid E. O'Brien }
557c80476e4SDavid E. O'Brien 
558c80476e4SDavid E. O'Brien Char   *
559c80476e4SDavid E. O'Brien value1(var, head)
560c80476e4SDavid E. O'Brien     Char   *var;
561c80476e4SDavid E. O'Brien     struct varent *head;
562c80476e4SDavid E. O'Brien {
56323338178SMark Peek     struct varent *vp;
564c80476e4SDavid E. O'Brien 
565c80476e4SDavid E. O'Brien     if (!var || !head)		/* PWP: extra error checking */
566c80476e4SDavid E. O'Brien 	return (STRNULL);
567c80476e4SDavid E. O'Brien 
568c80476e4SDavid E. O'Brien     vp = adrof1(var, head);
56929301572SMark Peek     return ((vp == NULL || vp->vec == NULL || vp->vec[0] == NULL) ?
57029301572SMark Peek 	STRNULL : vp->vec[0]);
571c80476e4SDavid E. O'Brien }
572c80476e4SDavid E. O'Brien 
573c80476e4SDavid E. O'Brien static struct varent *
574c80476e4SDavid E. O'Brien madrof(pat, vp)
575c80476e4SDavid E. O'Brien     Char   *pat;
57623338178SMark Peek     struct varent *vp;
577c80476e4SDavid E. O'Brien {
57823338178SMark Peek     struct varent *vp1;
579c80476e4SDavid E. O'Brien 
580c80476e4SDavid E. O'Brien     for (vp = vp->v_left; vp; vp = vp->v_right) {
581c80476e4SDavid E. O'Brien 	if (vp->v_left && (vp1 = madrof(pat, vp)) != NULL)
582c80476e4SDavid E. O'Brien 	    return vp1;
583c80476e4SDavid E. O'Brien 	if (Gmatch(vp->v_name, pat))
584c80476e4SDavid E. O'Brien 	    return vp;
585c80476e4SDavid E. O'Brien     }
586c80476e4SDavid E. O'Brien     return vp;
587c80476e4SDavid E. O'Brien }
588c80476e4SDavid E. O'Brien 
589c80476e4SDavid E. O'Brien struct varent *
590c80476e4SDavid E. O'Brien adrof1(name, v)
59123338178SMark Peek     Char *name;
59223338178SMark Peek     struct varent *v;
593c80476e4SDavid E. O'Brien {
594c80476e4SDavid E. O'Brien     int cmp;
595c80476e4SDavid E. O'Brien 
596c80476e4SDavid E. O'Brien     v = v->v_left;
597c80476e4SDavid E. O'Brien     while (v && ((cmp = *name - *v->v_name) != 0 ||
598c80476e4SDavid E. O'Brien 		 (cmp = Strcmp(name, v->v_name)) != 0))
599c80476e4SDavid E. O'Brien 	if (cmp < 0)
600c80476e4SDavid E. O'Brien 	    v = v->v_left;
601c80476e4SDavid E. O'Brien 	else
602c80476e4SDavid E. O'Brien 	    v = v->v_right;
603c80476e4SDavid E. O'Brien     return v;
604c80476e4SDavid E. O'Brien }
605c80476e4SDavid E. O'Brien 
606c80476e4SDavid E. O'Brien /*
607c80476e4SDavid E. O'Brien  * The caller is responsible for putting value in a safe place
608c80476e4SDavid E. O'Brien  */
609c80476e4SDavid E. O'Brien void
610c80476e4SDavid E. O'Brien set(var, val, flags)
611c80476e4SDavid E. O'Brien     Char   *var, *val;
612c80476e4SDavid E. O'Brien     int	   flags;
613c80476e4SDavid E. O'Brien {
61423338178SMark Peek     Char **vec = (Char **) xmalloc((size_t) (2 * sizeof(Char **)));
615c80476e4SDavid E. O'Brien 
616c80476e4SDavid E. O'Brien     vec[0] = val;
617c80476e4SDavid E. O'Brien     vec[1] = 0;
618c80476e4SDavid E. O'Brien     set1(var, vec, &shvhed, flags);
619c80476e4SDavid E. O'Brien }
620c80476e4SDavid E. O'Brien 
621c80476e4SDavid E. O'Brien void
622c80476e4SDavid E. O'Brien set1(var, vec, head, flags)
623c80476e4SDavid E. O'Brien     Char   *var, **vec;
624c80476e4SDavid E. O'Brien     struct varent *head;
625c80476e4SDavid E. O'Brien     int flags;
626c80476e4SDavid E. O'Brien {
62723338178SMark Peek     Char **oldv = vec;
628c80476e4SDavid E. O'Brien 
629c80476e4SDavid E. O'Brien     if ((flags & VAR_NOGLOB) == 0) {
630c80476e4SDavid E. O'Brien 	gflag = 0;
631c80476e4SDavid E. O'Brien 	tglob(oldv);
632c80476e4SDavid E. O'Brien 	if (gflag) {
633c80476e4SDavid E. O'Brien 	    vec = globall(oldv);
634c80476e4SDavid E. O'Brien 	    if (vec == 0) {
635c80476e4SDavid E. O'Brien 		blkfree(oldv);
636c80476e4SDavid E. O'Brien 		stderror(ERR_NAME | ERR_NOMATCH);
637c80476e4SDavid E. O'Brien 		return;
638c80476e4SDavid E. O'Brien 	    }
639c80476e4SDavid E. O'Brien 	    blkfree(oldv);
640c80476e4SDavid E. O'Brien 	    gargv = 0;
641c80476e4SDavid E. O'Brien 	}
642c80476e4SDavid E. O'Brien     }
643c80476e4SDavid E. O'Brien     /*
644c80476e4SDavid E. O'Brien      * Uniqueness addition from: Michael Veksler <mveksler@vnet.ibm.com>
645c80476e4SDavid E. O'Brien      */
646c80476e4SDavid E. O'Brien     if ( flags & (VAR_FIRST | VAR_LAST) ) {
647c80476e4SDavid E. O'Brien 	/*
648c80476e4SDavid E. O'Brien 	 * Code for -f (VAR_FIRST) and -l (VAR_LAST) options.
649c80476e4SDavid E. O'Brien 	 * Method:
650c80476e4SDavid E. O'Brien 	 *  Delete all duplicate words leaving "holes" in the word array (vec).
651c80476e4SDavid E. O'Brien 	 *  Then remove the "holes", keeping the order of the words unchanged.
652c80476e4SDavid E. O'Brien 	 */
653c80476e4SDavid E. O'Brien 	if (vec && vec[0] && vec[1]) { /* more than one word ? */
654c80476e4SDavid E. O'Brien 	    int i, j;
655c80476e4SDavid E. O'Brien 	    int num_items;
656c80476e4SDavid E. O'Brien 
657c80476e4SDavid E. O'Brien 	    for (num_items = 0; vec[num_items]; num_items++)
658c80476e4SDavid E. O'Brien 	        continue;
659c80476e4SDavid E. O'Brien 	    if (flags & VAR_FIRST) {
660c80476e4SDavid E. O'Brien 		/* delete duplications, keeping first occurance */
661c80476e4SDavid E. O'Brien 		for (i = 1; i < num_items; i++)
662c80476e4SDavid E. O'Brien 		    for (j = 0; j < i; j++)
663c80476e4SDavid E. O'Brien 			/* If have earlier identical item, remove i'th item */
664c80476e4SDavid E. O'Brien 			if (vec[i] && vec[j] && Strcmp(vec[j], vec[i]) == 0) {
665c80476e4SDavid E. O'Brien 			    free(vec[i]);
666c80476e4SDavid E. O'Brien 			    vec[i] = NULL;
667c80476e4SDavid E. O'Brien 			    break;
668c80476e4SDavid E. O'Brien 			}
669c80476e4SDavid E. O'Brien 	    } else if (flags & VAR_LAST) {
670c80476e4SDavid E. O'Brien 	      /* delete duplications, keeping last occurance */
671c80476e4SDavid E. O'Brien 		for (i = 0; i < num_items - 1; i++)
672c80476e4SDavid E. O'Brien 		    for (j = i + 1; j < num_items; j++)
673c80476e4SDavid E. O'Brien 			/* If have later identical item, remove i'th item */
674c80476e4SDavid E. O'Brien 			if (vec[i] && vec[j] && Strcmp(vec[j], vec[i]) == 0) {
675c80476e4SDavid E. O'Brien 			    /* remove identical item (the first) */
676c80476e4SDavid E. O'Brien 			    free(vec[i]);
677c80476e4SDavid E. O'Brien 			    vec[i] = NULL;
678c80476e4SDavid E. O'Brien 			}
679c80476e4SDavid E. O'Brien 	    }
680c80476e4SDavid E. O'Brien 	    /* Compress items - remove empty items */
681c80476e4SDavid E. O'Brien 	    for (j = i = 0; i < num_items; i++)
682c80476e4SDavid E. O'Brien 	       if (vec[i])
683c80476e4SDavid E. O'Brien 		  vec[j++] = vec[i];
684c80476e4SDavid E. O'Brien 
685c80476e4SDavid E. O'Brien 	    /* NULL-fy remaining items */
686c80476e4SDavid E. O'Brien 	    for (; j < num_items; j++)
687c80476e4SDavid E. O'Brien 		 vec[j] = NULL;
688c80476e4SDavid E. O'Brien 	}
689c80476e4SDavid E. O'Brien 	/* don't let the attribute propagate */
690c80476e4SDavid E. O'Brien 	flags &= ~(VAR_FIRST|VAR_LAST);
691c80476e4SDavid E. O'Brien     }
692c80476e4SDavid E. O'Brien     setq(var, vec, head, flags);
693c80476e4SDavid E. O'Brien }
694c80476e4SDavid E. O'Brien 
695c80476e4SDavid E. O'Brien 
696c80476e4SDavid E. O'Brien void
697c80476e4SDavid E. O'Brien setq(name, vec, p, flags)
698c80476e4SDavid E. O'Brien     Char   *name, **vec;
69923338178SMark Peek     struct varent *p;
700c80476e4SDavid E. O'Brien     int flags;
701c80476e4SDavid E. O'Brien {
70223338178SMark Peek     struct varent *c;
70323338178SMark Peek     int f;
704c80476e4SDavid E. O'Brien 
705c80476e4SDavid E. O'Brien     f = 0;			/* tree hangs off the header's left link */
706c80476e4SDavid E. O'Brien     while ((c = p->v_link[f]) != 0) {
707c80476e4SDavid E. O'Brien 	if ((f = *name - *c->v_name) == 0 &&
708c80476e4SDavid E. O'Brien 	    (f = Strcmp(name, c->v_name)) == 0) {
709c80476e4SDavid E. O'Brien 	    if (c->v_flags & VAR_READONLY)
710c80476e4SDavid E. O'Brien 		stderror(ERR_READONLY|ERR_NAME, c->v_name);
711c80476e4SDavid E. O'Brien 	    blkfree(c->vec);
712c80476e4SDavid E. O'Brien 	    c->v_flags = flags;
713c80476e4SDavid E. O'Brien 	    trim(c->vec = vec);
714c80476e4SDavid E. O'Brien 	    return;
715c80476e4SDavid E. O'Brien 	}
716c80476e4SDavid E. O'Brien 	p = c;
717c80476e4SDavid E. O'Brien 	f = f > 0;
718c80476e4SDavid E. O'Brien     }
719c80476e4SDavid E. O'Brien     p->v_link[f] = c = (struct varent *) xmalloc((size_t)sizeof(struct varent));
720c80476e4SDavid E. O'Brien     c->v_name = Strsave(name);
721c80476e4SDavid E. O'Brien     c->v_flags = flags;
722c80476e4SDavid E. O'Brien     c->v_bal = 0;
723c80476e4SDavid E. O'Brien     c->v_left = c->v_right = 0;
724c80476e4SDavid E. O'Brien     c->v_parent = p;
725c80476e4SDavid E. O'Brien     balance(p, f, 0);
726c80476e4SDavid E. O'Brien     trim(c->vec = vec);
727c80476e4SDavid E. O'Brien }
728c80476e4SDavid E. O'Brien 
729c80476e4SDavid E. O'Brien /*ARGSUSED*/
730c80476e4SDavid E. O'Brien void
731c80476e4SDavid E. O'Brien unset(v, c)
732c80476e4SDavid E. O'Brien     Char   **v;
733c80476e4SDavid E. O'Brien     struct command *c;
734c80476e4SDavid E. O'Brien {
73523338178SMark Peek     int did_roe, did_edit;
736c80476e4SDavid E. O'Brien 
737c80476e4SDavid E. O'Brien     USE(c);
738c80476e4SDavid E. O'Brien     did_roe = adrof(STRrecognize_only_executables) != NULL;
739c80476e4SDavid E. O'Brien     did_edit = adrof(STRedit) != NULL;
740c80476e4SDavid E. O'Brien     unset1(v, &shvhed);
74129301572SMark Peek 
74229301572SMark Peek #if defined(FILEC) && defined(TIOCSTI)
74329301572SMark Peek     if (adrof(STRfilec) == 0)
74429301572SMark Peek 	filec = 0;
74529301572SMark Peek #endif /* FILEC && TIOCSTI */
74629301572SMark Peek 
747c80476e4SDavid E. O'Brien     if (adrof(STRhistchars) == 0) {
748c80476e4SDavid E. O'Brien 	HIST = '!';
749c80476e4SDavid E. O'Brien 	HISTSUB = '^';
750c80476e4SDavid E. O'Brien     }
751b2d5d167SMark Peek     if (adrof(STRignoreeof) == 0)
752b2d5d167SMark Peek 	numeof = 0;
753c80476e4SDavid E. O'Brien     if (adrof(STRpromptchars) == 0) {
754c80476e4SDavid E. O'Brien 	PRCH = '>';
755c80476e4SDavid E. O'Brien 	PRCHROOT = '#';
756c80476e4SDavid E. O'Brien     }
757c80476e4SDavid E. O'Brien     if (adrof(STRhistlit) == 0)
758c80476e4SDavid E. O'Brien 	HistLit = 0;
759c80476e4SDavid E. O'Brien     if (adrof(STRloginsh) == 0)
760c80476e4SDavid E. O'Brien 	loginsh = 0;
761c80476e4SDavid E. O'Brien     if (adrof(STRwordchars) == 0)
762c80476e4SDavid E. O'Brien 	word_chars = STR_WORD_CHARS;
763c80476e4SDavid E. O'Brien     if (adrof(STRedit) == 0)
764c80476e4SDavid E. O'Brien 	editing = 0;
765c80476e4SDavid E. O'Brien     if (adrof(STRbackslash_quote) == 0)
766c80476e4SDavid E. O'Brien 	bslash_quote = 0;
767c80476e4SDavid E. O'Brien     if (adrof(STRsymlinks) == 0)
768c80476e4SDavid E. O'Brien 	symlinks = 0;
769c80476e4SDavid E. O'Brien     if (adrof(STRimplicitcd) == 0)
770c80476e4SDavid E. O'Brien 	implicit_cd = 0;
7716767bd61SMark Peek     if (adrof(STRkillring) == 0)
7726767bd61SMark Peek 	SetKillRing(0);
773c80476e4SDavid E. O'Brien     if (did_edit && noediting && adrof(STRedit) == 0)
774c80476e4SDavid E. O'Brien 	noediting = 0;
775c80476e4SDavid E. O'Brien     if (did_roe && adrof(STRrecognize_only_executables) == 0)
776c80476e4SDavid E. O'Brien 	tw_cmd_free();
777c80476e4SDavid E. O'Brien #ifdef COLOR_LS_F
778c80476e4SDavid E. O'Brien     if (adrof(STRcolor) == 0)
779c80476e4SDavid E. O'Brien 	set_color_context();
780c80476e4SDavid E. O'Brien #endif /* COLOR_LS_F */
781c80476e4SDavid E. O'Brien #if defined(KANJI) && defined(SHORT_STRINGS) && defined(DSPMBYTE)
782c80476e4SDavid E. O'Brien     update_dspmbyte_vars();
783c80476e4SDavid E. O'Brien #endif
7843b6eaa7bSAndrey A. Chernov #ifdef NLS_CATALOGS
78523338178SMark Peek     nlsclose();
7863b6eaa7bSAndrey A. Chernov     nlsinit();
7873b6eaa7bSAndrey A. Chernov #endif /* NLS_CATALOGS */
788c80476e4SDavid E. O'Brien }
789c80476e4SDavid E. O'Brien 
790c80476e4SDavid E. O'Brien void
791c80476e4SDavid E. O'Brien unset1(v, head)
79223338178SMark Peek     Char *v[];
793c80476e4SDavid E. O'Brien     struct varent *head;
794c80476e4SDavid E. O'Brien {
79523338178SMark Peek     struct varent *vp;
79623338178SMark Peek     int cnt;
797c80476e4SDavid E. O'Brien 
798c80476e4SDavid E. O'Brien     while (*++v) {
799c80476e4SDavid E. O'Brien 	cnt = 0;
800c80476e4SDavid E. O'Brien 	while ((vp = madrof(*v, head)) != NULL)
801c80476e4SDavid E. O'Brien 	    if (vp->v_flags & VAR_READONLY)
802c80476e4SDavid E. O'Brien 		stderror(ERR_READONLY|ERR_NAME, vp->v_name);
803c80476e4SDavid E. O'Brien 	    else
804c80476e4SDavid E. O'Brien 		unsetv1(vp), cnt++;
805c80476e4SDavid E. O'Brien 	if (cnt == 0)
806c80476e4SDavid E. O'Brien 	    setname(short2str(*v));
807c80476e4SDavid E. O'Brien     }
808c80476e4SDavid E. O'Brien }
809c80476e4SDavid E. O'Brien 
810c80476e4SDavid E. O'Brien void
811c80476e4SDavid E. O'Brien unsetv(var)
812c80476e4SDavid E. O'Brien     Char   *var;
813c80476e4SDavid E. O'Brien {
81423338178SMark Peek     struct varent *vp;
815c80476e4SDavid E. O'Brien 
816c80476e4SDavid E. O'Brien     if ((vp = adrof1(var, &shvhed)) == 0)
817c80476e4SDavid E. O'Brien 	udvar(var);
818c80476e4SDavid E. O'Brien     unsetv1(vp);
819c80476e4SDavid E. O'Brien }
820c80476e4SDavid E. O'Brien 
821c80476e4SDavid E. O'Brien static void
822c80476e4SDavid E. O'Brien unsetv1(p)
82323338178SMark Peek     struct varent *p;
824c80476e4SDavid E. O'Brien {
82523338178SMark Peek     struct varent *c, *pp;
82623338178SMark Peek     int f;
827c80476e4SDavid E. O'Brien 
828c80476e4SDavid E. O'Brien     /*
829c80476e4SDavid E. O'Brien      * Free associated memory first to avoid complications.
830c80476e4SDavid E. O'Brien      */
831c80476e4SDavid E. O'Brien     blkfree(p->vec);
832c80476e4SDavid E. O'Brien     xfree((ptr_t) p->v_name);
833c80476e4SDavid E. O'Brien     /*
834c80476e4SDavid E. O'Brien      * If p is missing one child, then we can move the other into where p is.
835c80476e4SDavid E. O'Brien      * Otherwise, we find the predecessor of p, which is guaranteed to have no
836c80476e4SDavid E. O'Brien      * right child, copy it into p, and move it's left child into it.
837c80476e4SDavid E. O'Brien      */
838c80476e4SDavid E. O'Brien     if (p->v_right == 0)
839c80476e4SDavid E. O'Brien 	c = p->v_left;
840c80476e4SDavid E. O'Brien     else if (p->v_left == 0)
841c80476e4SDavid E. O'Brien 	c = p->v_right;
842c80476e4SDavid E. O'Brien     else {
843c80476e4SDavid E. O'Brien 	for (c = p->v_left; c->v_right; c = c->v_right)
844c80476e4SDavid E. O'Brien 	    continue;
845c80476e4SDavid E. O'Brien 	p->v_name = c->v_name;
846c80476e4SDavid E. O'Brien 	p->v_flags = c->v_flags;
847c80476e4SDavid E. O'Brien 	p->vec = c->vec;
848c80476e4SDavid E. O'Brien 	p = c;
849c80476e4SDavid E. O'Brien 	c = p->v_left;
850c80476e4SDavid E. O'Brien     }
851c80476e4SDavid E. O'Brien 
852c80476e4SDavid E. O'Brien     /*
853c80476e4SDavid E. O'Brien      * Move c into where p is.
854c80476e4SDavid E. O'Brien      */
855c80476e4SDavid E. O'Brien     pp = p->v_parent;
856c80476e4SDavid E. O'Brien     f = pp->v_right == p;
857c80476e4SDavid E. O'Brien     if ((pp->v_link[f] = c) != 0)
858c80476e4SDavid E. O'Brien 	c->v_parent = pp;
859c80476e4SDavid E. O'Brien     /*
860c80476e4SDavid E. O'Brien      * Free the deleted node, and rebalance.
861c80476e4SDavid E. O'Brien      */
862c80476e4SDavid E. O'Brien     xfree((ptr_t) p);
863c80476e4SDavid E. O'Brien     balance(pp, f, 1);
864c80476e4SDavid E. O'Brien }
865c80476e4SDavid E. O'Brien 
866c80476e4SDavid E. O'Brien void
867c80476e4SDavid E. O'Brien setNS(cp)
868c80476e4SDavid E. O'Brien     Char   *cp;
869c80476e4SDavid E. O'Brien {
870c80476e4SDavid E. O'Brien     set(cp, Strsave(STRNULL), VAR_READWRITE);
871c80476e4SDavid E. O'Brien }
872c80476e4SDavid E. O'Brien 
873c80476e4SDavid E. O'Brien /*ARGSUSED*/
874c80476e4SDavid E. O'Brien void
875c80476e4SDavid E. O'Brien shift(v, c)
87623338178SMark Peek     Char **v;
877c80476e4SDavid E. O'Brien     struct command *c;
878c80476e4SDavid E. O'Brien {
87923338178SMark Peek     struct varent *argv;
88023338178SMark Peek     Char *name;
881c80476e4SDavid E. O'Brien 
882c80476e4SDavid E. O'Brien     USE(c);
883c80476e4SDavid E. O'Brien     v++;
884c80476e4SDavid E. O'Brien     name = *v;
885c80476e4SDavid E. O'Brien     if (name == 0)
886c80476e4SDavid E. O'Brien 	name = STRargv;
887c80476e4SDavid E. O'Brien     else
888c80476e4SDavid E. O'Brien 	(void) strip(name);
889c80476e4SDavid E. O'Brien     argv = adrof(name);
89029301572SMark Peek     if (argv == NULL || argv->vec == NULL)
891c80476e4SDavid E. O'Brien 	udvar(name);
892c80476e4SDavid E. O'Brien     if (argv->vec[0] == 0)
893c80476e4SDavid E. O'Brien 	stderror(ERR_NAME | ERR_NOMORE);
894c80476e4SDavid E. O'Brien     lshift(argv->vec, 1);
895c80476e4SDavid E. O'Brien     update_vars(name);
896c80476e4SDavid E. O'Brien }
897c80476e4SDavid E. O'Brien 
898c80476e4SDavid E. O'Brien static Char STRsep[2] = { PATHSEP, '\0' };
899c80476e4SDavid E. O'Brien 
900c80476e4SDavid E. O'Brien static void
901c80476e4SDavid E. O'Brien exportpath(val)
902c80476e4SDavid E. O'Brien     Char  **val;
903c80476e4SDavid E. O'Brien {
904c80476e4SDavid E. O'Brien   Char    	*exppath;
905c80476e4SDavid E. O'Brien   size_t	exppath_size = BUFSIZE;
906c80476e4SDavid E. O'Brien   exppath = (Char *)xmalloc(sizeof(Char)*exppath_size);
907c80476e4SDavid E. O'Brien 
908c80476e4SDavid E. O'Brien     exppath[0] = 0;
909c80476e4SDavid E. O'Brien     if (val)
910c80476e4SDavid E. O'Brien 	while (*val) {
911c80476e4SDavid E. O'Brien 	  while (Strlen(*val) + Strlen(exppath) + 2 > exppath_size) {
912c80476e4SDavid E. O'Brien 	    if ((exppath
913c80476e4SDavid E. O'Brien 		 = (Char *)xrealloc(exppath, sizeof(Char)*(exppath_size *= 2)))
914c80476e4SDavid E. O'Brien 		 == NULL) {
915c80476e4SDavid E. O'Brien 		xprintf(CGETS(18, 1,
916c80476e4SDavid E. O'Brien 			      "Warning: ridiculously long PATH truncated\n"));
917c80476e4SDavid E. O'Brien 		break;
918c80476e4SDavid E. O'Brien 	      }
919c80476e4SDavid E. O'Brien 	    }
920c80476e4SDavid E. O'Brien 	    (void) Strcat(exppath, *val++);
921c80476e4SDavid E. O'Brien 	    if (*val == 0 || eq(*val, STRRparen))
922c80476e4SDavid E. O'Brien 	      break;
923c80476e4SDavid E. O'Brien 	    (void) Strcat(exppath, STRsep);
924c80476e4SDavid E. O'Brien 	  }
925c80476e4SDavid E. O'Brien   tsetenv(STRKPATH, exppath);
926c80476e4SDavid E. O'Brien   free(exppath);
927c80476e4SDavid E. O'Brien }
928c80476e4SDavid E. O'Brien 
929c80476e4SDavid E. O'Brien #ifndef lint
930c80476e4SDavid E. O'Brien  /*
931c80476e4SDavid E. O'Brien   * Lint thinks these have null effect
932c80476e4SDavid E. O'Brien   */
933c80476e4SDavid E. O'Brien  /* macros to do single rotations on node p */
934c80476e4SDavid E. O'Brien # define rright(p) (\
935c80476e4SDavid E. O'Brien 	t = (p)->v_left,\
936c80476e4SDavid E. O'Brien 	(t)->v_parent = (p)->v_parent,\
937c80476e4SDavid E. O'Brien 	(((p)->v_left = t->v_right) != NULL) ?\
938c80476e4SDavid E. O'Brien 	    (t->v_right->v_parent = (p)) : 0,\
939c80476e4SDavid E. O'Brien 	(t->v_right = (p))->v_parent = t,\
940c80476e4SDavid E. O'Brien 	(p) = t)
941c80476e4SDavid E. O'Brien # define rleft(p) (\
942c80476e4SDavid E. O'Brien 	t = (p)->v_right,\
943c80476e4SDavid E. O'Brien 	((t)->v_parent = (p)->v_parent,\
944c80476e4SDavid E. O'Brien 	((p)->v_right = t->v_left) != NULL) ? \
945c80476e4SDavid E. O'Brien 		(t->v_left->v_parent = (p)) : 0,\
946c80476e4SDavid E. O'Brien 	(t->v_left = (p))->v_parent = t,\
947c80476e4SDavid E. O'Brien 	(p) = t)
948c80476e4SDavid E. O'Brien #else
949c80476e4SDavid E. O'Brien static struct varent *
950c80476e4SDavid E. O'Brien rleft(p)
951c80476e4SDavid E. O'Brien     struct varent *p;
952c80476e4SDavid E. O'Brien {
953c80476e4SDavid E. O'Brien     return (p);
954c80476e4SDavid E. O'Brien }
955c80476e4SDavid E. O'Brien static struct varent *
956c80476e4SDavid E. O'Brien rright(p)
957c80476e4SDavid E. O'Brien     struct varent *p;
958c80476e4SDavid E. O'Brien {
959c80476e4SDavid E. O'Brien     return (p);
960c80476e4SDavid E. O'Brien }
961c80476e4SDavid E. O'Brien 
962c80476e4SDavid E. O'Brien #endif /* ! lint */
963c80476e4SDavid E. O'Brien 
964c80476e4SDavid E. O'Brien 
965c80476e4SDavid E. O'Brien /*
966c80476e4SDavid E. O'Brien  * Rebalance a tree, starting at p and up.
967c80476e4SDavid E. O'Brien  * F == 0 means we've come from p's left child.
968c80476e4SDavid E. O'Brien  * D == 1 means we've just done a delete, otherwise an insert.
969c80476e4SDavid E. O'Brien  */
970c80476e4SDavid E. O'Brien static void
971c80476e4SDavid E. O'Brien balance(p, f, d)
97223338178SMark Peek     struct varent *p;
97323338178SMark Peek     int f, d;
974c80476e4SDavid E. O'Brien {
97523338178SMark Peek     struct varent *pp;
976c80476e4SDavid E. O'Brien 
977c80476e4SDavid E. O'Brien #ifndef lint
97823338178SMark Peek     struct varent *t;	/* used by the rotate macros */
979c80476e4SDavid E. O'Brien #endif /* !lint */
98023338178SMark Peek     int ff;
981c80476e4SDavid E. O'Brien #ifdef lint
982c80476e4SDavid E. O'Brien     ff = 0;	/* Sun's lint is dumb! */
983c80476e4SDavid E. O'Brien #endif
984c80476e4SDavid E. O'Brien 
985c80476e4SDavid E. O'Brien     /*
986c80476e4SDavid E. O'Brien      * Ok, from here on, p is the node we're operating on; pp is it's parent; f
987c80476e4SDavid E. O'Brien      * is the branch of p from which we have come; ff is the branch of pp which
988c80476e4SDavid E. O'Brien      * is p.
989c80476e4SDavid E. O'Brien      */
990c80476e4SDavid E. O'Brien     for (; (pp = p->v_parent) != 0; p = pp, f = ff) {
991c80476e4SDavid E. O'Brien 	ff = pp->v_right == p;
992c80476e4SDavid E. O'Brien 	if (f ^ d) {		/* right heavy */
993c80476e4SDavid E. O'Brien 	    switch (p->v_bal) {
994c80476e4SDavid E. O'Brien 	    case -1:		/* was left heavy */
995c80476e4SDavid E. O'Brien 		p->v_bal = 0;
996c80476e4SDavid E. O'Brien 		break;
997c80476e4SDavid E. O'Brien 	    case 0:		/* was balanced */
998c80476e4SDavid E. O'Brien 		p->v_bal = 1;
999c80476e4SDavid E. O'Brien 		break;
1000c80476e4SDavid E. O'Brien 	    case 1:		/* was already right heavy */
1001c80476e4SDavid E. O'Brien 		switch (p->v_right->v_bal) {
1002c80476e4SDavid E. O'Brien 		case 1:	/* sigle rotate */
1003c80476e4SDavid E. O'Brien 		    pp->v_link[ff] = rleft(p);
1004c80476e4SDavid E. O'Brien 		    p->v_left->v_bal = 0;
1005c80476e4SDavid E. O'Brien 		    p->v_bal = 0;
1006c80476e4SDavid E. O'Brien 		    break;
1007c80476e4SDavid E. O'Brien 		case 0:	/* single rotate */
1008c80476e4SDavid E. O'Brien 		    pp->v_link[ff] = rleft(p);
1009c80476e4SDavid E. O'Brien 		    p->v_left->v_bal = 1;
1010c80476e4SDavid E. O'Brien 		    p->v_bal = -1;
1011c80476e4SDavid E. O'Brien 		    break;
1012c80476e4SDavid E. O'Brien 		case -1:	/* double rotate */
1013c80476e4SDavid E. O'Brien 		    (void) rright(p->v_right);
1014c80476e4SDavid E. O'Brien 		    pp->v_link[ff] = rleft(p);
1015c80476e4SDavid E. O'Brien 		    p->v_left->v_bal =
1016c80476e4SDavid E. O'Brien 			p->v_bal < 1 ? 0 : -1;
1017c80476e4SDavid E. O'Brien 		    p->v_right->v_bal =
1018c80476e4SDavid E. O'Brien 			p->v_bal > -1 ? 0 : 1;
1019c80476e4SDavid E. O'Brien 		    p->v_bal = 0;
1020c80476e4SDavid E. O'Brien 		    break;
1021c80476e4SDavid E. O'Brien 		default:
1022c80476e4SDavid E. O'Brien 		    break;
1023c80476e4SDavid E. O'Brien 		}
1024c80476e4SDavid E. O'Brien 		break;
1025c80476e4SDavid E. O'Brien 	    default:
1026c80476e4SDavid E. O'Brien 		break;
1027c80476e4SDavid E. O'Brien 	    }
1028c80476e4SDavid E. O'Brien 	}
1029c80476e4SDavid E. O'Brien 	else {			/* left heavy */
1030c80476e4SDavid E. O'Brien 	    switch (p->v_bal) {
1031c80476e4SDavid E. O'Brien 	    case 1:		/* was right heavy */
1032c80476e4SDavid E. O'Brien 		p->v_bal = 0;
1033c80476e4SDavid E. O'Brien 		break;
1034c80476e4SDavid E. O'Brien 	    case 0:		/* was balanced */
1035c80476e4SDavid E. O'Brien 		p->v_bal = -1;
1036c80476e4SDavid E. O'Brien 		break;
1037c80476e4SDavid E. O'Brien 	    case -1:		/* was already left heavy */
1038c80476e4SDavid E. O'Brien 		switch (p->v_left->v_bal) {
1039c80476e4SDavid E. O'Brien 		case -1:	/* single rotate */
1040c80476e4SDavid E. O'Brien 		    pp->v_link[ff] = rright(p);
1041c80476e4SDavid E. O'Brien 		    p->v_right->v_bal = 0;
1042c80476e4SDavid E. O'Brien 		    p->v_bal = 0;
1043c80476e4SDavid E. O'Brien 		    break;
1044c80476e4SDavid E. O'Brien 		case 0:	/* signle rotate */
1045c80476e4SDavid E. O'Brien 		    pp->v_link[ff] = rright(p);
1046c80476e4SDavid E. O'Brien 		    p->v_right->v_bal = -1;
1047c80476e4SDavid E. O'Brien 		    p->v_bal = 1;
1048c80476e4SDavid E. O'Brien 		    break;
1049c80476e4SDavid E. O'Brien 		case 1:	/* double rotate */
1050c80476e4SDavid E. O'Brien 		    (void) rleft(p->v_left);
1051c80476e4SDavid E. O'Brien 		    pp->v_link[ff] = rright(p);
1052c80476e4SDavid E. O'Brien 		    p->v_left->v_bal =
1053c80476e4SDavid E. O'Brien 			p->v_bal < 1 ? 0 : -1;
1054c80476e4SDavid E. O'Brien 		    p->v_right->v_bal =
1055c80476e4SDavid E. O'Brien 			p->v_bal > -1 ? 0 : 1;
1056c80476e4SDavid E. O'Brien 		    p->v_bal = 0;
1057c80476e4SDavid E. O'Brien 		    break;
1058c80476e4SDavid E. O'Brien 		default:
1059c80476e4SDavid E. O'Brien 		    break;
1060c80476e4SDavid E. O'Brien 		}
1061c80476e4SDavid E. O'Brien 		break;
1062c80476e4SDavid E. O'Brien 	    default:
1063c80476e4SDavid E. O'Brien 		break;
1064c80476e4SDavid E. O'Brien 	    }
1065c80476e4SDavid E. O'Brien 	}
1066c80476e4SDavid E. O'Brien 	/*
1067c80476e4SDavid E. O'Brien 	 * If from insert, then we terminate when p is balanced. If from
1068c80476e4SDavid E. O'Brien 	 * delete, then we terminate when p is unbalanced.
1069c80476e4SDavid E. O'Brien 	 */
1070c80476e4SDavid E. O'Brien 	if ((p->v_bal == 0) ^ d)
1071c80476e4SDavid E. O'Brien 	    break;
1072c80476e4SDavid E. O'Brien     }
1073c80476e4SDavid E. O'Brien }
1074c80476e4SDavid E. O'Brien 
1075c80476e4SDavid E. O'Brien void
1076c80476e4SDavid E. O'Brien plist(p, what)
107723338178SMark Peek     struct varent *p;
1078c80476e4SDavid E. O'Brien     int what;
1079c80476e4SDavid E. O'Brien {
108023338178SMark Peek     struct varent *c;
108123338178SMark Peek     int len;
1082c80476e4SDavid E. O'Brien 
1083c80476e4SDavid E. O'Brien     if (setintr)
1084c80476e4SDavid E. O'Brien #ifdef BSDSIGS
1085c80476e4SDavid E. O'Brien 	(void) sigsetmask(sigblock((sigmask_t) 0) & ~sigmask(SIGINT));
1086c80476e4SDavid E. O'Brien #else /* !BSDSIGS */
1087c80476e4SDavid E. O'Brien 	(void) sigrelse(SIGINT);
1088c80476e4SDavid E. O'Brien #endif /* BSDSIGS */
1089c80476e4SDavid E. O'Brien 
1090c80476e4SDavid E. O'Brien     for (;;) {
1091c80476e4SDavid E. O'Brien 	while (p->v_left)
1092c80476e4SDavid E. O'Brien 	    p = p->v_left;
1093c80476e4SDavid E. O'Brien x:
1094c80476e4SDavid E. O'Brien 	if (p->v_parent == 0)	/* is it the header? */
1095c80476e4SDavid E. O'Brien 	    return;
1096c80476e4SDavid E. O'Brien 	if ((p->v_flags & what) != 0) {
1097c80476e4SDavid E. O'Brien 	    len = blklen(p->vec);
1098c80476e4SDavid E. O'Brien 	    xprintf("%S\t", p->v_name);
1099c80476e4SDavid E. O'Brien 	    if (len != 1)
1100c80476e4SDavid E. O'Brien 		xputchar('(');
1101c80476e4SDavid E. O'Brien 	    blkpr(p->vec);
1102c80476e4SDavid E. O'Brien 	    if (len != 1)
1103c80476e4SDavid E. O'Brien 		xputchar(')');
1104c80476e4SDavid E. O'Brien 	    xputchar('\n');
1105c80476e4SDavid E. O'Brien 	}
1106c80476e4SDavid E. O'Brien 	if (p->v_right) {
1107c80476e4SDavid E. O'Brien 	    p = p->v_right;
1108c80476e4SDavid E. O'Brien 	    continue;
1109c80476e4SDavid E. O'Brien 	}
1110c80476e4SDavid E. O'Brien 	do {
1111c80476e4SDavid E. O'Brien 	    c = p;
1112c80476e4SDavid E. O'Brien 	    p = p->v_parent;
1113c80476e4SDavid E. O'Brien 	} while (p->v_right == c);
1114c80476e4SDavid E. O'Brien 	goto x;
1115c80476e4SDavid E. O'Brien     }
1116c80476e4SDavid E. O'Brien }
1117c80476e4SDavid E. O'Brien 
1118c80476e4SDavid E. O'Brien #if defined(KANJI) && defined(SHORT_STRINGS) && defined(DSPMBYTE)
111923338178SMark Peek extern int dspmbyte_ls;
1120c80476e4SDavid E. O'Brien 
1121c80476e4SDavid E. O'Brien void
1122c80476e4SDavid E. O'Brien update_dspmbyte_vars()
1123c80476e4SDavid E. O'Brien {
1124c80476e4SDavid E. O'Brien     int lp, iskcode;
1125c80476e4SDavid E. O'Brien     Char *dstr1;
1126c80476e4SDavid E. O'Brien     struct varent *vp;
1127c80476e4SDavid E. O'Brien 
1128c80476e4SDavid E. O'Brien     /* if variable "nokanji" is set, multi-byte display is disabled */
1129c80476e4SDavid E. O'Brien     if ((vp = adrof(CHECK_MBYTEVAR)) && !adrof(STRnokanji)) {
1130c80476e4SDavid E. O'Brien 	_enable_mbdisp = 1;
1131c80476e4SDavid E. O'Brien 	dstr1 = vp->vec[0];
113223338178SMark Peek 	if(eq (dstr1, STRsjis))
1133c80476e4SDavid E. O'Brien 	    iskcode = 1;
113423338178SMark Peek 	else if (eq(dstr1, STReuc))
1135c80476e4SDavid E. O'Brien 	    iskcode = 2;
113623338178SMark Peek 	else if (eq(dstr1, STRbig5))
11376767bd61SMark Peek 	    iskcode = 3;
113823338178SMark Peek 	else if (eq(dstr1, STRutf8))
113929301572SMark Peek 	    iskcode = 4;
1140c80476e4SDavid E. O'Brien 	else if ((dstr1[0] - '0') >= 0 && (dstr1[0] - '0') <= 3) {
1141c80476e4SDavid E. O'Brien 	    iskcode = 0;
1142c80476e4SDavid E. O'Brien 	}
1143c80476e4SDavid E. O'Brien 	else {
1144c80476e4SDavid E. O'Brien 	    xprintf(CGETS(18, 2,
1145c80476e4SDavid E. O'Brien 	       "Warning: unknown multibyte display; using default(euc(JP))\n"));
1146c80476e4SDavid E. O'Brien 	    iskcode = 2;
1147c80476e4SDavid E. O'Brien 	}
1148c80476e4SDavid E. O'Brien 	if (dstr1 && vp->vec[1] && eq(vp->vec[1], STRls))
1149c80476e4SDavid E. O'Brien 	  dspmbyte_ls = 1;
1150c80476e4SDavid E. O'Brien 	else
1151c80476e4SDavid E. O'Brien 	  dspmbyte_ls = 0;
1152c80476e4SDavid E. O'Brien 	for (lp = 0; lp < 256 && iskcode > 0; lp++) {
1153c80476e4SDavid E. O'Brien 	    switch (iskcode) {
1154c80476e4SDavid E. O'Brien 	    case 1:
1155c80476e4SDavid E. O'Brien 		/* Shift-JIS */
1156c80476e4SDavid E. O'Brien 		_cmap[lp] = _cmap_mbyte[lp];
1157c80476e4SDavid E. O'Brien 		_mbmap[lp] = _mbmap_sjis[lp];
1158c80476e4SDavid E. O'Brien 		break;
1159c80476e4SDavid E. O'Brien 	    case 2:
1160c80476e4SDavid E. O'Brien 		/* 2 ... euc */
1161c80476e4SDavid E. O'Brien 		_cmap[lp] = _cmap_mbyte[lp];
1162c80476e4SDavid E. O'Brien 		_mbmap[lp] = _mbmap_euc[lp];
1163c80476e4SDavid E. O'Brien 		break;
11646767bd61SMark Peek 	    case 3:
11656767bd61SMark Peek 		/* 3 ... big5 */
11666767bd61SMark Peek 		_cmap[lp] = _cmap_mbyte[lp];
11676767bd61SMark Peek 		_mbmap[lp] = _mbmap_big5[lp];
11686767bd61SMark Peek 		break;
116929301572SMark Peek 	    case 4:
117029301572SMark Peek 		/* 4 ... utf8 */
117129301572SMark Peek 		_cmap[lp] = _cmap_mbyte[lp];
117229301572SMark Peek 		_mbmap[lp] = _mbmap_utf8[lp];
117329301572SMark Peek 		break;
1174c80476e4SDavid E. O'Brien 	    default:
1175c80476e4SDavid E. O'Brien 		xprintf(CGETS(18, 3,
1176c80476e4SDavid E. O'Brien 		    "Warning: unknown multibyte code %d; multibyte disabled\n"),
1177c80476e4SDavid E. O'Brien 		    iskcode);
1178c80476e4SDavid E. O'Brien 		_cmap[lp] = _cmap_c[lp];
1179c80476e4SDavid E. O'Brien 		_mbmap[lp] = 0;	/* Default map all 0 */
1180c80476e4SDavid E. O'Brien 		_enable_mbdisp = 0;
1181c80476e4SDavid E. O'Brien 		break;
1182c80476e4SDavid E. O'Brien 	    }
1183c80476e4SDavid E. O'Brien 	}
1184c80476e4SDavid E. O'Brien 	if (iskcode == 0) {
1185c80476e4SDavid E. O'Brien 	    /* check original table */
1186c80476e4SDavid E. O'Brien 	    if (Strlen(dstr1) != 256) {
1187c80476e4SDavid E. O'Brien 		xprintf(CGETS(18, 4,
1188c80476e4SDavid E. O'Brien        "Warning: Invalid multibyte table length (%d); multibyte disabled\n"),
1189c80476e4SDavid E. O'Brien 		    Strlen(dstr1));
1190c80476e4SDavid E. O'Brien 		_enable_mbdisp = 0;
1191c80476e4SDavid E. O'Brien 	    }
1192c80476e4SDavid E. O'Brien 	    for (lp = 0; lp < 256 && _enable_mbdisp == 1; lp++) {
1193c80476e4SDavid E. O'Brien 		if (!((dstr1[lp] - '0') >= 0 && (dstr1[lp] - '0') <= 3)) {
1194c80476e4SDavid E. O'Brien 		    xprintf(CGETS(18, 4,
1195c80476e4SDavid E. O'Brien 	   "Warning: bad multibyte code at offset +%d; multibyte diabled\n"),
1196c80476e4SDavid E. O'Brien 			lp);
1197c80476e4SDavid E. O'Brien 		    _enable_mbdisp = 0;
1198c80476e4SDavid E. O'Brien 		    break;
1199c80476e4SDavid E. O'Brien 		}
1200c80476e4SDavid E. O'Brien 	    }
1201c80476e4SDavid E. O'Brien 	    /* set original table */
1202c80476e4SDavid E. O'Brien 	    for (lp = 0; lp < 256; lp++) {
1203c80476e4SDavid E. O'Brien 		if (_enable_mbdisp == 1) {
1204c80476e4SDavid E. O'Brien 		    _cmap[lp] = _cmap_mbyte[lp];
1205c80476e4SDavid E. O'Brien 		    _mbmap[lp] = (unsigned short) ((dstr1[lp] - '0') & 0x0f);
1206c80476e4SDavid E. O'Brien 		}
1207c80476e4SDavid E. O'Brien 		else {
1208c80476e4SDavid E. O'Brien 		    _cmap[lp] = _cmap_c[lp];
1209c80476e4SDavid E. O'Brien 		    _mbmap[lp] = 0;	/* Default map all 0 */
1210c80476e4SDavid E. O'Brien 		}
1211c80476e4SDavid E. O'Brien 	    }
1212c80476e4SDavid E. O'Brien 	}
1213c80476e4SDavid E. O'Brien     }
1214c80476e4SDavid E. O'Brien     else {
1215c80476e4SDavid E. O'Brien 	for (lp = 0; lp < 256; lp++) {
1216c80476e4SDavid E. O'Brien 	    _cmap[lp] = _cmap_c[lp];
1217c80476e4SDavid E. O'Brien 	    _mbmap[lp] = 0;	/* Default map all 0 */
1218c80476e4SDavid E. O'Brien 	}
1219c80476e4SDavid E. O'Brien 	_enable_mbdisp = 0;
1220c80476e4SDavid E. O'Brien 	dspmbyte_ls = 0;
1221c80476e4SDavid E. O'Brien     }
1222c80476e4SDavid E. O'Brien #ifdef MBYTEDEBUG	/* Sorry, use for beta testing */
1223c80476e4SDavid E. O'Brien     {
1224c80476e4SDavid E. O'Brien 	Char mbmapstr[300];
1225c80476e4SDavid E. O'Brien 	for (lp = 0; lp < 256; lp++) {
1226c80476e4SDavid E. O'Brien 	    mbmapstr[lp] = _mbmap[lp] + '0';
1227c80476e4SDavid E. O'Brien 	    mbmapstr[lp+1] = 0;
1228c80476e4SDavid E. O'Brien 	}
1229c80476e4SDavid E. O'Brien 	set(STRmbytemap, Strsave(mbmapstr), VAR_READWRITE);
1230c80476e4SDavid E. O'Brien     }
1231c80476e4SDavid E. O'Brien #endif /* MBYTEMAP */
1232c80476e4SDavid E. O'Brien }
1233c80476e4SDavid E. O'Brien 
1234c80476e4SDavid E. O'Brien /* dspkanji/dspmbyte autosetting */
1235c80476e4SDavid E. O'Brien /* PATCH IDEA FROM Issei.Suzuki VERY THANKS */
1236c80476e4SDavid E. O'Brien void
1237c80476e4SDavid E. O'Brien autoset_dspmbyte(pcp)
1238c80476e4SDavid E. O'Brien     Char *pcp;
1239c80476e4SDavid E. O'Brien {
1240c80476e4SDavid E. O'Brien     int i;
1241c80476e4SDavid E. O'Brien     struct dspm_autoset_Table {
1242c80476e4SDavid E. O'Brien 	Char *n;
1243c80476e4SDavid E. O'Brien 	Char *v;
1244c80476e4SDavid E. O'Brien     } dspmt[] = {
124523338178SMark Peek 	{ STRLANGEUCJP, STReuc },
124623338178SMark Peek 	{ STRLANGEUCKR, STReuc },
124723338178SMark Peek 	{ STRLANGEUCZH, STReuc },
124823338178SMark Peek 	{ STRLANGEUCJPB, STReuc },
124923338178SMark Peek 	{ STRLANGEUCKRB, STReuc },
125023338178SMark Peek 	{ STRLANGEUCZHB, STReuc },
1251b2d5d167SMark Peek #ifdef linux
125223338178SMark Peek 	{ STRLANGEUCJPC, STReuc },
1253b2d5d167SMark Peek #endif
125423338178SMark Peek 	{ STRLANGSJIS, STRsjis },
125523338178SMark Peek 	{ STRLANGSJISB, STRsjis },
125623338178SMark Peek 	{ STRLANGBIG5, STRbig5 },
125723338178SMark Peek 	{ STRstarutfstar8, STRutf8 },
1258c80476e4SDavid E. O'Brien 	{ NULL, NULL }
1259c80476e4SDavid E. O'Brien     };
126023338178SMark Peek #ifdef HAVE_NL_LANGINFO
126123338178SMark Peek     struct dspm_autoset_Table dspmc[] = {
126223338178SMark Peek 	{ STRstarutfstar8, STRutf8 },
126323338178SMark Peek 	{ STReuc, STReuc },
126423338178SMark Peek 	{ STRGB2312, STReuc },
126523338178SMark Peek 	{ STRLANGBIG5, STRbig5 },
126623338178SMark Peek 	{ NULL, NULL }
126723338178SMark Peek     };
126823338178SMark Peek     Char *codeset;
126923338178SMark Peek 
127023338178SMark Peek     codeset = str2short(nl_langinfo(CODESET));
127123338178SMark Peek     if (*codeset != '\0') {
127223338178SMark Peek 	for (i = 0; dspmc[i].n; i++) {
127323338178SMark Peek 	    Char *estr;
127423338178SMark Peek 	    if (dspmc[i].n[0] && t_pmatch(pcp, dspmc[i].n, &estr, 0) > 0) {
127523338178SMark Peek 		set(CHECK_MBYTEVAR, Strsave(dspmc[i].v), VAR_READWRITE);
127623338178SMark Peek 		update_dspmbyte_vars();
127723338178SMark Peek 		return;
127823338178SMark Peek 	    }
127923338178SMark Peek 	}
128023338178SMark Peek     }
128123338178SMark Peek #endif
1282c80476e4SDavid E. O'Brien 
1283c80476e4SDavid E. O'Brien     if (*pcp == '\0')
1284c80476e4SDavid E. O'Brien 	return;
1285c80476e4SDavid E. O'Brien 
1286c80476e4SDavid E. O'Brien     for (i = 0; dspmt[i].n; i++) {
1287b2d5d167SMark Peek 	Char *estr;
128823338178SMark Peek 	if (dspmt[i].n[0] && t_pmatch(pcp, dspmt[i].n, &estr, 0) > 0) {
1289c80476e4SDavid E. O'Brien 	    set(CHECK_MBYTEVAR, Strsave(dspmt[i].v), VAR_READWRITE);
1290c80476e4SDavid E. O'Brien 	    update_dspmbyte_vars();
1291c80476e4SDavid E. O'Brien 	    break;
1292c80476e4SDavid E. O'Brien 	}
1293c80476e4SDavid E. O'Brien     }
1294c80476e4SDavid E. O'Brien }
1295c80476e4SDavid E. O'Brien #endif
1296