sh.set.c revision 167465
1244197Sgonzo/* $Header: /p/tcsh/cvsroot/tcsh/sh.set.c,v 3.70 2006/08/24 20:56:31 christos Exp $ */
2244197Sgonzo/*
3244197Sgonzo * sh.set.c: Setting and Clearing of variables
4244197Sgonzo */
5244197Sgonzo/*-
6244197Sgonzo * Copyright (c) 1980, 1991 The Regents of the University of California.
7244197Sgonzo * All rights reserved.
8244197Sgonzo *
9244197Sgonzo * Redistribution and use in source and binary forms, with or without
10244197Sgonzo * modification, are permitted provided that the following conditions
11244197Sgonzo * are met:
12244197Sgonzo * 1. Redistributions of source code must retain the above copyright
13244197Sgonzo *    notice, this list of conditions and the following disclaimer.
14244197Sgonzo * 2. Redistributions in binary form must reproduce the above copyright
15244197Sgonzo *    notice, this list of conditions and the following disclaimer in the
16244197Sgonzo *    documentation and/or other materials provided with the distribution.
17244197Sgonzo * 3. Neither the name of the University nor the names of its contributors
18244197Sgonzo *    may be used to endorse or promote products derived from this software
19244197Sgonzo *    without specific prior written permission.
20244197Sgonzo *
21244197Sgonzo * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22244197Sgonzo * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23244197Sgonzo * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24244197Sgonzo * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25244197Sgonzo * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26244197Sgonzo * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27244197Sgonzo * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28244197Sgonzo * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29244197Sgonzo * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30244197Sgonzo * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31244197Sgonzo * SUCH DAMAGE.
32244197Sgonzo */
33244197Sgonzo#include "sh.h"
34244197Sgonzo
35244197SgonzoRCSID("$tcsh: sh.set.c,v 3.70 2006/08/24 20:56:31 christos Exp $")
36244197Sgonzo
37244197Sgonzo#include "ed.h"
38244197Sgonzo#include "tw.h"
39244197Sgonzo
40244197Sgonzo#ifdef HAVE_NL_LANGINFO
41244197Sgonzo#include <langinfo.h>
42244197Sgonzo#endif
43244197Sgonzo
44244197Sgonzoextern int GotTermCaps;
45244197Sgonzoint numeof = 0;
46244197Sgonzo
47244197Sgonzostatic	void		 update_vars	(Char *);
48244197Sgonzostatic	Char		*getinx		(Char *, int *);
49244197Sgonzostatic	void		 asx		(Char *, int, Char *);
50244197Sgonzostatic	struct varent 	*getvx		(Char *, int);
51244197Sgonzostatic	Char		*xset		(Char *, Char ***);
52244197Sgonzostatic	Char		*operate	(int, Char *, Char *);
53244197Sgonzostatic	void	 	 putn1		(unsigned);
54244197Sgonzostatic	struct varent	*madrof		(Char *, struct varent *);
55244197Sgonzostatic	void		 unsetv1	(struct varent *);
56244197Sgonzostatic	void		 exportpath	(Char **);
57244197Sgonzostatic	void		 balance	(struct varent *, int, int);
58244197Sgonzo
59244197Sgonzo/*
60244197Sgonzo * C Shell
61244197Sgonzo */
62244197Sgonzo
63244197Sgonzostatic void
64244197Sgonzoupdate_vars(Char *vp)
65244197Sgonzo{
66244197Sgonzo    if (eq(vp, STRpath)) {
67244197Sgonzo	struct varent *p = adrof(STRpath);
68244197Sgonzo	if (p == NULL)
69244197Sgonzo	    stderror(ERR_NAME | ERR_UNDVAR);
70244197Sgonzo	else {
71244197Sgonzo	    exportpath(p->vec);
72244197Sgonzo	    dohash(NULL, NULL);
73244197Sgonzo	}
74244197Sgonzo    }
75244197Sgonzo    else if (eq(vp, STRhistchars)) {
76244197Sgonzo	Char *pn = varval(vp);
77244197Sgonzo
78244197Sgonzo	HIST = *pn++;
79244197Sgonzo	HISTSUB = *pn;
80244197Sgonzo    }
81244197Sgonzo    else if (eq(vp, STRpromptchars)) {
82244197Sgonzo	Char *pn = varval(vp);
83244197Sgonzo
84244197Sgonzo	PRCH = *pn++;
85244197Sgonzo	PRCHROOT = *pn;
86244197Sgonzo    }
87244197Sgonzo    else if (eq(vp, STRhistlit)) {
88244197Sgonzo	HistLit = 1;
89244197Sgonzo    }
90244197Sgonzo    else if (eq(vp, STRuser)) {
91244197Sgonzo	tsetenv(STRKUSER, varval(vp));
92244197Sgonzo	tsetenv(STRLOGNAME, varval(vp));
93244197Sgonzo    }
94244197Sgonzo    else if (eq(vp, STRgroup)) {
95244197Sgonzo	tsetenv(STRKGROUP, varval(vp));
96244197Sgonzo    }
97244197Sgonzo    else if (eq(vp, STRwordchars)) {
98244197Sgonzo	word_chars = varval(vp);
99244197Sgonzo    }
100244197Sgonzo    else if (eq(vp, STRloginsh)) {
101244197Sgonzo	loginsh = 1;
102244197Sgonzo    }
103244197Sgonzo    else if (eq(vp, STRsymlinks)) {
104244197Sgonzo	Char *pn = varval(vp);
105244197Sgonzo
106244197Sgonzo	if (eq(pn, STRignore))
107244197Sgonzo	    symlinks = SYM_IGNORE;
108244197Sgonzo	else if (eq(pn, STRexpand))
109244197Sgonzo	    symlinks = SYM_EXPAND;
110244197Sgonzo	else if (eq(pn, STRchase))
111244197Sgonzo	    symlinks = SYM_CHASE;
112244197Sgonzo	else
113244197Sgonzo	    symlinks = 0;
114244197Sgonzo    }
115244197Sgonzo    else if (eq(vp, STRterm)) {
116244197Sgonzo	Char *cp = varval(vp);
117244197Sgonzo	tsetenv(STRKTERM, cp);
118244197Sgonzo#ifdef DOESNT_WORK_RIGHT
119244197Sgonzo	cp = getenv("TERMCAP");
120244197Sgonzo	if (cp && (*cp != '/'))	/* if TERMCAP and not a path */
121244197Sgonzo	    Unsetenv(STRTERMCAP);
122244197Sgonzo#endif /* DOESNT_WORK_RIGHT */
123244197Sgonzo	GotTermCaps = 0;
124244197Sgonzo	if (noediting && Strcmp(cp, STRnetwork) != 0 &&
125244197Sgonzo	    Strcmp(cp, STRunknown) != 0 && Strcmp(cp, STRdumb) != 0) {
126244197Sgonzo	    editing = 1;
127244197Sgonzo	    noediting = 0;
128244197Sgonzo	    setNS(STRedit);
129244197Sgonzo	}
130244197Sgonzo	ed_Init();		/* reset the editor */
131244197Sgonzo    }
132244197Sgonzo    else if (eq(vp, STRhome)) {
133244197Sgonzo	Char *cp, *canon;
134244197Sgonzo
135244197Sgonzo	cp = Strsave(varval(vp));	/* get the old value back */
136244197Sgonzo	cleanup_push(cp, xfree);
137244197Sgonzo
138244197Sgonzo	/*
139244197Sgonzo	 * convert to cononical pathname (possibly resolving symlinks)
140244197Sgonzo	 */
141244197Sgonzo	canon = dcanon(cp, cp);
142244197Sgonzo	cleanup_ignore(cp);
143244197Sgonzo	cleanup_until(cp);
144244197Sgonzo	cleanup_push(canon, xfree);
145266152Sian
146266152Sian	setcopy(vp, canon, VAR_READWRITE);	/* have to save the new val */
147266152Sian
148244197Sgonzo	/* and now mirror home with HOME */
149244197Sgonzo	tsetenv(STRKHOME, canon);
150244197Sgonzo	/* fix directory stack for new tilde home */
151244197Sgonzo	dtilde();
152244197Sgonzo	cleanup_until(canon);
153244197Sgonzo    }
154244197Sgonzo    else if (eq(vp, STRedit)) {
155244197Sgonzo	editing = 1;
156244197Sgonzo	noediting = 0;
157244197Sgonzo	/* PWP: add more stuff in here later */
158244197Sgonzo    }
159244197Sgonzo    else if (eq(vp, STRshlvl)) {
160244197Sgonzo	tsetenv(STRKSHLVL, varval(vp));
161244197Sgonzo    }
162244197Sgonzo    else if (eq(vp, STRignoreeof)) {
163244197Sgonzo	Char *cp;
164244197Sgonzo	numeof = 0;
165244197Sgonzo    	for ((cp = varval(STRignoreeof)); cp && *cp; cp++) {
166244197Sgonzo	    if (!Isdigit(*cp)) {
167244197Sgonzo		numeof = 0;
168244197Sgonzo		break;
169244197Sgonzo	    }
170244197Sgonzo	    numeof = numeof * 10 + *cp - '0';
171244197Sgonzo	}
172244197Sgonzo	if (numeof <= 0) numeof = 26;	/* Sanity check */
173244197Sgonzo    }
174244197Sgonzo    else if (eq(vp, STRbackslash_quote)) {
175244197Sgonzo	bslash_quote = 1;
176252395Sgonzo    }
177252395Sgonzo    else if (eq(vp, STRdirstack)) {
178252395Sgonzo	dsetstack();
179244197Sgonzo    }
180244197Sgonzo    else if (eq(vp, STRrecognize_only_executables)) {
181244197Sgonzo	tw_cmd_free();
182252395Sgonzo    }
183244197Sgonzo    else if (eq(vp, STRkillring)) {
184252395Sgonzo	SetKillRing(getn(varval(vp)));
185252395Sgonzo    }
186252395Sgonzo#ifndef HAVENOUTMP
187244197Sgonzo    else if (eq(vp, STRwatch)) {
188244197Sgonzo	resetwatch();
189244197Sgonzo    }
190244197Sgonzo#endif /* HAVENOUTMP */
191244197Sgonzo    else if (eq(vp, STRimplicitcd)) {
192244197Sgonzo	implicit_cd = ((eq(varval(vp), STRverbose)) ? 2 : 1);
193244197Sgonzo    }
194244197Sgonzo#ifdef COLOR_LS_F
195244197Sgonzo    else if (eq(vp, STRcolor)) {
196244197Sgonzo	set_color_context();
197244197Sgonzo    }
198244197Sgonzo#endif /* COLOR_LS_F */
199244197Sgonzo#if defined(KANJI) && defined(SHORT_STRINGS) && defined(DSPMBYTE)
200244197Sgonzo    else if(eq(vp, CHECK_MBYTEVAR) || eq(vp, STRnokanji)) {
201244197Sgonzo	update_dspmbyte_vars();
202244197Sgonzo    }
203244197Sgonzo#endif
204244197Sgonzo#ifdef NLS_CATALOGS
205244197Sgonzo    else if (eq(vp, STRcatalog)) {
206244197Sgonzo	nlsclose();
207244197Sgonzo	nlsinit();
208244197Sgonzo    }
209244197Sgonzo#if defined(FILEC) && defined(TIOCSTI)
210244197Sgonzo    else if (eq(vp, STRfilec))
211244197Sgonzo	filec = 1;
212244197Sgonzo#endif
213244197Sgonzo#endif /* NLS_CATALOGS */
214244197Sgonzo}
215244197Sgonzo
216244197Sgonzo
217244197Sgonzo/*ARGSUSED*/
218244197Sgonzovoid
219244197Sgonzodoset(Char **v, struct command *c)
220244197Sgonzo{
221244197Sgonzo    Char *p;
222244197Sgonzo    Char   *vp, op;
223244197Sgonzo    Char  **vecp;
224244197Sgonzo    int    hadsub;
225244197Sgonzo    int     subscr;
226244197Sgonzo    int	    flags = VAR_READWRITE;
227244197Sgonzo    int    first_match = 0;
228244197Sgonzo    int    last_match = 0;
229244197Sgonzo    int    changed = 0;
230244197Sgonzo
231244197Sgonzo    USE(c);
232244197Sgonzo    v++;
233244197Sgonzo    do {
234244197Sgonzo	changed = 0;
235244197Sgonzo	/*
236244197Sgonzo	 * Readonly addition From: Tim P. Starrin <noid@cyborg.larc.nasa.gov>
237244197Sgonzo	 */
238244197Sgonzo	if (*v && eq(*v, STRmr)) {
239244197Sgonzo	    flags = VAR_READONLY;
240244197Sgonzo	    v++;
241244197Sgonzo	    changed = 1;
242244197Sgonzo	}
243244197Sgonzo	if (*v && eq(*v, STRmf) && !last_match) {
244244197Sgonzo	    first_match = 1;
245244197Sgonzo	    v++;
246244197Sgonzo	    changed = 1;
247244197Sgonzo	}
248244197Sgonzo	if (*v && eq(*v, STRml) && !first_match) {
249244197Sgonzo	    last_match = 1;
250244197Sgonzo	    v++;
251244197Sgonzo	    changed = 1;
252244197Sgonzo	}
253244197Sgonzo    } while(changed);
254244197Sgonzo    p = *v++;
255244197Sgonzo    if (p == 0) {
256244197Sgonzo	plist(&shvhed, flags);
257244197Sgonzo	return;
258244197Sgonzo    }
259244197Sgonzo    do {
260244197Sgonzo	hadsub = 0;
261244197Sgonzo	vp = p;
262244197Sgonzo	if (letter(*p))
263244197Sgonzo	    for (; alnum(*p); p++)
264244197Sgonzo		continue;
265244197Sgonzo	if (vp == p || !letter(*vp))
266244197Sgonzo	    stderror(ERR_NAME | ERR_VARBEGIN);
267244197Sgonzo	if (*p == '[') {
268244197Sgonzo	    hadsub++;
269244197Sgonzo	    p = getinx(p, &subscr);
270244197Sgonzo	}
271244197Sgonzo	if ((op = *p) != 0) {
272244197Sgonzo	    *p++ = 0;
273244197Sgonzo	    if (*p == 0 && *v && **v == '(')
274244197Sgonzo		p = *v++;
275244197Sgonzo	}
276244197Sgonzo	else if (*v && eq(*v, STRequal)) {
277244197Sgonzo	    op = '=', v++;
278244197Sgonzo	    if (*v)
279244197Sgonzo		p = *v++;
280244197Sgonzo	}
281244197Sgonzo	if (op && op != '=')
282244197Sgonzo	    stderror(ERR_NAME | ERR_SYNTAX);
283244197Sgonzo	if (eq(p, STRLparen)) {
284244197Sgonzo	    Char **e = v;
285244197Sgonzo
286244197Sgonzo	    if (hadsub)
287244197Sgonzo		stderror(ERR_NAME | ERR_SYNTAX);
288244197Sgonzo	    for (;;) {
289244197Sgonzo		if (!*e)
290244197Sgonzo		    stderror(ERR_NAME | ERR_MISSING, ')');
291244197Sgonzo		if (**e == ')')
292244197Sgonzo		    break;
293244197Sgonzo		e++;
294244197Sgonzo	    }
295244197Sgonzo	    p = *e;
296244197Sgonzo	    *e = 0;
297244197Sgonzo	    vecp = saveblk(v);
298244197Sgonzo	    if (first_match)
299244197Sgonzo	       flags |= VAR_FIRST;
300244197Sgonzo	    else if (last_match)
301244197Sgonzo	       flags |= VAR_LAST;
302244197Sgonzo
303244197Sgonzo	    set1(vp, vecp, &shvhed, flags);
304244197Sgonzo	    *e = p;
305244197Sgonzo	    v = e + 1;
306244197Sgonzo	}
307244197Sgonzo	else if (hadsub) {
308244197Sgonzo	    Char *copy;
309244197Sgonzo
310244197Sgonzo	    copy = Strsave(p);
311252395Sgonzo	    cleanup_push(copy, xfree);
312244197Sgonzo	    asx(vp, subscr, copy);
313244197Sgonzo	    cleanup_ignore(copy);
314244197Sgonzo	    cleanup_until(copy);
315244197Sgonzo	}
316244197Sgonzo	else
317244197Sgonzo	    setv(vp, Strsave(p), flags);
318244197Sgonzo	update_vars(vp);
319244197Sgonzo    } while ((p = *v++) != NULL);
320244197Sgonzo}
321244197Sgonzo
322244197Sgonzostatic Char *
323244197Sgonzogetinx(Char *cp, int *ip)
324244197Sgonzo{
325244197Sgonzo    *ip = 0;
326244197Sgonzo    *cp++ = 0;
327244197Sgonzo    while (*cp && Isdigit(*cp))
328244197Sgonzo	*ip = *ip * 10 + *cp++ - '0';
329244197Sgonzo    if (*cp++ != ']')
330244197Sgonzo	stderror(ERR_NAME | ERR_SUBSCRIPT);
331244197Sgonzo    return (cp);
332244197Sgonzo}
333244197Sgonzo
334244197Sgonzostatic void
335244197Sgonzoasx(Char *vp, int subscr, Char *p)
336244197Sgonzo{
337244197Sgonzo    struct varent *v = getvx(vp, subscr);
338244197Sgonzo    Char *prev;
339244197Sgonzo
340244197Sgonzo    if (v->v_flags & VAR_READONLY)
341244197Sgonzo	stderror(ERR_READONLY|ERR_NAME, v->v_name);
342244197Sgonzo    prev = v->vec[subscr - 1];
343244197Sgonzo    cleanup_push(prev, xfree);
344244197Sgonzo    v->vec[subscr - 1] = globone(p, G_APPEND);
345244197Sgonzo    cleanup_until(prev);
346244197Sgonzo}
347244197Sgonzo
348252395Sgonzostatic struct varent *
349244197Sgonzogetvx(Char *vp, int subscr)
350252395Sgonzo{
351252395Sgonzo    struct varent *v = adrof(vp);
352252395Sgonzo
353252395Sgonzo    if (v == 0)
354252395Sgonzo	udvar(vp);
355252395Sgonzo    if (subscr < 1 || subscr > blklen(v->vec))
356278727Sian	stderror(ERR_NAME | ERR_RANGE);
357252395Sgonzo    return (v);
358252395Sgonzo}
359252395Sgonzo
360252395Sgonzo/*ARGSUSED*/
361252395Sgonzovoid
362252395Sgonzodolet(Char **v, struct command *dummy)
363256292Sdim{
364256292Sdim    Char *p;
365256292Sdim    Char   *vp, c, op;
366244197Sgonzo    int    hadsub;
367252395Sgonzo    int     subscr;
368244197Sgonzo
369244197Sgonzo    USE(dummy);
370244197Sgonzo    v++;
371244197Sgonzo    p = *v++;
372244197Sgonzo    if (p == 0) {
373244197Sgonzo	prvars();
374244197Sgonzo	return;
375244197Sgonzo    }
376244197Sgonzo    do {
377244197Sgonzo	hadsub = 0;
378244197Sgonzo	vp = p;
379244197Sgonzo	if (letter(*p))
380244197Sgonzo	    for (; alnum(*p); p++)
381244197Sgonzo		continue;
382244197Sgonzo	if (vp == p || !letter(*vp))
383244197Sgonzo	    stderror(ERR_NAME | ERR_VARBEGIN);
384244197Sgonzo	if (*p == '[') {
385244197Sgonzo	    hadsub++;
386244197Sgonzo	    p = getinx(p, &subscr);
387244197Sgonzo	}
388244197Sgonzo	if (*p == 0 && *v)
389244197Sgonzo	    p = *v++;
390244197Sgonzo	if ((op = *p) != 0)
391244197Sgonzo	    *p++ = 0;
392244197Sgonzo	else
393244197Sgonzo	    stderror(ERR_NAME | ERR_ASSIGN);
394244197Sgonzo
395244197Sgonzo	/*
396244197Sgonzo	 * if there is no expression after the '=' then print a "Syntax Error"
397244197Sgonzo	 * message - strike
398244197Sgonzo	 */
399244197Sgonzo	if (*p == '\0' && *v == NULL)
400244197Sgonzo	    stderror(ERR_NAME | ERR_ASSIGN);
401244197Sgonzo
402244197Sgonzo	vp = Strsave(vp);
403244197Sgonzo	cleanup_push(vp, xfree);
404244197Sgonzo	if (op == '=') {
405244197Sgonzo	    c = '=';
406244197Sgonzo	    p = xset(p, &v);
407244197Sgonzo	}
408244197Sgonzo	else {
409244197Sgonzo	    c = *p++;
410244197Sgonzo	    if (any("+-", c)) {
411244197Sgonzo		if (c != op || *p)
412244197Sgonzo		    stderror(ERR_NAME | ERR_UNKNOWNOP);
413244197Sgonzo		p = Strsave(STR1);
414244197Sgonzo	    }
415244197Sgonzo	    else {
416244197Sgonzo		if (any("<>", op)) {
417244197Sgonzo		    if (c != op)
418244197Sgonzo			stderror(ERR_NAME | ERR_UNKNOWNOP);
419244197Sgonzo		    stderror(ERR_NAME | ERR_SYNTAX);
420244197Sgonzo		}
421244197Sgonzo		if (c != '=')
422244197Sgonzo		    stderror(ERR_NAME | ERR_UNKNOWNOP);
423244197Sgonzo		p = xset(p, &v);
424244197Sgonzo	    }
425244197Sgonzo	}
426244197Sgonzo	cleanup_push(p, xfree);
427244197Sgonzo	if (op == '=') {
428244197Sgonzo	    if (hadsub)
429244197Sgonzo		asx(vp, subscr, p);
430244197Sgonzo	    else
431244197Sgonzo		setv(vp, p, VAR_READWRITE);
432244197Sgonzo	    cleanup_ignore(p);
433244197Sgonzo	}
434244197Sgonzo	else if (hadsub) {
435244197Sgonzo	    struct varent *gv = getvx(vp, subscr);
436244197Sgonzo	    Char *val;
437244197Sgonzo
438244197Sgonzo	    val = operate(op, gv->vec[subscr - 1], p);
439244197Sgonzo	    cleanup_push(val, xfree);
440244197Sgonzo	    asx(vp, subscr, val);
441244197Sgonzo	    cleanup_ignore(val);
442244197Sgonzo	    cleanup_until(val);
443244197Sgonzo	}
444244197Sgonzo	else {
445244197Sgonzo	    Char *val;
446244197Sgonzo
447244197Sgonzo	    val = operate(op, varval(vp), p);
448244197Sgonzo	    cleanup_push(val, xfree);
449244197Sgonzo	    setv(vp, val, VAR_READWRITE);
450244197Sgonzo	    cleanup_ignore(val);
451244197Sgonzo	    cleanup_until(val);
452244197Sgonzo	}
453244197Sgonzo	update_vars(vp);
454244197Sgonzo	cleanup_until(vp);
455244197Sgonzo    } while ((p = *v++) != NULL);
456244197Sgonzo}
457244197Sgonzo
458244197Sgonzostatic Char *
459244197Sgonzoxset(Char *cp, Char ***vp)
460244197Sgonzo{
461244197Sgonzo    Char *dp;
462244197Sgonzo
463244197Sgonzo    if (*cp) {
464244197Sgonzo	dp = Strsave(cp);
465244197Sgonzo	--(*vp);
466244197Sgonzo	xfree(** vp);
467244197Sgonzo	**vp = dp;
468244197Sgonzo    }
469244197Sgonzo    return (putn(expr(vp)));
470244197Sgonzo}
471244197Sgonzo
472244197Sgonzostatic Char *
473244197Sgonzooperate(int op, Char *vp, Char *p)
474244197Sgonzo{
475244197Sgonzo    Char    opr[2];
476244197Sgonzo    Char   *vec[5];
477244197Sgonzo    Char **v = vec;
478244197Sgonzo    Char  **vecp = v;
479244197Sgonzo    int i;
480244197Sgonzo
481244197Sgonzo    if (op != '=') {
482244197Sgonzo	if (*vp)
483244197Sgonzo	    *v++ = vp;
484244197Sgonzo	opr[0] = op;
485244197Sgonzo	opr[1] = 0;
486244197Sgonzo	*v++ = opr;
487244197Sgonzo	if (op == '<' || op == '>')
488244197Sgonzo	    *v++ = opr;
489244197Sgonzo    }
490244197Sgonzo    *v++ = p;
491244197Sgonzo    *v++ = 0;
492244197Sgonzo    i = expr(&vecp);
493244197Sgonzo    if (*vecp)
494244197Sgonzo	stderror(ERR_NAME | ERR_EXPRESSION);
495244197Sgonzo    return (putn(i));
496244197Sgonzo}
497244197Sgonzo
498244197Sgonzostatic Char *putp;
499244197Sgonzo
500244197SgonzoChar   *
501244197Sgonzoputn(int n)
502244197Sgonzo{
503244197Sgonzo    Char nbuf[(CHAR_BIT * sizeof (n) + 2) / 3 + 2]; /* Enough even for octal */
504244197Sgonzo
505244197Sgonzo    putp = nbuf;
506244197Sgonzo    if (n < 0) {
507244197Sgonzo	n = -n;
508244197Sgonzo	*putp++ = '-';
509244197Sgonzo    }
510244197Sgonzo    putn1(n);
511244197Sgonzo    *putp = 0;
512244197Sgonzo    return (Strsave(nbuf));
513244197Sgonzo}
514244197Sgonzo
515244197Sgonzostatic void
516244197Sgonzoputn1(unsigned n)
517244197Sgonzo{
518    if (n > 9)
519	putn1(n / 10);
520    *putp++ = n % 10 + '0';
521}
522
523int
524getn(Char *cp)
525{
526    int n;
527    int     sign;
528
529    if (!cp)			/* PWP: extra error checking */
530	stderror(ERR_NAME | ERR_BADNUM);
531
532    sign = 0;
533    if (cp[0] == '+' && cp[1])
534	cp++;
535    if (*cp == '-') {
536	sign++;
537	cp++;
538	if (!Isdigit(*cp))
539	    stderror(ERR_NAME | ERR_BADNUM);
540    }
541    n = 0;
542    while (Isdigit(*cp))
543	n = n * 10 + *cp++ - '0';
544    if (*cp)
545	stderror(ERR_NAME | ERR_BADNUM);
546    return (sign ? -n : n);
547}
548
549Char   *
550value1(Char *var, struct varent *head)
551{
552    struct varent *vp;
553
554    if (!var || !head)		/* PWP: extra error checking */
555	return (STRNULL);
556
557    vp = adrof1(var, head);
558    return ((vp == NULL || vp->vec == NULL || vp->vec[0] == NULL) ?
559	STRNULL : vp->vec[0]);
560}
561
562static struct varent *
563madrof(Char *pat, struct varent *vp)
564{
565    struct varent *vp1;
566
567    for (vp = vp->v_left; vp; vp = vp->v_right) {
568	if (vp->v_left && (vp1 = madrof(pat, vp)) != NULL)
569	    return vp1;
570	if (Gmatch(vp->v_name, pat))
571	    return vp;
572    }
573    return vp;
574}
575
576struct varent *
577adrof1(const Char *name, struct varent *v)
578{
579    int cmp;
580
581    v = v->v_left;
582    while (v && ((cmp = *name - *v->v_name) != 0 ||
583		 (cmp = Strcmp(name, v->v_name)) != 0))
584	if (cmp < 0)
585	    v = v->v_left;
586	else
587	    v = v->v_right;
588    return v;
589}
590
591void
592setcopy(const Char *var, const Char *val, int flags)
593{
594    Char *copy;
595
596    copy = Strsave(val);
597    cleanup_push(copy, xfree);
598    setv(var, copy, flags);
599    cleanup_ignore(copy);
600    cleanup_until(copy);
601}
602
603/*
604 * The caller is responsible for putting value in a safe place
605 */
606void
607setv(const Char *var, Char *val, int flags)
608{
609    Char **vec = xmalloc(2 * sizeof(Char **));
610
611    vec[0] = val;
612    vec[1] = 0;
613    set1(var, vec, &shvhed, flags);
614}
615
616void
617set1(const Char *var, Char **vec, struct varent *head, int flags)
618{
619    Char **oldv = vec;
620
621    if ((flags & VAR_NOGLOB) == 0) {
622	int gflag;
623
624	gflag = tglob(oldv);
625	if (gflag) {
626	    vec = globall(oldv, gflag);
627	    if (vec == 0) {
628		blkfree(oldv);
629		stderror(ERR_NAME | ERR_NOMATCH);
630	    }
631	    blkfree(oldv);
632	}
633    }
634    /*
635     * Uniqueness addition from: Michael Veksler <mveksler@vnet.ibm.com>
636     */
637    if ( flags & (VAR_FIRST | VAR_LAST) ) {
638	/*
639	 * Code for -f (VAR_FIRST) and -l (VAR_LAST) options.
640	 * Method:
641	 *  Delete all duplicate words leaving "holes" in the word array (vec).
642	 *  Then remove the "holes", keeping the order of the words unchanged.
643	 */
644	if (vec && vec[0] && vec[1]) { /* more than one word ? */
645	    int i, j;
646	    int num_items;
647
648	    for (num_items = 0; vec[num_items]; num_items++)
649	        continue;
650	    if (flags & VAR_FIRST) {
651		/* delete duplications, keeping first occurance */
652		for (i = 1; i < num_items; i++)
653		    for (j = 0; j < i; j++)
654			/* If have earlier identical item, remove i'th item */
655			if (vec[i] && vec[j] && Strcmp(vec[j], vec[i]) == 0) {
656			    xfree(vec[i]);
657			    vec[i] = NULL;
658			    break;
659			}
660	    } else if (flags & VAR_LAST) {
661	      /* delete duplications, keeping last occurance */
662		for (i = 0; i < num_items - 1; i++)
663		    for (j = i + 1; j < num_items; j++)
664			/* If have later identical item, remove i'th item */
665			if (vec[i] && vec[j] && Strcmp(vec[j], vec[i]) == 0) {
666			    /* remove identical item (the first) */
667			    xfree(vec[i]);
668			    vec[i] = NULL;
669			}
670	    }
671	    /* Compress items - remove empty items */
672	    for (j = i = 0; i < num_items; i++)
673	       if (vec[i])
674		  vec[j++] = vec[i];
675
676	    /* NULL-fy remaining items */
677	    for (; j < num_items; j++)
678		 vec[j] = NULL;
679	}
680	/* don't let the attribute propagate */
681	flags &= ~(VAR_FIRST|VAR_LAST);
682    }
683    setq(var, vec, head, flags);
684}
685
686
687void
688setq(const Char *name, Char **vec, struct varent *p, int flags)
689{
690    struct varent *c;
691    int f;
692
693    f = 0;			/* tree hangs off the header's left link */
694    while ((c = p->v_link[f]) != 0) {
695	if ((f = *name - *c->v_name) == 0 &&
696	    (f = Strcmp(name, c->v_name)) == 0) {
697	    if (c->v_flags & VAR_READONLY)
698		stderror(ERR_READONLY|ERR_NAME, c->v_name);
699	    blkfree(c->vec);
700	    c->v_flags = flags;
701	    trim(c->vec = vec);
702	    return;
703	}
704	p = c;
705	f = f > 0;
706    }
707    p->v_link[f] = c = xmalloc(sizeof(struct varent));
708    c->v_name = Strsave(name);
709    c->v_flags = flags;
710    c->v_bal = 0;
711    c->v_left = c->v_right = 0;
712    c->v_parent = p;
713    balance(p, f, 0);
714    trim(c->vec = vec);
715}
716
717/*ARGSUSED*/
718void
719unset(Char **v, struct command *c)
720{
721    int did_roe, did_edit;
722
723    USE(c);
724    did_roe = adrof(STRrecognize_only_executables) != NULL;
725    did_edit = adrof(STRedit) != NULL;
726    unset1(v, &shvhed);
727
728#if defined(FILEC) && defined(TIOCSTI)
729    if (adrof(STRfilec) == 0)
730	filec = 0;
731#endif /* FILEC && TIOCSTI */
732
733    if (adrof(STRhistchars) == 0) {
734	HIST = '!';
735	HISTSUB = '^';
736    }
737    if (adrof(STRignoreeof) == 0)
738	numeof = 0;
739    if (adrof(STRpromptchars) == 0) {
740	PRCH = '>';
741	PRCHROOT = '#';
742    }
743    if (adrof(STRhistlit) == 0)
744	HistLit = 0;
745    if (adrof(STRloginsh) == 0)
746	loginsh = 0;
747    if (adrof(STRwordchars) == 0)
748	word_chars = STR_WORD_CHARS;
749    if (adrof(STRedit) == 0)
750	editing = 0;
751    if (adrof(STRbackslash_quote) == 0)
752	bslash_quote = 0;
753    if (adrof(STRsymlinks) == 0)
754	symlinks = 0;
755    if (adrof(STRimplicitcd) == 0)
756	implicit_cd = 0;
757    if (adrof(STRkillring) == 0)
758	SetKillRing(0);
759    if (did_edit && noediting && adrof(STRedit) == 0)
760	noediting = 0;
761    if (did_roe && adrof(STRrecognize_only_executables) == 0)
762	tw_cmd_free();
763#ifdef COLOR_LS_F
764    if (adrof(STRcolor) == 0)
765	set_color_context();
766#endif /* COLOR_LS_F */
767#if defined(KANJI) && defined(SHORT_STRINGS) && defined(DSPMBYTE)
768    update_dspmbyte_vars();
769#endif
770#ifdef NLS_CATALOGS
771    nlsclose();
772    nlsinit();
773#endif /* NLS_CATALOGS */
774}
775
776void
777unset1(Char *v[], struct varent *head)
778{
779    struct varent *vp;
780    int cnt;
781
782    while (*++v) {
783	cnt = 0;
784	while ((vp = madrof(*v, head)) != NULL)
785	    if (vp->v_flags & VAR_READONLY)
786		stderror(ERR_READONLY|ERR_NAME, vp->v_name);
787	    else
788		unsetv1(vp), cnt++;
789	if (cnt == 0)
790	    setname(short2str(*v));
791    }
792}
793
794void
795unsetv(Char *var)
796{
797    struct varent *vp;
798
799    if ((vp = adrof1(var, &shvhed)) == 0)
800	udvar(var);
801    unsetv1(vp);
802}
803
804static void
805unsetv1(struct varent *p)
806{
807    struct varent *c, *pp;
808    int f;
809
810    /*
811     * Free associated memory first to avoid complications.
812     */
813    blkfree(p->vec);
814    xfree(p->v_name);
815    /*
816     * If p is missing one child, then we can move the other into where p is.
817     * Otherwise, we find the predecessor of p, which is guaranteed to have no
818     * right child, copy it into p, and move it's left child into it.
819     */
820    if (p->v_right == 0)
821	c = p->v_left;
822    else if (p->v_left == 0)
823	c = p->v_right;
824    else {
825	for (c = p->v_left; c->v_right; c = c->v_right)
826	    continue;
827	p->v_name = c->v_name;
828	p->v_flags = c->v_flags;
829	p->vec = c->vec;
830	p = c;
831	c = p->v_left;
832    }
833
834    /*
835     * Move c into where p is.
836     */
837    pp = p->v_parent;
838    f = pp->v_right == p;
839    if ((pp->v_link[f] = c) != 0)
840	c->v_parent = pp;
841    /*
842     * Free the deleted node, and rebalance.
843     */
844    xfree(p);
845    balance(pp, f, 1);
846}
847
848void
849setNS(Char *cp)
850{
851    setcopy(cp, STRNULL, VAR_READWRITE);
852}
853
854/*ARGSUSED*/
855void
856shift(Char **v, struct command *c)
857{
858    struct varent *argv;
859    Char *name;
860
861    USE(c);
862    v++;
863    name = *v;
864    if (name == 0)
865	name = STRargv;
866    else
867	(void) strip(name);
868    argv = adrof(name);
869    if (argv == NULL || argv->vec == NULL)
870	udvar(name);
871    if (argv->vec[0] == 0)
872	stderror(ERR_NAME | ERR_NOMORE);
873    lshift(argv->vec, 1);
874    update_vars(name);
875}
876
877static void
878exportpath(Char **val)
879{
880    struct Strbuf buf = Strbuf_INIT;
881    Char    	*exppath;
882
883    if (val)
884	while (*val) {
885	    Strbuf_append(&buf, *val++);
886	    if (*val == 0 || eq(*val, STRRparen))
887		break;
888	    Strbuf_append1(&buf, PATHSEP);
889	}
890    exppath = Strbuf_finish(&buf);
891    cleanup_push(exppath, xfree);
892    tsetenv(STRKPATH, exppath);
893    cleanup_until(exppath);
894}
895
896#ifndef lint
897 /*
898  * Lint thinks these have null effect
899  */
900 /* macros to do single rotations on node p */
901# define rright(p) (\
902	t = (p)->v_left,\
903	(t)->v_parent = (p)->v_parent,\
904	(((p)->v_left = t->v_right) != NULL) ?\
905	    (t->v_right->v_parent = (p)) : 0,\
906	(t->v_right = (p))->v_parent = t,\
907	(p) = t)
908# define rleft(p) (\
909	t = (p)->v_right,\
910	((t)->v_parent = (p)->v_parent,\
911	((p)->v_right = t->v_left) != NULL) ? \
912		(t->v_left->v_parent = (p)) : 0,\
913	(t->v_left = (p))->v_parent = t,\
914	(p) = t)
915#else
916static struct varent *
917rleft(struct varent *p)
918{
919    return (p);
920}
921static struct varent *
922rright(struct varent *p)
923{
924    return (p);
925}
926
927#endif /* ! lint */
928
929
930/*
931 * Rebalance a tree, starting at p and up.
932 * F == 0 means we've come from p's left child.
933 * D == 1 means we've just done a delete, otherwise an insert.
934 */
935static void
936balance(struct varent *p, int f, int d)
937{
938    struct varent *pp;
939
940#ifndef lint
941    struct varent *t;	/* used by the rotate macros */
942#endif /* !lint */
943    int ff;
944#ifdef lint
945    ff = 0;	/* Sun's lint is dumb! */
946#endif
947
948    /*
949     * Ok, from here on, p is the node we're operating on; pp is it's parent; f
950     * is the branch of p from which we have come; ff is the branch of pp which
951     * is p.
952     */
953    for (; (pp = p->v_parent) != 0; p = pp, f = ff) {
954	ff = pp->v_right == p;
955	if (f ^ d) {		/* right heavy */
956	    switch (p->v_bal) {
957	    case -1:		/* was left heavy */
958		p->v_bal = 0;
959		break;
960	    case 0:		/* was balanced */
961		p->v_bal = 1;
962		break;
963	    case 1:		/* was already right heavy */
964		switch (p->v_right->v_bal) {
965		case 1:	/* single rotate */
966		    pp->v_link[ff] = rleft(p);
967		    p->v_left->v_bal = 0;
968		    p->v_bal = 0;
969		    break;
970		case 0:	/* single rotate */
971		    pp->v_link[ff] = rleft(p);
972		    p->v_left->v_bal = 1;
973		    p->v_bal = -1;
974		    break;
975		case -1:	/* double rotate */
976		    (void) rright(p->v_right);
977		    pp->v_link[ff] = rleft(p);
978		    p->v_left->v_bal =
979			p->v_bal < 1 ? 0 : -1;
980		    p->v_right->v_bal =
981			p->v_bal > -1 ? 0 : 1;
982		    p->v_bal = 0;
983		    break;
984		default:
985		    break;
986		}
987		break;
988	    default:
989		break;
990	    }
991	}
992	else {			/* left heavy */
993	    switch (p->v_bal) {
994	    case 1:		/* was right heavy */
995		p->v_bal = 0;
996		break;
997	    case 0:		/* was balanced */
998		p->v_bal = -1;
999		break;
1000	    case -1:		/* was already left heavy */
1001		switch (p->v_left->v_bal) {
1002		case -1:	/* single rotate */
1003		    pp->v_link[ff] = rright(p);
1004		    p->v_right->v_bal = 0;
1005		    p->v_bal = 0;
1006		    break;
1007		case 0:	/* single rotate */
1008		    pp->v_link[ff] = rright(p);
1009		    p->v_right->v_bal = -1;
1010		    p->v_bal = 1;
1011		    break;
1012		case 1:	/* double rotate */
1013		    (void) rleft(p->v_left);
1014		    pp->v_link[ff] = rright(p);
1015		    p->v_left->v_bal =
1016			p->v_bal < 1 ? 0 : -1;
1017		    p->v_right->v_bal =
1018			p->v_bal > -1 ? 0 : 1;
1019		    p->v_bal = 0;
1020		    break;
1021		default:
1022		    break;
1023		}
1024		break;
1025	    default:
1026		break;
1027	    }
1028	}
1029	/*
1030	 * If from insert, then we terminate when p is balanced. If from
1031	 * delete, then we terminate when p is unbalanced.
1032	 */
1033	if ((p->v_bal == 0) ^ d)
1034	    break;
1035    }
1036}
1037
1038void
1039plist(struct varent *p, int what)
1040{
1041    struct varent *c;
1042    int len;
1043
1044    for (;;) {
1045	while (p->v_left)
1046	    p = p->v_left;
1047x:
1048	if (p->v_parent == 0)	/* is it the header? */
1049	    break;
1050	if ((p->v_flags & what) != 0) {
1051	    if (setintr) {
1052		int old_pintr_disabled;
1053
1054		pintr_push_enable(&old_pintr_disabled);
1055		cleanup_until(&old_pintr_disabled);
1056	    }
1057	    len = blklen(p->vec);
1058	    xprintf("%S\t", p->v_name);
1059	    if (len != 1)
1060		xputchar('(');
1061	    blkpr(p->vec);
1062	    if (len != 1)
1063		xputchar(')');
1064	    xputchar('\n');
1065	}
1066	if (p->v_right) {
1067	    p = p->v_right;
1068	    continue;
1069	}
1070	do {
1071	    c = p;
1072	    p = p->v_parent;
1073	} while (p->v_right == c);
1074	goto x;
1075    }
1076}
1077
1078#if defined(KANJI) && defined(SHORT_STRINGS) && defined(DSPMBYTE)
1079extern int dspmbyte_ls;
1080
1081void
1082update_dspmbyte_vars(void)
1083{
1084    int lp, iskcode;
1085    Char *dstr1;
1086    struct varent *vp;
1087
1088    /* if variable "nokanji" is set, multi-byte display is disabled */
1089    if ((vp = adrof(CHECK_MBYTEVAR)) && !adrof(STRnokanji)) {
1090	_enable_mbdisp = 1;
1091	dstr1 = vp->vec[0];
1092	if(eq (dstr1, STRsjis))
1093	    iskcode = 1;
1094	else if (eq(dstr1, STReuc))
1095	    iskcode = 2;
1096	else if (eq(dstr1, STRbig5))
1097	    iskcode = 3;
1098	else if (eq(dstr1, STRutf8))
1099	    iskcode = 4;
1100	else if ((dstr1[0] - '0') >= 0 && (dstr1[0] - '0') <= 3) {
1101	    iskcode = 0;
1102	}
1103	else {
1104	    xprintf(CGETS(18, 2,
1105	       "Warning: unknown multibyte display; using default(euc(JP))\n"));
1106	    iskcode = 2;
1107	}
1108	if (dstr1 && vp->vec[1] && eq(vp->vec[1], STRls))
1109	  dspmbyte_ls = 1;
1110	else
1111	  dspmbyte_ls = 0;
1112	for (lp = 0; lp < 256 && iskcode > 0; lp++) {
1113	    switch (iskcode) {
1114	    case 1:
1115		/* Shift-JIS */
1116		_cmap[lp] = _cmap_mbyte[lp];
1117		_mbmap[lp] = _mbmap_sjis[lp];
1118		break;
1119	    case 2:
1120		/* 2 ... euc */
1121		_cmap[lp] = _cmap_mbyte[lp];
1122		_mbmap[lp] = _mbmap_euc[lp];
1123		break;
1124	    case 3:
1125		/* 3 ... big5 */
1126		_cmap[lp] = _cmap_mbyte[lp];
1127		_mbmap[lp] = _mbmap_big5[lp];
1128		break;
1129	    case 4:
1130		/* 4 ... utf8 */
1131		_cmap[lp] = _cmap_mbyte[lp];
1132		_mbmap[lp] = _mbmap_utf8[lp];
1133		break;
1134	    default:
1135		xprintf(CGETS(18, 3,
1136		    "Warning: unknown multibyte code %d; multibyte disabled\n"),
1137		    iskcode);
1138		_cmap[lp] = _cmap_c[lp];
1139		_mbmap[lp] = 0;	/* Default map all 0 */
1140		_enable_mbdisp = 0;
1141		break;
1142	    }
1143	}
1144	if (iskcode == 0) {
1145	    /* check original table */
1146	    if (Strlen(dstr1) != 256) {
1147		xprintf(CGETS(18, 4,
1148       "Warning: Invalid multibyte table length (%d); multibyte disabled\n"),
1149		    Strlen(dstr1));
1150		_enable_mbdisp = 0;
1151	    }
1152	    for (lp = 0; lp < 256 && _enable_mbdisp == 1; lp++) {
1153		if (!((dstr1[lp] - '0') >= 0 && (dstr1[lp] - '0') <= 3)) {
1154		    xprintf(CGETS(18, 4,
1155	   "Warning: bad multibyte code at offset +%d; multibyte diabled\n"),
1156			lp);
1157		    _enable_mbdisp = 0;
1158		    break;
1159		}
1160	    }
1161	    /* set original table */
1162	    for (lp = 0; lp < 256; lp++) {
1163		if (_enable_mbdisp == 1) {
1164		    _cmap[lp] = _cmap_mbyte[lp];
1165		    _mbmap[lp] = (unsigned short) ((dstr1[lp] - '0') & 0x0f);
1166		}
1167		else {
1168		    _cmap[lp] = _cmap_c[lp];
1169		    _mbmap[lp] = 0;	/* Default map all 0 */
1170		}
1171	    }
1172	}
1173    }
1174    else {
1175	for (lp = 0; lp < 256; lp++) {
1176	    _cmap[lp] = _cmap_c[lp];
1177	    _mbmap[lp] = 0;	/* Default map all 0 */
1178	}
1179	_enable_mbdisp = 0;
1180	dspmbyte_ls = 0;
1181    }
1182#ifdef MBYTEDEBUG	/* Sorry, use for beta testing */
1183    {
1184	Char mbmapstr[300];
1185	for (lp = 0; lp < 256; lp++)
1186	    mbmapstr[lp] = _mbmap[lp] + '0';
1187	mbmapstr[lp] = 0;
1188	setcopy(STRmbytemap, mbmapstr, VAR_READWRITE);
1189    }
1190#endif /* MBYTEMAP */
1191}
1192
1193/* dspkanji/dspmbyte autosetting */
1194/* PATCH IDEA FROM Issei.Suzuki VERY THANKS */
1195void
1196autoset_dspmbyte(const Char *pcp)
1197{
1198    int i;
1199    static const struct dspm_autoset_Table {
1200	Char *n;
1201	Char *v;
1202    } dspmt[] = {
1203	{ STRLANGEUCJP, STReuc },
1204	{ STRLANGEUCKR, STReuc },
1205	{ STRLANGEUCZH, STReuc },
1206	{ STRLANGEUCJPB, STReuc },
1207	{ STRLANGEUCKRB, STReuc },
1208	{ STRLANGEUCZHB, STReuc },
1209#ifdef linux
1210	{ STRLANGEUCJPC, STReuc },
1211#endif
1212	{ STRLANGSJIS, STRsjis },
1213	{ STRLANGSJISB, STRsjis },
1214	{ STRLANGBIG5, STRbig5 },
1215	{ STRstarutfstar8, STRutf8 },
1216	{ NULL, NULL }
1217    };
1218#if defined(HAVE_NL_LANGINFO) && defined(CODESET)
1219    static const struct dspm_autoset_Table dspmc[] = {
1220	{ STRstarutfstar8, STRutf8 },
1221	{ STReuc, STReuc },
1222	{ STRGB2312, STReuc },
1223	{ STRLANGBIG5, STRbig5 },
1224	{ NULL, NULL }
1225    };
1226    Char *codeset;
1227
1228    codeset = str2short(nl_langinfo(CODESET));
1229    if (*codeset != '\0') {
1230	for (i = 0; dspmc[i].n; i++) {
1231	    const Char *estr;
1232	    if (dspmc[i].n[0] && t_pmatch(pcp, dspmc[i].n, &estr, 0) > 0) {
1233		setcopy(CHECK_MBYTEVAR, dspmc[i].v, VAR_READWRITE);
1234		update_dspmbyte_vars();
1235		return;
1236	    }
1237	}
1238    }
1239#endif
1240
1241    if (*pcp == '\0')
1242	return;
1243
1244    for (i = 0; dspmt[i].n; i++) {
1245	const Char *estr;
1246	if (dspmt[i].n[0] && t_pmatch(pcp, dspmt[i].n, &estr, 0) > 0) {
1247	    setcopy(CHECK_MBYTEVAR, dspmt[i].v, VAR_READWRITE);
1248	    update_dspmbyte_vars();
1249	    break;
1250	}
1251    }
1252}
1253#endif
1254