Deleted Added
full compact
sh.set.c (83098) sh.set.c (90446)
1/* $Header: /src/pub/tcsh/sh.set.c,v 3.39 2001/03/18 19:06:30 christos Exp $ */
2/*
3 * sh.set.c: Setting and Clearing of variables
4 */
5/*-
6 * Copyright (c) 1980, 1991 The Regents of the University of California.
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This product includes software developed by the University of
20 * California, Berkeley and its contributors.
21 * 4. Neither the name of the University nor the names of its contributors
22 * may be used to endorse or promote products derived from this software
23 * without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * SUCH DAMAGE.
36 */
37#include "sh.h"
38
39RCSID("$Id: sh.set.c,v 3.39 2001/03/18 19:06:30 christos Exp $")
40
41#include "ed.h"
42#include "tw.h"
43
44extern Char HistLit;
45extern bool GotTermCaps;
46
47static void update_vars __P((Char *));
48static Char *getinx __P((Char *, int *));
49static void asx __P((Char *, int, Char *));
50static struct varent *getvx __P((Char *, int));
51static Char *xset __P((Char *, Char ***));
52static Char *operate __P((int, Char *, Char *));
53static void putn1 __P((int));
54static struct varent *madrof __P((Char *, struct varent *));
55static void unsetv1 __P((struct varent *));
56static void exportpath __P((Char **));
57static void balance __P((struct varent *, int, int));
58
59/*
60 * C Shell
61 */
62
63static void
64update_vars(vp)
65 Char *vp;
66{
67 if (eq(vp, STRpath)) {
68 exportpath(adrof(STRpath)->vec);
69 dohash(NULL, NULL);
70 }
71 else if (eq(vp, STRhistchars)) {
72 register Char *pn = varval(vp);
73
74 HIST = *pn++;
75 HISTSUB = *pn;
76 }
77 else if (eq(vp, STRpromptchars)) {
78 register Char *pn = varval(vp);
79
80 PRCH = *pn++;
81 PRCHROOT = *pn;
82 }
83 else if (eq(vp, STRhistlit)) {
84 HistLit = 1;
85 }
86 else if (eq(vp, STRuser)) {
87 tsetenv(STRKUSER, varval(vp));
88 tsetenv(STRLOGNAME, varval(vp));
89 }
90 else if (eq(vp, STRgroup)) {
91 tsetenv(STRKGROUP, varval(vp));
92 }
93 else if (eq(vp, STRwordchars)) {
94 word_chars = varval(vp);
95 }
96 else if (eq(vp, STRloginsh)) {
97 loginsh = 1;
98 }
99 else if (eq(vp, STRsymlinks)) {
100 register Char *pn = varval(vp);
101
102 if (eq(pn, STRignore))
103 symlinks = SYM_IGNORE;
104 else if (eq(pn, STRexpand))
105 symlinks = SYM_EXPAND;
106 else if (eq(pn, STRchase))
107 symlinks = SYM_CHASE;
108 else
109 symlinks = 0;
110 }
111 else if (eq(vp, STRterm)) {
112 Char *cp = varval(vp);
113 tsetenv(STRKTERM, cp);
114#ifdef DOESNT_WORK_RIGHT
115 cp = getenv("TERMCAP");
116 if (cp && (*cp != '/')) /* if TERMCAP and not a path */
117 Unsetenv(STRTERMCAP);
118#endif /* DOESNT_WORK_RIGHT */
119 GotTermCaps = 0;
120 if (noediting && Strcmp(cp, STRnetwork) != 0 &&
121 Strcmp(cp, STRunknown) != 0 && Strcmp(cp, STRdumb) != 0) {
122 editing = 1;
123 noediting = 0;
124 set(STRedit, Strsave(STRNULL), VAR_READWRITE);
125 }
126 ed_Init(); /* reset the editor */
127 }
128 else if (eq(vp, STRhome)) {
129 register Char *cp;
130
131 cp = Strsave(varval(vp)); /* get the old value back */
132
133 /*
134 * convert to cononical pathname (possibly resolving symlinks)
135 */
136 cp = dcanon(cp, cp);
137
138 set(vp, Strsave(cp), VAR_READWRITE); /* have to save the new val */
139
140 /* and now mirror home with HOME */
141 tsetenv(STRKHOME, cp);
142 /* fix directory stack for new tilde home */
143 dtilde();
144 xfree((ptr_t) cp);
145 }
146 else if (eq(vp, STRedit)) {
147 editing = 1;
148 noediting = 0;
149 /* PWP: add more stuff in here later */
150 }
151 else if (eq(vp, STRshlvl)) {
152 tsetenv(STRKSHLVL, varval(vp));
153 }
154 else if (eq(vp, STRbackslash_quote)) {
155 bslash_quote = 1;
156 }
157 else if (eq(vp, STRdirstack)) {
158 dsetstack();
159 }
160 else if (eq(vp, STRrecognize_only_executables)) {
161 tw_cmd_free();
162 }
163 else if (eq(vp, STRkillring)) {
164 SetKillRing(getn(varval(vp)));
165 }
166#ifndef HAVENOUTMP
167 else if (eq(vp, STRwatch)) {
168 resetwatch();
169 }
170#endif /* HAVENOUTMP */
171 else if (eq(vp, STRimplicitcd)) {
172 implicit_cd = ((eq(varval(vp), STRverbose)) ? 2 : 1);
173 }
174#ifdef COLOR_LS_F
175 else if (eq(vp, STRcolor)) {
176 set_color_context();
177 }
178#endif /* COLOR_LS_F */
179#if defined(KANJI) && defined(SHORT_STRINGS) && defined(DSPMBYTE)
180 else if(eq(vp, CHECK_MBYTEVAR) || eq(vp, STRnokanji)) {
181 update_dspmbyte_vars();
182 }
183#endif
184#ifdef NLS_CATALOGS
185 else if (eq(vp, STRcatalog)) {
186 (void) catclose(catd);
187 nlsinit();
188 }
189#endif /* NLS_CATALOGS */
190}
191
192
193/*ARGSUSED*/
194void
195doset(v, c)
196 register Char **v;
197 struct command *c;
198{
199 register Char *p;
200 Char *vp, op;
201 Char **vecp;
202 bool hadsub;
203 int subscr;
204 int flags = VAR_READWRITE;
205 bool first_match = 0;
206 bool last_match = 0;
207 bool changed = 0;
208
209 USE(c);
210 v++;
211 do {
212 changed = 0;
213 /*
214 * Readonly addition From: Tim P. Starrin <noid@cyborg.larc.nasa.gov>
215 */
216 if (*v && eq(*v, STRmr)) {
217 flags = VAR_READONLY;
218 v++;
219 changed = 1;
220 }
221 if (*v && eq(*v, STRmf) && !last_match) {
222 first_match = 1;
223 v++;
224 changed = 1;
225 }
226 if (*v && eq(*v, STRml) && !first_match) {
227 last_match = 1;
228 v++;
229 changed = 1;
230 }
231 } while(changed);
232 p = *v++;
233 if (p == 0) {
234 plist(&shvhed, flags);
235 return;
236 }
237 do {
238 hadsub = 0;
239 vp = p;
240 if (letter(*p))
241 for (; alnum(*p); p++)
242 continue;
243 if (vp == p || !letter(*vp))
244 stderror(ERR_NAME | ERR_VARBEGIN);
245 if ((p - vp) > MAXVARLEN) {
246 stderror(ERR_NAME | ERR_VARTOOLONG);
247 return;
248 }
249 if (*p == '[') {
250 hadsub++;
251 p = getinx(p, &subscr);
252 }
253 if ((op = *p) != 0) {
254 *p++ = 0;
255 if (*p == 0 && *v && **v == '(')
256 p = *v++;
257 }
258 else if (*v && eq(*v, STRequal)) {
259 op = '=', v++;
260 if (*v)
261 p = *v++;
262 }
263 if (op && op != '=')
264 stderror(ERR_NAME | ERR_SYNTAX);
265 if (eq(p, STRLparen)) {
266 register Char **e = v;
267
268 if (hadsub)
269 stderror(ERR_NAME | ERR_SYNTAX);
270 for (;;) {
271 if (!*e)
272 stderror(ERR_NAME | ERR_MISSING, ')');
273 if (**e == ')')
274 break;
275 e++;
276 }
277 p = *e;
278 *e = 0;
279 vecp = saveblk(v);
280 if (first_match)
281 flags |= VAR_FIRST;
282 else if (last_match)
283 flags |= VAR_LAST;
284
285 set1(vp, vecp, &shvhed, flags);
286 *e = p;
287 v = e + 1;
288 }
289 else if (hadsub)
290 asx(vp, subscr, Strsave(p));
291 else
292 set(vp, Strsave(p), flags);
293 update_vars(vp);
294 } while ((p = *v++) != NULL);
295}
296
297static Char *
298getinx(cp, ip)
299 register Char *cp;
300 register int *ip;
301{
302 *ip = 0;
303 *cp++ = 0;
304 while (*cp && Isdigit(*cp))
305 *ip = *ip * 10 + *cp++ - '0';
306 if (*cp++ != ']')
307 stderror(ERR_NAME | ERR_SUBSCRIPT);
308 return (cp);
309}
310
311static void
312asx(vp, subscr, p)
313 Char *vp;
314 int subscr;
315 Char *p;
316{
317 register struct varent *v = getvx(vp, subscr);
318
319 if (v->v_flags & VAR_READONLY)
320 stderror(ERR_READONLY|ERR_NAME, v->v_name);
321 xfree((ptr_t) v->vec[subscr - 1]);
322 v->vec[subscr - 1] = globone(p, G_APPEND);
323}
324
325static struct varent *
326getvx(vp, subscr)
327 Char *vp;
328 int subscr;
329{
330 register struct varent *v = adrof(vp);
331
332 if (v == 0)
333 udvar(vp);
334 if (subscr < 1 || subscr > blklen(v->vec))
335 stderror(ERR_NAME | ERR_RANGE);
336 return (v);
337}
338
339/*ARGSUSED*/
340void
341dolet(v, dummy)
342 Char **v;
343 struct command *dummy;
344{
345 register Char *p;
346 Char *vp, c, op;
347 bool hadsub;
348 int subscr;
349
350 USE(dummy);
351 v++;
352 p = *v++;
353 if (p == 0) {
354 prvars();
355 return;
356 }
357 do {
358 hadsub = 0;
359 vp = p;
360 if (letter(*p))
361 for (; alnum(*p); p++)
362 continue;
363 if (vp == p || !letter(*vp))
364 stderror(ERR_NAME | ERR_VARBEGIN);
365 if ((p - vp) > MAXVARLEN)
366 stderror(ERR_NAME | ERR_VARTOOLONG);
367 if (*p == '[') {
368 hadsub++;
369 p = getinx(p, &subscr);
370 }
371 if (*p == 0 && *v)
372 p = *v++;
373 if ((op = *p) != 0)
374 *p++ = 0;
375 else
376 stderror(ERR_NAME | ERR_ASSIGN);
377
378 /*
379 * if there is no expression after the '=' then print a "Syntax Error"
380 * message - strike
381 */
382 if (*p == '\0' && *v == NULL)
383 stderror(ERR_NAME | ERR_ASSIGN);
384
385 vp = Strsave(vp);
386 if (op == '=') {
387 c = '=';
388 p = xset(p, &v);
389 }
390 else {
391 c = *p++;
392 if (any("+-", c)) {
393 if (c != op || *p)
394 stderror(ERR_NAME | ERR_UNKNOWNOP);
395 p = Strsave(STR1);
396 }
397 else {
398 if (any("<>", op)) {
399 if (c != op)
400 stderror(ERR_NAME | ERR_UNKNOWNOP);
401 c = *p++;
402 stderror(ERR_NAME | ERR_SYNTAX);
403 }
404 if (c != '=')
405 stderror(ERR_NAME | ERR_UNKNOWNOP);
406 p = xset(p, &v);
407 }
408 }
409 if (op == '=') {
410 if (hadsub)
411 asx(vp, subscr, p);
412 else
413 set(vp, p, VAR_READWRITE);
414 }
415 else if (hadsub) {
416 struct varent *gv = getvx(vp, subscr);
417
418 asx(vp, subscr, operate(op, gv->vec[subscr - 1], p));
419 }
420 else
421 set(vp, operate(op, varval(vp), p), VAR_READWRITE);
422 update_vars(vp);
423 xfree((ptr_t) vp);
424 if (c != '=')
425 xfree((ptr_t) p);
426 } while ((p = *v++) != NULL);
427}
428
429static Char *
430xset(cp, vp)
431 Char *cp, ***vp;
432{
433 register Char *dp;
434
435 if (*cp) {
436 dp = Strsave(cp);
437 --(*vp);
438 xfree((ptr_t) ** vp);
439 **vp = dp;
440 }
441 return (putn(expr(vp)));
442}
443
444static Char *
445operate(op, vp, p)
446 int op;
447 Char *vp, *p;
448{
449 Char opr[2];
450 Char *vec[5];
451 register Char **v = vec;
452 Char **vecp = v;
453 register int i;
454
455 if (op != '=') {
456 if (*vp)
457 *v++ = vp;
458 opr[0] = (Char) op;
459 opr[1] = 0;
460 *v++ = opr;
461 if (op == '<' || op == '>')
462 *v++ = opr;
463 }
464 *v++ = p;
465 *v++ = 0;
466 i = expr(&vecp);
467 if (*vecp)
468 stderror(ERR_NAME | ERR_EXPRESSION);
469 return (putn(i));
470}
471
472static Char *putp, nbuf[50];
473
474Char *
475putn(n)
476 register int n;
477{
478 int num;
479
480 putp = nbuf;
481 if (n < 0) {
482 n = -n;
483 *putp++ = '-';
484 }
485 num = 2; /* confuse lint */
486 if (sizeof(int) == num && ((unsigned int) n) == 0x8000) {
487 *putp++ = '3';
488 n = 2768;
489#ifdef pdp11
490 }
491#else /* !pdp11 */
492 }
493 else {
494 num = 4; /* confuse lint */
495 if (sizeof(int) == num && ((unsigned int) n) == 0x80000000) {
496 *putp++ = '2';
497 n = 147483648;
498 }
499 }
500#endif /* pdp11 */
501 putn1(n);
502 *putp = 0;
503 return (Strsave(nbuf));
504}
505
506static void
507putn1(n)
508 register int n;
509{
510 if (n > 9)
511 putn1(n / 10);
512 *putp++ = n % 10 + '0';
513}
514
515int
516getn(cp)
517 register Char *cp;
518{
519 register int n;
520 int sign;
521
522 if (!cp) /* PWP: extra error checking */
523 stderror(ERR_NAME | ERR_BADNUM);
524
525 sign = 0;
526 if (cp[0] == '+' && cp[1])
527 cp++;
528 if (*cp == '-') {
529 sign++;
530 cp++;
531 if (!Isdigit(*cp))
532 stderror(ERR_NAME | ERR_BADNUM);
533 }
534 n = 0;
535 while (Isdigit(*cp))
536 n = n * 10 + *cp++ - '0';
537 if (*cp)
538 stderror(ERR_NAME | ERR_BADNUM);
539 return (sign ? -n : n);
540}
541
542Char *
543value1(var, head)
544 Char *var;
545 struct varent *head;
546{
547 register struct varent *vp;
548
549 if (!var || !head) /* PWP: extra error checking */
550 return (STRNULL);
551
552 vp = adrof1(var, head);
553 return (vp == 0 || vp->vec[0] == 0 ? STRNULL : vp->vec[0]);
554}
555
556static struct varent *
557madrof(pat, vp)
558 Char *pat;
559 register struct varent *vp;
560{
561 register struct varent *vp1;
562
563 for (vp = vp->v_left; vp; vp = vp->v_right) {
564 if (vp->v_left && (vp1 = madrof(pat, vp)) != NULL)
565 return vp1;
566 if (Gmatch(vp->v_name, pat))
567 return vp;
568 }
569 return vp;
570}
571
572struct varent *
573adrof1(name, v)
574 register Char *name;
575 register struct varent *v;
576{
577 int cmp;
578
579 v = v->v_left;
580 while (v && ((cmp = *name - *v->v_name) != 0 ||
581 (cmp = Strcmp(name, v->v_name)) != 0))
582 if (cmp < 0)
583 v = v->v_left;
584 else
585 v = v->v_right;
586 return v;
587}
588
589/*
590 * The caller is responsible for putting value in a safe place
591 */
592void
593set(var, val, flags)
594 Char *var, *val;
595 int flags;
596{
597 register Char **vec = (Char **) xmalloc((size_t) (2 * sizeof(Char **)));
598
599 vec[0] = val;
600 vec[1] = 0;
601 set1(var, vec, &shvhed, flags);
602}
603
604void
605set1(var, vec, head, flags)
606 Char *var, **vec;
607 struct varent *head;
608 int flags;
609{
610 register Char **oldv = vec;
611
612 if ((flags & VAR_NOGLOB) == 0) {
613 gflag = 0;
614 tglob(oldv);
615 if (gflag) {
616 vec = globall(oldv);
617 if (vec == 0) {
618 blkfree(oldv);
619 stderror(ERR_NAME | ERR_NOMATCH);
620 return;
621 }
622 blkfree(oldv);
623 gargv = 0;
624 }
625 }
626 /*
627 * Uniqueness addition from: Michael Veksler <mveksler@vnet.ibm.com>
628 */
629 if ( flags & (VAR_FIRST | VAR_LAST) ) {
630 /*
631 * Code for -f (VAR_FIRST) and -l (VAR_LAST) options.
632 * Method:
633 * Delete all duplicate words leaving "holes" in the word array (vec).
634 * Then remove the "holes", keeping the order of the words unchanged.
635 */
636 if (vec && vec[0] && vec[1]) { /* more than one word ? */
637 int i, j;
638 int num_items;
639
640 for (num_items = 0; vec[num_items]; num_items++)
641 continue;
642 if (flags & VAR_FIRST) {
643 /* delete duplications, keeping first occurance */
644 for (i = 1; i < num_items; i++)
645 for (j = 0; j < i; j++)
646 /* If have earlier identical item, remove i'th item */
647 if (vec[i] && vec[j] && Strcmp(vec[j], vec[i]) == 0) {
648 free(vec[i]);
649 vec[i] = NULL;
650 break;
651 }
652 } else if (flags & VAR_LAST) {
653 /* delete duplications, keeping last occurance */
654 for (i = 0; i < num_items - 1; i++)
655 for (j = i + 1; j < num_items; j++)
656 /* If have later identical item, remove i'th item */
657 if (vec[i] && vec[j] && Strcmp(vec[j], vec[i]) == 0) {
658 /* remove identical item (the first) */
659 free(vec[i]);
660 vec[i] = NULL;
661 }
662 }
663 /* Compress items - remove empty items */
664 for (j = i = 0; i < num_items; i++)
665 if (vec[i])
666 vec[j++] = vec[i];
667
668 /* NULL-fy remaining items */
669 for (; j < num_items; j++)
670 vec[j] = NULL;
671 }
672 /* don't let the attribute propagate */
673 flags &= ~(VAR_FIRST|VAR_LAST);
674 }
675 setq(var, vec, head, flags);
676}
677
678
679void
680setq(name, vec, p, flags)
681 Char *name, **vec;
682 register struct varent *p;
683 int flags;
684{
685 register struct varent *c;
686 register int f;
687
688 f = 0; /* tree hangs off the header's left link */
689 while ((c = p->v_link[f]) != 0) {
690 if ((f = *name - *c->v_name) == 0 &&
691 (f = Strcmp(name, c->v_name)) == 0) {
692 if (c->v_flags & VAR_READONLY)
693 stderror(ERR_READONLY|ERR_NAME, c->v_name);
694 blkfree(c->vec);
695 c->v_flags = flags;
696 trim(c->vec = vec);
697 return;
698 }
699 p = c;
700 f = f > 0;
701 }
702 p->v_link[f] = c = (struct varent *) xmalloc((size_t)sizeof(struct varent));
703 c->v_name = Strsave(name);
704 c->v_flags = flags;
705 c->v_bal = 0;
706 c->v_left = c->v_right = 0;
707 c->v_parent = p;
708 balance(p, f, 0);
709 trim(c->vec = vec);
710}
711
712/*ARGSUSED*/
713void
714unset(v, c)
715 Char **v;
716 struct command *c;
717{
718 bool did_roe, did_edit;
719
720 USE(c);
721 did_roe = adrof(STRrecognize_only_executables) != NULL;
722 did_edit = adrof(STRedit) != NULL;
723 unset1(v, &shvhed);
724 if (adrof(STRhistchars) == 0) {
725 HIST = '!';
726 HISTSUB = '^';
727 }
728 if (adrof(STRpromptchars) == 0) {
729 PRCH = '>';
730 PRCHROOT = '#';
731 }
732 if (adrof(STRhistlit) == 0)
733 HistLit = 0;
734 if (adrof(STRloginsh) == 0)
735 loginsh = 0;
736 if (adrof(STRwordchars) == 0)
737 word_chars = STR_WORD_CHARS;
738 if (adrof(STRedit) == 0)
739 editing = 0;
740 if (adrof(STRbackslash_quote) == 0)
741 bslash_quote = 0;
742 if (adrof(STRsymlinks) == 0)
743 symlinks = 0;
744 if (adrof(STRimplicitcd) == 0)
745 implicit_cd = 0;
746 if (adrof(STRkillring) == 0)
747 SetKillRing(0);
748 if (did_edit && noediting && adrof(STRedit) == 0)
749 noediting = 0;
750 if (did_roe && adrof(STRrecognize_only_executables) == 0)
751 tw_cmd_free();
752#ifdef COLOR_LS_F
753 if (adrof(STRcolor) == 0)
754 set_color_context();
755#endif /* COLOR_LS_F */
756#if defined(KANJI) && defined(SHORT_STRINGS) && defined(DSPMBYTE)
757 update_dspmbyte_vars();
758#endif
759#ifdef NLS_CATALOGS
760 (void) catclose(catd);
761 nlsinit();
762#endif /* NLS_CATALOGS */
763}
764
765void
766unset1(v, head)
767 register Char *v[];
768 struct varent *head;
769{
770 register struct varent *vp;
771 register int cnt;
772
773 while (*++v) {
774 cnt = 0;
775 while ((vp = madrof(*v, head)) != NULL)
776 if (vp->v_flags & VAR_READONLY)
777 stderror(ERR_READONLY|ERR_NAME, vp->v_name);
778 else
779 unsetv1(vp), cnt++;
780 if (cnt == 0)
781 setname(short2str(*v));
782 }
783}
784
785void
786unsetv(var)
787 Char *var;
788{
789 register struct varent *vp;
790
791 if ((vp = adrof1(var, &shvhed)) == 0)
792 udvar(var);
793 unsetv1(vp);
794}
795
796static void
797unsetv1(p)
798 register struct varent *p;
799{
800 register struct varent *c, *pp;
801 register int f;
802
803 /*
804 * Free associated memory first to avoid complications.
805 */
806 blkfree(p->vec);
807 xfree((ptr_t) p->v_name);
808 /*
809 * If p is missing one child, then we can move the other into where p is.
810 * Otherwise, we find the predecessor of p, which is guaranteed to have no
811 * right child, copy it into p, and move it's left child into it.
812 */
813 if (p->v_right == 0)
814 c = p->v_left;
815 else if (p->v_left == 0)
816 c = p->v_right;
817 else {
818 for (c = p->v_left; c->v_right; c = c->v_right)
819 continue;
820 p->v_name = c->v_name;
821 p->v_flags = c->v_flags;
822 p->vec = c->vec;
823 p = c;
824 c = p->v_left;
825 }
826
827 /*
828 * Move c into where p is.
829 */
830 pp = p->v_parent;
831 f = pp->v_right == p;
832 if ((pp->v_link[f] = c) != 0)
833 c->v_parent = pp;
834 /*
835 * Free the deleted node, and rebalance.
836 */
837 xfree((ptr_t) p);
838 balance(pp, f, 1);
839}
840
841void
842setNS(cp)
843 Char *cp;
844{
845 set(cp, Strsave(STRNULL), VAR_READWRITE);
846}
847
848/*ARGSUSED*/
849void
850shift(v, c)
851 register Char **v;
852 struct command *c;
853{
854 register struct varent *argv;
855 register Char *name;
856
857 USE(c);
858 v++;
859 name = *v;
860 if (name == 0)
861 name = STRargv;
862 else
863 (void) strip(name);
864 argv = adrof(name);
865 if (argv == 0)
866 udvar(name);
867 if (argv->vec[0] == 0)
868 stderror(ERR_NAME | ERR_NOMORE);
869 lshift(argv->vec, 1);
870 update_vars(name);
871}
872
873static Char STRsep[2] = { PATHSEP, '\0' };
874
875static void
876exportpath(val)
877 Char **val;
878{
879 Char *exppath;
880 size_t exppath_size = BUFSIZE;
881 exppath = (Char *)xmalloc(sizeof(Char)*exppath_size);
882
883 exppath[0] = 0;
884 if (val)
885 while (*val) {
886 while (Strlen(*val) + Strlen(exppath) + 2 > exppath_size) {
887 if ((exppath
888 = (Char *)xrealloc(exppath, sizeof(Char)*(exppath_size *= 2)))
889 == NULL) {
890 xprintf(CGETS(18, 1,
891 "Warning: ridiculously long PATH truncated\n"));
892 break;
893 }
894 }
895 (void) Strcat(exppath, *val++);
896 if (*val == 0 || eq(*val, STRRparen))
897 break;
898 (void) Strcat(exppath, STRsep);
899 }
900 tsetenv(STRKPATH, exppath);
901 free(exppath);
902}
903
904#ifndef lint
905 /*
906 * Lint thinks these have null effect
907 */
908 /* macros to do single rotations on node p */
909# define rright(p) (\
910 t = (p)->v_left,\
911 (t)->v_parent = (p)->v_parent,\
912 (((p)->v_left = t->v_right) != NULL) ?\
913 (t->v_right->v_parent = (p)) : 0,\
914 (t->v_right = (p))->v_parent = t,\
915 (p) = t)
916# define rleft(p) (\
917 t = (p)->v_right,\
918 ((t)->v_parent = (p)->v_parent,\
919 ((p)->v_right = t->v_left) != NULL) ? \
920 (t->v_left->v_parent = (p)) : 0,\
921 (t->v_left = (p))->v_parent = t,\
922 (p) = t)
923#else
924static struct varent *
925rleft(p)
926 struct varent *p;
927{
928 return (p);
929}
930static struct varent *
931rright(p)
932 struct varent *p;
933{
934 return (p);
935}
936
937#endif /* ! lint */
938
939
940/*
941 * Rebalance a tree, starting at p and up.
942 * F == 0 means we've come from p's left child.
943 * D == 1 means we've just done a delete, otherwise an insert.
944 */
945static void
946balance(p, f, d)
947 register struct varent *p;
948 register int f, d;
949{
950 register struct varent *pp;
951
952#ifndef lint
953 register struct varent *t; /* used by the rotate macros */
954#endif /* !lint */
955 register int ff;
956#ifdef lint
957 ff = 0; /* Sun's lint is dumb! */
958#endif
959
960 /*
961 * Ok, from here on, p is the node we're operating on; pp is it's parent; f
962 * is the branch of p from which we have come; ff is the branch of pp which
963 * is p.
964 */
965 for (; (pp = p->v_parent) != 0; p = pp, f = ff) {
966 ff = pp->v_right == p;
967 if (f ^ d) { /* right heavy */
968 switch (p->v_bal) {
969 case -1: /* was left heavy */
970 p->v_bal = 0;
971 break;
972 case 0: /* was balanced */
973 p->v_bal = 1;
974 break;
975 case 1: /* was already right heavy */
976 switch (p->v_right->v_bal) {
977 case 1: /* sigle rotate */
978 pp->v_link[ff] = rleft(p);
979 p->v_left->v_bal = 0;
980 p->v_bal = 0;
981 break;
982 case 0: /* single rotate */
983 pp->v_link[ff] = rleft(p);
984 p->v_left->v_bal = 1;
985 p->v_bal = -1;
986 break;
987 case -1: /* double rotate */
988 (void) rright(p->v_right);
989 pp->v_link[ff] = rleft(p);
990 p->v_left->v_bal =
991 p->v_bal < 1 ? 0 : -1;
992 p->v_right->v_bal =
993 p->v_bal > -1 ? 0 : 1;
994 p->v_bal = 0;
995 break;
996 default:
997 break;
998 }
999 break;
1000 default:
1001 break;
1002 }
1003 }
1004 else { /* left heavy */
1005 switch (p->v_bal) {
1006 case 1: /* was right heavy */
1007 p->v_bal = 0;
1008 break;
1009 case 0: /* was balanced */
1010 p->v_bal = -1;
1011 break;
1012 case -1: /* was already left heavy */
1013 switch (p->v_left->v_bal) {
1014 case -1: /* single rotate */
1015 pp->v_link[ff] = rright(p);
1016 p->v_right->v_bal = 0;
1017 p->v_bal = 0;
1018 break;
1019 case 0: /* signle rotate */
1020 pp->v_link[ff] = rright(p);
1021 p->v_right->v_bal = -1;
1022 p->v_bal = 1;
1023 break;
1024 case 1: /* double rotate */
1025 (void) rleft(p->v_left);
1026 pp->v_link[ff] = rright(p);
1027 p->v_left->v_bal =
1028 p->v_bal < 1 ? 0 : -1;
1029 p->v_right->v_bal =
1030 p->v_bal > -1 ? 0 : 1;
1031 p->v_bal = 0;
1032 break;
1033 default:
1034 break;
1035 }
1036 break;
1037 default:
1038 break;
1039 }
1040 }
1041 /*
1042 * If from insert, then we terminate when p is balanced. If from
1043 * delete, then we terminate when p is unbalanced.
1044 */
1045 if ((p->v_bal == 0) ^ d)
1046 break;
1047 }
1048}
1049
1050void
1051plist(p, what)
1052 register struct varent *p;
1053 int what;
1054{
1055 register struct varent *c;
1056 register int len;
1057
1058 if (setintr)
1059#ifdef BSDSIGS
1060 (void) sigsetmask(sigblock((sigmask_t) 0) & ~sigmask(SIGINT));
1061#else /* !BSDSIGS */
1062 (void) sigrelse(SIGINT);
1063#endif /* BSDSIGS */
1064
1065 for (;;) {
1066 while (p->v_left)
1067 p = p->v_left;
1068x:
1069 if (p->v_parent == 0) /* is it the header? */
1070 return;
1071 if ((p->v_flags & what) != 0) {
1072 len = blklen(p->vec);
1073 xprintf("%S\t", p->v_name);
1074 if (len != 1)
1075 xputchar('(');
1076 blkpr(p->vec);
1077 if (len != 1)
1078 xputchar(')');
1079 xputchar('\n');
1080 }
1081 if (p->v_right) {
1082 p = p->v_right;
1083 continue;
1084 }
1085 do {
1086 c = p;
1087 p = p->v_parent;
1088 } while (p->v_right == c);
1089 goto x;
1090 }
1091}
1092
1093#if defined(KANJI) && defined(SHORT_STRINGS) && defined(DSPMBYTE)
1094bool dspmbyte_ls;
1095
1096void
1097update_dspmbyte_vars()
1098{
1099 int lp, iskcode;
1100 Char *dstr1;
1101 struct varent *vp;
1102
1103 /* if variable "nokanji" is set, multi-byte display is disabled */
1104 if ((vp = adrof(CHECK_MBYTEVAR)) && !adrof(STRnokanji)) {
1105 _enable_mbdisp = 1;
1106 dstr1 = vp->vec[0];
1107 if(eq (dstr1, STRKSJIS))
1108 iskcode = 1;
1109 else if (eq(dstr1, STRKEUC))
1110 iskcode = 2;
1111 else if (eq(dstr1, STRKBIG5))
1112 iskcode = 3;
1113 else if ((dstr1[0] - '0') >= 0 && (dstr1[0] - '0') <= 3) {
1114 iskcode = 0;
1115 }
1116 else {
1117 xprintf(CGETS(18, 2,
1118 "Warning: unknown multibyte display; using default(euc(JP))\n"));
1119 iskcode = 2;
1120 }
1121 if (dstr1 && vp->vec[1] && eq(vp->vec[1], STRls))
1122 dspmbyte_ls = 1;
1123 else
1124 dspmbyte_ls = 0;
1125 for (lp = 0; lp < 256 && iskcode > 0; lp++) {
1126 switch (iskcode) {
1127 case 1:
1128 /* Shift-JIS */
1129 _cmap[lp] = _cmap_mbyte[lp];
1130 _mbmap[lp] = _mbmap_sjis[lp];
1131 break;
1132 case 2:
1133 /* 2 ... euc */
1134 _cmap[lp] = _cmap_mbyte[lp];
1135 _mbmap[lp] = _mbmap_euc[lp];
1136 break;
1137 case 3:
1138 /* 3 ... big5 */
1139 _cmap[lp] = _cmap_mbyte[lp];
1140 _mbmap[lp] = _mbmap_big5[lp];
1141 break;
1142 default:
1143 xprintf(CGETS(18, 3,
1144 "Warning: unknown multibyte code %d; multibyte disabled\n"),
1145 iskcode);
1146 _cmap[lp] = _cmap_c[lp];
1147 _mbmap[lp] = 0; /* Default map all 0 */
1148 _enable_mbdisp = 0;
1149 break;
1150 }
1151 }
1152 if (iskcode == 0) {
1153 /* check original table */
1154 if (Strlen(dstr1) != 256) {
1155 xprintf(CGETS(18, 4,
1156 "Warning: Invalid multibyte table length (%d); multibyte disabled\n"),
1157 Strlen(dstr1));
1158 _enable_mbdisp = 0;
1159 }
1160 for (lp = 0; lp < 256 && _enable_mbdisp == 1; lp++) {
1161 if (!((dstr1[lp] - '0') >= 0 && (dstr1[lp] - '0') <= 3)) {
1162 xprintf(CGETS(18, 4,
1163 "Warning: bad multibyte code at offset +%d; multibyte diabled\n"),
1164 lp);
1165 _enable_mbdisp = 0;
1166 break;
1167 }
1168 }
1169 /* set original table */
1170 for (lp = 0; lp < 256; lp++) {
1171 if (_enable_mbdisp == 1) {
1172 _cmap[lp] = _cmap_mbyte[lp];
1173 _mbmap[lp] = (unsigned short) ((dstr1[lp] - '0') & 0x0f);
1174 }
1175 else {
1176 _cmap[lp] = _cmap_c[lp];
1177 _mbmap[lp] = 0; /* Default map all 0 */
1178 }
1179 }
1180 }
1181 }
1182 else {
1183 for (lp = 0; lp < 256; lp++) {
1184 _cmap[lp] = _cmap_c[lp];
1185 _mbmap[lp] = 0; /* Default map all 0 */
1186 }
1187 _enable_mbdisp = 0;
1188 dspmbyte_ls = 0;
1189 }
1190#ifdef MBYTEDEBUG /* Sorry, use for beta testing */
1191 {
1192 Char mbmapstr[300];
1193 for (lp = 0; lp < 256; lp++) {
1194 mbmapstr[lp] = _mbmap[lp] + '0';
1195 mbmapstr[lp+1] = 0;
1196 }
1197 set(STRmbytemap, Strsave(mbmapstr), VAR_READWRITE);
1198 }
1199#endif /* MBYTEMAP */
1200}
1201
1202/* dspkanji/dspmbyte autosetting */
1203/* PATCH IDEA FROM Issei.Suzuki VERY THANKS */
1204void
1205autoset_dspmbyte(pcp)
1206 Char *pcp;
1207{
1208 int i;
1209 struct dspm_autoset_Table {
1210 Char *n;
1211 Char *v;
1212 } dspmt[] = {
1213 { STRLANGEUCJP, STRKEUC },
1214 { STRLANGEUCKR, STRKEUC },
1/* $Header: /src/pub/tcsh/sh.set.c,v 3.39 2001/03/18 19:06:30 christos Exp $ */
2/*
3 * sh.set.c: Setting and Clearing of variables
4 */
5/*-
6 * Copyright (c) 1980, 1991 The Regents of the University of California.
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This product includes software developed by the University of
20 * California, Berkeley and its contributors.
21 * 4. Neither the name of the University nor the names of its contributors
22 * may be used to endorse or promote products derived from this software
23 * without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * SUCH DAMAGE.
36 */
37#include "sh.h"
38
39RCSID("$Id: sh.set.c,v 3.39 2001/03/18 19:06:30 christos Exp $")
40
41#include "ed.h"
42#include "tw.h"
43
44extern Char HistLit;
45extern bool GotTermCaps;
46
47static void update_vars __P((Char *));
48static Char *getinx __P((Char *, int *));
49static void asx __P((Char *, int, Char *));
50static struct varent *getvx __P((Char *, int));
51static Char *xset __P((Char *, Char ***));
52static Char *operate __P((int, Char *, Char *));
53static void putn1 __P((int));
54static struct varent *madrof __P((Char *, struct varent *));
55static void unsetv1 __P((struct varent *));
56static void exportpath __P((Char **));
57static void balance __P((struct varent *, int, int));
58
59/*
60 * C Shell
61 */
62
63static void
64update_vars(vp)
65 Char *vp;
66{
67 if (eq(vp, STRpath)) {
68 exportpath(adrof(STRpath)->vec);
69 dohash(NULL, NULL);
70 }
71 else if (eq(vp, STRhistchars)) {
72 register Char *pn = varval(vp);
73
74 HIST = *pn++;
75 HISTSUB = *pn;
76 }
77 else if (eq(vp, STRpromptchars)) {
78 register Char *pn = varval(vp);
79
80 PRCH = *pn++;
81 PRCHROOT = *pn;
82 }
83 else if (eq(vp, STRhistlit)) {
84 HistLit = 1;
85 }
86 else if (eq(vp, STRuser)) {
87 tsetenv(STRKUSER, varval(vp));
88 tsetenv(STRLOGNAME, varval(vp));
89 }
90 else if (eq(vp, STRgroup)) {
91 tsetenv(STRKGROUP, varval(vp));
92 }
93 else if (eq(vp, STRwordchars)) {
94 word_chars = varval(vp);
95 }
96 else if (eq(vp, STRloginsh)) {
97 loginsh = 1;
98 }
99 else if (eq(vp, STRsymlinks)) {
100 register Char *pn = varval(vp);
101
102 if (eq(pn, STRignore))
103 symlinks = SYM_IGNORE;
104 else if (eq(pn, STRexpand))
105 symlinks = SYM_EXPAND;
106 else if (eq(pn, STRchase))
107 symlinks = SYM_CHASE;
108 else
109 symlinks = 0;
110 }
111 else if (eq(vp, STRterm)) {
112 Char *cp = varval(vp);
113 tsetenv(STRKTERM, cp);
114#ifdef DOESNT_WORK_RIGHT
115 cp = getenv("TERMCAP");
116 if (cp && (*cp != '/')) /* if TERMCAP and not a path */
117 Unsetenv(STRTERMCAP);
118#endif /* DOESNT_WORK_RIGHT */
119 GotTermCaps = 0;
120 if (noediting && Strcmp(cp, STRnetwork) != 0 &&
121 Strcmp(cp, STRunknown) != 0 && Strcmp(cp, STRdumb) != 0) {
122 editing = 1;
123 noediting = 0;
124 set(STRedit, Strsave(STRNULL), VAR_READWRITE);
125 }
126 ed_Init(); /* reset the editor */
127 }
128 else if (eq(vp, STRhome)) {
129 register Char *cp;
130
131 cp = Strsave(varval(vp)); /* get the old value back */
132
133 /*
134 * convert to cononical pathname (possibly resolving symlinks)
135 */
136 cp = dcanon(cp, cp);
137
138 set(vp, Strsave(cp), VAR_READWRITE); /* have to save the new val */
139
140 /* and now mirror home with HOME */
141 tsetenv(STRKHOME, cp);
142 /* fix directory stack for new tilde home */
143 dtilde();
144 xfree((ptr_t) cp);
145 }
146 else if (eq(vp, STRedit)) {
147 editing = 1;
148 noediting = 0;
149 /* PWP: add more stuff in here later */
150 }
151 else if (eq(vp, STRshlvl)) {
152 tsetenv(STRKSHLVL, varval(vp));
153 }
154 else if (eq(vp, STRbackslash_quote)) {
155 bslash_quote = 1;
156 }
157 else if (eq(vp, STRdirstack)) {
158 dsetstack();
159 }
160 else if (eq(vp, STRrecognize_only_executables)) {
161 tw_cmd_free();
162 }
163 else if (eq(vp, STRkillring)) {
164 SetKillRing(getn(varval(vp)));
165 }
166#ifndef HAVENOUTMP
167 else if (eq(vp, STRwatch)) {
168 resetwatch();
169 }
170#endif /* HAVENOUTMP */
171 else if (eq(vp, STRimplicitcd)) {
172 implicit_cd = ((eq(varval(vp), STRverbose)) ? 2 : 1);
173 }
174#ifdef COLOR_LS_F
175 else if (eq(vp, STRcolor)) {
176 set_color_context();
177 }
178#endif /* COLOR_LS_F */
179#if defined(KANJI) && defined(SHORT_STRINGS) && defined(DSPMBYTE)
180 else if(eq(vp, CHECK_MBYTEVAR) || eq(vp, STRnokanji)) {
181 update_dspmbyte_vars();
182 }
183#endif
184#ifdef NLS_CATALOGS
185 else if (eq(vp, STRcatalog)) {
186 (void) catclose(catd);
187 nlsinit();
188 }
189#endif /* NLS_CATALOGS */
190}
191
192
193/*ARGSUSED*/
194void
195doset(v, c)
196 register Char **v;
197 struct command *c;
198{
199 register Char *p;
200 Char *vp, op;
201 Char **vecp;
202 bool hadsub;
203 int subscr;
204 int flags = VAR_READWRITE;
205 bool first_match = 0;
206 bool last_match = 0;
207 bool changed = 0;
208
209 USE(c);
210 v++;
211 do {
212 changed = 0;
213 /*
214 * Readonly addition From: Tim P. Starrin <noid@cyborg.larc.nasa.gov>
215 */
216 if (*v && eq(*v, STRmr)) {
217 flags = VAR_READONLY;
218 v++;
219 changed = 1;
220 }
221 if (*v && eq(*v, STRmf) && !last_match) {
222 first_match = 1;
223 v++;
224 changed = 1;
225 }
226 if (*v && eq(*v, STRml) && !first_match) {
227 last_match = 1;
228 v++;
229 changed = 1;
230 }
231 } while(changed);
232 p = *v++;
233 if (p == 0) {
234 plist(&shvhed, flags);
235 return;
236 }
237 do {
238 hadsub = 0;
239 vp = p;
240 if (letter(*p))
241 for (; alnum(*p); p++)
242 continue;
243 if (vp == p || !letter(*vp))
244 stderror(ERR_NAME | ERR_VARBEGIN);
245 if ((p - vp) > MAXVARLEN) {
246 stderror(ERR_NAME | ERR_VARTOOLONG);
247 return;
248 }
249 if (*p == '[') {
250 hadsub++;
251 p = getinx(p, &subscr);
252 }
253 if ((op = *p) != 0) {
254 *p++ = 0;
255 if (*p == 0 && *v && **v == '(')
256 p = *v++;
257 }
258 else if (*v && eq(*v, STRequal)) {
259 op = '=', v++;
260 if (*v)
261 p = *v++;
262 }
263 if (op && op != '=')
264 stderror(ERR_NAME | ERR_SYNTAX);
265 if (eq(p, STRLparen)) {
266 register Char **e = v;
267
268 if (hadsub)
269 stderror(ERR_NAME | ERR_SYNTAX);
270 for (;;) {
271 if (!*e)
272 stderror(ERR_NAME | ERR_MISSING, ')');
273 if (**e == ')')
274 break;
275 e++;
276 }
277 p = *e;
278 *e = 0;
279 vecp = saveblk(v);
280 if (first_match)
281 flags |= VAR_FIRST;
282 else if (last_match)
283 flags |= VAR_LAST;
284
285 set1(vp, vecp, &shvhed, flags);
286 *e = p;
287 v = e + 1;
288 }
289 else if (hadsub)
290 asx(vp, subscr, Strsave(p));
291 else
292 set(vp, Strsave(p), flags);
293 update_vars(vp);
294 } while ((p = *v++) != NULL);
295}
296
297static Char *
298getinx(cp, ip)
299 register Char *cp;
300 register int *ip;
301{
302 *ip = 0;
303 *cp++ = 0;
304 while (*cp && Isdigit(*cp))
305 *ip = *ip * 10 + *cp++ - '0';
306 if (*cp++ != ']')
307 stderror(ERR_NAME | ERR_SUBSCRIPT);
308 return (cp);
309}
310
311static void
312asx(vp, subscr, p)
313 Char *vp;
314 int subscr;
315 Char *p;
316{
317 register struct varent *v = getvx(vp, subscr);
318
319 if (v->v_flags & VAR_READONLY)
320 stderror(ERR_READONLY|ERR_NAME, v->v_name);
321 xfree((ptr_t) v->vec[subscr - 1]);
322 v->vec[subscr - 1] = globone(p, G_APPEND);
323}
324
325static struct varent *
326getvx(vp, subscr)
327 Char *vp;
328 int subscr;
329{
330 register struct varent *v = adrof(vp);
331
332 if (v == 0)
333 udvar(vp);
334 if (subscr < 1 || subscr > blklen(v->vec))
335 stderror(ERR_NAME | ERR_RANGE);
336 return (v);
337}
338
339/*ARGSUSED*/
340void
341dolet(v, dummy)
342 Char **v;
343 struct command *dummy;
344{
345 register Char *p;
346 Char *vp, c, op;
347 bool hadsub;
348 int subscr;
349
350 USE(dummy);
351 v++;
352 p = *v++;
353 if (p == 0) {
354 prvars();
355 return;
356 }
357 do {
358 hadsub = 0;
359 vp = p;
360 if (letter(*p))
361 for (; alnum(*p); p++)
362 continue;
363 if (vp == p || !letter(*vp))
364 stderror(ERR_NAME | ERR_VARBEGIN);
365 if ((p - vp) > MAXVARLEN)
366 stderror(ERR_NAME | ERR_VARTOOLONG);
367 if (*p == '[') {
368 hadsub++;
369 p = getinx(p, &subscr);
370 }
371 if (*p == 0 && *v)
372 p = *v++;
373 if ((op = *p) != 0)
374 *p++ = 0;
375 else
376 stderror(ERR_NAME | ERR_ASSIGN);
377
378 /*
379 * if there is no expression after the '=' then print a "Syntax Error"
380 * message - strike
381 */
382 if (*p == '\0' && *v == NULL)
383 stderror(ERR_NAME | ERR_ASSIGN);
384
385 vp = Strsave(vp);
386 if (op == '=') {
387 c = '=';
388 p = xset(p, &v);
389 }
390 else {
391 c = *p++;
392 if (any("+-", c)) {
393 if (c != op || *p)
394 stderror(ERR_NAME | ERR_UNKNOWNOP);
395 p = Strsave(STR1);
396 }
397 else {
398 if (any("<>", op)) {
399 if (c != op)
400 stderror(ERR_NAME | ERR_UNKNOWNOP);
401 c = *p++;
402 stderror(ERR_NAME | ERR_SYNTAX);
403 }
404 if (c != '=')
405 stderror(ERR_NAME | ERR_UNKNOWNOP);
406 p = xset(p, &v);
407 }
408 }
409 if (op == '=') {
410 if (hadsub)
411 asx(vp, subscr, p);
412 else
413 set(vp, p, VAR_READWRITE);
414 }
415 else if (hadsub) {
416 struct varent *gv = getvx(vp, subscr);
417
418 asx(vp, subscr, operate(op, gv->vec[subscr - 1], p));
419 }
420 else
421 set(vp, operate(op, varval(vp), p), VAR_READWRITE);
422 update_vars(vp);
423 xfree((ptr_t) vp);
424 if (c != '=')
425 xfree((ptr_t) p);
426 } while ((p = *v++) != NULL);
427}
428
429static Char *
430xset(cp, vp)
431 Char *cp, ***vp;
432{
433 register Char *dp;
434
435 if (*cp) {
436 dp = Strsave(cp);
437 --(*vp);
438 xfree((ptr_t) ** vp);
439 **vp = dp;
440 }
441 return (putn(expr(vp)));
442}
443
444static Char *
445operate(op, vp, p)
446 int op;
447 Char *vp, *p;
448{
449 Char opr[2];
450 Char *vec[5];
451 register Char **v = vec;
452 Char **vecp = v;
453 register int i;
454
455 if (op != '=') {
456 if (*vp)
457 *v++ = vp;
458 opr[0] = (Char) op;
459 opr[1] = 0;
460 *v++ = opr;
461 if (op == '<' || op == '>')
462 *v++ = opr;
463 }
464 *v++ = p;
465 *v++ = 0;
466 i = expr(&vecp);
467 if (*vecp)
468 stderror(ERR_NAME | ERR_EXPRESSION);
469 return (putn(i));
470}
471
472static Char *putp, nbuf[50];
473
474Char *
475putn(n)
476 register int n;
477{
478 int num;
479
480 putp = nbuf;
481 if (n < 0) {
482 n = -n;
483 *putp++ = '-';
484 }
485 num = 2; /* confuse lint */
486 if (sizeof(int) == num && ((unsigned int) n) == 0x8000) {
487 *putp++ = '3';
488 n = 2768;
489#ifdef pdp11
490 }
491#else /* !pdp11 */
492 }
493 else {
494 num = 4; /* confuse lint */
495 if (sizeof(int) == num && ((unsigned int) n) == 0x80000000) {
496 *putp++ = '2';
497 n = 147483648;
498 }
499 }
500#endif /* pdp11 */
501 putn1(n);
502 *putp = 0;
503 return (Strsave(nbuf));
504}
505
506static void
507putn1(n)
508 register int n;
509{
510 if (n > 9)
511 putn1(n / 10);
512 *putp++ = n % 10 + '0';
513}
514
515int
516getn(cp)
517 register Char *cp;
518{
519 register int n;
520 int sign;
521
522 if (!cp) /* PWP: extra error checking */
523 stderror(ERR_NAME | ERR_BADNUM);
524
525 sign = 0;
526 if (cp[0] == '+' && cp[1])
527 cp++;
528 if (*cp == '-') {
529 sign++;
530 cp++;
531 if (!Isdigit(*cp))
532 stderror(ERR_NAME | ERR_BADNUM);
533 }
534 n = 0;
535 while (Isdigit(*cp))
536 n = n * 10 + *cp++ - '0';
537 if (*cp)
538 stderror(ERR_NAME | ERR_BADNUM);
539 return (sign ? -n : n);
540}
541
542Char *
543value1(var, head)
544 Char *var;
545 struct varent *head;
546{
547 register struct varent *vp;
548
549 if (!var || !head) /* PWP: extra error checking */
550 return (STRNULL);
551
552 vp = adrof1(var, head);
553 return (vp == 0 || vp->vec[0] == 0 ? STRNULL : vp->vec[0]);
554}
555
556static struct varent *
557madrof(pat, vp)
558 Char *pat;
559 register struct varent *vp;
560{
561 register struct varent *vp1;
562
563 for (vp = vp->v_left; vp; vp = vp->v_right) {
564 if (vp->v_left && (vp1 = madrof(pat, vp)) != NULL)
565 return vp1;
566 if (Gmatch(vp->v_name, pat))
567 return vp;
568 }
569 return vp;
570}
571
572struct varent *
573adrof1(name, v)
574 register Char *name;
575 register struct varent *v;
576{
577 int cmp;
578
579 v = v->v_left;
580 while (v && ((cmp = *name - *v->v_name) != 0 ||
581 (cmp = Strcmp(name, v->v_name)) != 0))
582 if (cmp < 0)
583 v = v->v_left;
584 else
585 v = v->v_right;
586 return v;
587}
588
589/*
590 * The caller is responsible for putting value in a safe place
591 */
592void
593set(var, val, flags)
594 Char *var, *val;
595 int flags;
596{
597 register Char **vec = (Char **) xmalloc((size_t) (2 * sizeof(Char **)));
598
599 vec[0] = val;
600 vec[1] = 0;
601 set1(var, vec, &shvhed, flags);
602}
603
604void
605set1(var, vec, head, flags)
606 Char *var, **vec;
607 struct varent *head;
608 int flags;
609{
610 register Char **oldv = vec;
611
612 if ((flags & VAR_NOGLOB) == 0) {
613 gflag = 0;
614 tglob(oldv);
615 if (gflag) {
616 vec = globall(oldv);
617 if (vec == 0) {
618 blkfree(oldv);
619 stderror(ERR_NAME | ERR_NOMATCH);
620 return;
621 }
622 blkfree(oldv);
623 gargv = 0;
624 }
625 }
626 /*
627 * Uniqueness addition from: Michael Veksler <mveksler@vnet.ibm.com>
628 */
629 if ( flags & (VAR_FIRST | VAR_LAST) ) {
630 /*
631 * Code for -f (VAR_FIRST) and -l (VAR_LAST) options.
632 * Method:
633 * Delete all duplicate words leaving "holes" in the word array (vec).
634 * Then remove the "holes", keeping the order of the words unchanged.
635 */
636 if (vec && vec[0] && vec[1]) { /* more than one word ? */
637 int i, j;
638 int num_items;
639
640 for (num_items = 0; vec[num_items]; num_items++)
641 continue;
642 if (flags & VAR_FIRST) {
643 /* delete duplications, keeping first occurance */
644 for (i = 1; i < num_items; i++)
645 for (j = 0; j < i; j++)
646 /* If have earlier identical item, remove i'th item */
647 if (vec[i] && vec[j] && Strcmp(vec[j], vec[i]) == 0) {
648 free(vec[i]);
649 vec[i] = NULL;
650 break;
651 }
652 } else if (flags & VAR_LAST) {
653 /* delete duplications, keeping last occurance */
654 for (i = 0; i < num_items - 1; i++)
655 for (j = i + 1; j < num_items; j++)
656 /* If have later identical item, remove i'th item */
657 if (vec[i] && vec[j] && Strcmp(vec[j], vec[i]) == 0) {
658 /* remove identical item (the first) */
659 free(vec[i]);
660 vec[i] = NULL;
661 }
662 }
663 /* Compress items - remove empty items */
664 for (j = i = 0; i < num_items; i++)
665 if (vec[i])
666 vec[j++] = vec[i];
667
668 /* NULL-fy remaining items */
669 for (; j < num_items; j++)
670 vec[j] = NULL;
671 }
672 /* don't let the attribute propagate */
673 flags &= ~(VAR_FIRST|VAR_LAST);
674 }
675 setq(var, vec, head, flags);
676}
677
678
679void
680setq(name, vec, p, flags)
681 Char *name, **vec;
682 register struct varent *p;
683 int flags;
684{
685 register struct varent *c;
686 register int f;
687
688 f = 0; /* tree hangs off the header's left link */
689 while ((c = p->v_link[f]) != 0) {
690 if ((f = *name - *c->v_name) == 0 &&
691 (f = Strcmp(name, c->v_name)) == 0) {
692 if (c->v_flags & VAR_READONLY)
693 stderror(ERR_READONLY|ERR_NAME, c->v_name);
694 blkfree(c->vec);
695 c->v_flags = flags;
696 trim(c->vec = vec);
697 return;
698 }
699 p = c;
700 f = f > 0;
701 }
702 p->v_link[f] = c = (struct varent *) xmalloc((size_t)sizeof(struct varent));
703 c->v_name = Strsave(name);
704 c->v_flags = flags;
705 c->v_bal = 0;
706 c->v_left = c->v_right = 0;
707 c->v_parent = p;
708 balance(p, f, 0);
709 trim(c->vec = vec);
710}
711
712/*ARGSUSED*/
713void
714unset(v, c)
715 Char **v;
716 struct command *c;
717{
718 bool did_roe, did_edit;
719
720 USE(c);
721 did_roe = adrof(STRrecognize_only_executables) != NULL;
722 did_edit = adrof(STRedit) != NULL;
723 unset1(v, &shvhed);
724 if (adrof(STRhistchars) == 0) {
725 HIST = '!';
726 HISTSUB = '^';
727 }
728 if (adrof(STRpromptchars) == 0) {
729 PRCH = '>';
730 PRCHROOT = '#';
731 }
732 if (adrof(STRhistlit) == 0)
733 HistLit = 0;
734 if (adrof(STRloginsh) == 0)
735 loginsh = 0;
736 if (adrof(STRwordchars) == 0)
737 word_chars = STR_WORD_CHARS;
738 if (adrof(STRedit) == 0)
739 editing = 0;
740 if (adrof(STRbackslash_quote) == 0)
741 bslash_quote = 0;
742 if (adrof(STRsymlinks) == 0)
743 symlinks = 0;
744 if (adrof(STRimplicitcd) == 0)
745 implicit_cd = 0;
746 if (adrof(STRkillring) == 0)
747 SetKillRing(0);
748 if (did_edit && noediting && adrof(STRedit) == 0)
749 noediting = 0;
750 if (did_roe && adrof(STRrecognize_only_executables) == 0)
751 tw_cmd_free();
752#ifdef COLOR_LS_F
753 if (adrof(STRcolor) == 0)
754 set_color_context();
755#endif /* COLOR_LS_F */
756#if defined(KANJI) && defined(SHORT_STRINGS) && defined(DSPMBYTE)
757 update_dspmbyte_vars();
758#endif
759#ifdef NLS_CATALOGS
760 (void) catclose(catd);
761 nlsinit();
762#endif /* NLS_CATALOGS */
763}
764
765void
766unset1(v, head)
767 register Char *v[];
768 struct varent *head;
769{
770 register struct varent *vp;
771 register int cnt;
772
773 while (*++v) {
774 cnt = 0;
775 while ((vp = madrof(*v, head)) != NULL)
776 if (vp->v_flags & VAR_READONLY)
777 stderror(ERR_READONLY|ERR_NAME, vp->v_name);
778 else
779 unsetv1(vp), cnt++;
780 if (cnt == 0)
781 setname(short2str(*v));
782 }
783}
784
785void
786unsetv(var)
787 Char *var;
788{
789 register struct varent *vp;
790
791 if ((vp = adrof1(var, &shvhed)) == 0)
792 udvar(var);
793 unsetv1(vp);
794}
795
796static void
797unsetv1(p)
798 register struct varent *p;
799{
800 register struct varent *c, *pp;
801 register int f;
802
803 /*
804 * Free associated memory first to avoid complications.
805 */
806 blkfree(p->vec);
807 xfree((ptr_t) p->v_name);
808 /*
809 * If p is missing one child, then we can move the other into where p is.
810 * Otherwise, we find the predecessor of p, which is guaranteed to have no
811 * right child, copy it into p, and move it's left child into it.
812 */
813 if (p->v_right == 0)
814 c = p->v_left;
815 else if (p->v_left == 0)
816 c = p->v_right;
817 else {
818 for (c = p->v_left; c->v_right; c = c->v_right)
819 continue;
820 p->v_name = c->v_name;
821 p->v_flags = c->v_flags;
822 p->vec = c->vec;
823 p = c;
824 c = p->v_left;
825 }
826
827 /*
828 * Move c into where p is.
829 */
830 pp = p->v_parent;
831 f = pp->v_right == p;
832 if ((pp->v_link[f] = c) != 0)
833 c->v_parent = pp;
834 /*
835 * Free the deleted node, and rebalance.
836 */
837 xfree((ptr_t) p);
838 balance(pp, f, 1);
839}
840
841void
842setNS(cp)
843 Char *cp;
844{
845 set(cp, Strsave(STRNULL), VAR_READWRITE);
846}
847
848/*ARGSUSED*/
849void
850shift(v, c)
851 register Char **v;
852 struct command *c;
853{
854 register struct varent *argv;
855 register Char *name;
856
857 USE(c);
858 v++;
859 name = *v;
860 if (name == 0)
861 name = STRargv;
862 else
863 (void) strip(name);
864 argv = adrof(name);
865 if (argv == 0)
866 udvar(name);
867 if (argv->vec[0] == 0)
868 stderror(ERR_NAME | ERR_NOMORE);
869 lshift(argv->vec, 1);
870 update_vars(name);
871}
872
873static Char STRsep[2] = { PATHSEP, '\0' };
874
875static void
876exportpath(val)
877 Char **val;
878{
879 Char *exppath;
880 size_t exppath_size = BUFSIZE;
881 exppath = (Char *)xmalloc(sizeof(Char)*exppath_size);
882
883 exppath[0] = 0;
884 if (val)
885 while (*val) {
886 while (Strlen(*val) + Strlen(exppath) + 2 > exppath_size) {
887 if ((exppath
888 = (Char *)xrealloc(exppath, sizeof(Char)*(exppath_size *= 2)))
889 == NULL) {
890 xprintf(CGETS(18, 1,
891 "Warning: ridiculously long PATH truncated\n"));
892 break;
893 }
894 }
895 (void) Strcat(exppath, *val++);
896 if (*val == 0 || eq(*val, STRRparen))
897 break;
898 (void) Strcat(exppath, STRsep);
899 }
900 tsetenv(STRKPATH, exppath);
901 free(exppath);
902}
903
904#ifndef lint
905 /*
906 * Lint thinks these have null effect
907 */
908 /* macros to do single rotations on node p */
909# define rright(p) (\
910 t = (p)->v_left,\
911 (t)->v_parent = (p)->v_parent,\
912 (((p)->v_left = t->v_right) != NULL) ?\
913 (t->v_right->v_parent = (p)) : 0,\
914 (t->v_right = (p))->v_parent = t,\
915 (p) = t)
916# define rleft(p) (\
917 t = (p)->v_right,\
918 ((t)->v_parent = (p)->v_parent,\
919 ((p)->v_right = t->v_left) != NULL) ? \
920 (t->v_left->v_parent = (p)) : 0,\
921 (t->v_left = (p))->v_parent = t,\
922 (p) = t)
923#else
924static struct varent *
925rleft(p)
926 struct varent *p;
927{
928 return (p);
929}
930static struct varent *
931rright(p)
932 struct varent *p;
933{
934 return (p);
935}
936
937#endif /* ! lint */
938
939
940/*
941 * Rebalance a tree, starting at p and up.
942 * F == 0 means we've come from p's left child.
943 * D == 1 means we've just done a delete, otherwise an insert.
944 */
945static void
946balance(p, f, d)
947 register struct varent *p;
948 register int f, d;
949{
950 register struct varent *pp;
951
952#ifndef lint
953 register struct varent *t; /* used by the rotate macros */
954#endif /* !lint */
955 register int ff;
956#ifdef lint
957 ff = 0; /* Sun's lint is dumb! */
958#endif
959
960 /*
961 * Ok, from here on, p is the node we're operating on; pp is it's parent; f
962 * is the branch of p from which we have come; ff is the branch of pp which
963 * is p.
964 */
965 for (; (pp = p->v_parent) != 0; p = pp, f = ff) {
966 ff = pp->v_right == p;
967 if (f ^ d) { /* right heavy */
968 switch (p->v_bal) {
969 case -1: /* was left heavy */
970 p->v_bal = 0;
971 break;
972 case 0: /* was balanced */
973 p->v_bal = 1;
974 break;
975 case 1: /* was already right heavy */
976 switch (p->v_right->v_bal) {
977 case 1: /* sigle rotate */
978 pp->v_link[ff] = rleft(p);
979 p->v_left->v_bal = 0;
980 p->v_bal = 0;
981 break;
982 case 0: /* single rotate */
983 pp->v_link[ff] = rleft(p);
984 p->v_left->v_bal = 1;
985 p->v_bal = -1;
986 break;
987 case -1: /* double rotate */
988 (void) rright(p->v_right);
989 pp->v_link[ff] = rleft(p);
990 p->v_left->v_bal =
991 p->v_bal < 1 ? 0 : -1;
992 p->v_right->v_bal =
993 p->v_bal > -1 ? 0 : 1;
994 p->v_bal = 0;
995 break;
996 default:
997 break;
998 }
999 break;
1000 default:
1001 break;
1002 }
1003 }
1004 else { /* left heavy */
1005 switch (p->v_bal) {
1006 case 1: /* was right heavy */
1007 p->v_bal = 0;
1008 break;
1009 case 0: /* was balanced */
1010 p->v_bal = -1;
1011 break;
1012 case -1: /* was already left heavy */
1013 switch (p->v_left->v_bal) {
1014 case -1: /* single rotate */
1015 pp->v_link[ff] = rright(p);
1016 p->v_right->v_bal = 0;
1017 p->v_bal = 0;
1018 break;
1019 case 0: /* signle rotate */
1020 pp->v_link[ff] = rright(p);
1021 p->v_right->v_bal = -1;
1022 p->v_bal = 1;
1023 break;
1024 case 1: /* double rotate */
1025 (void) rleft(p->v_left);
1026 pp->v_link[ff] = rright(p);
1027 p->v_left->v_bal =
1028 p->v_bal < 1 ? 0 : -1;
1029 p->v_right->v_bal =
1030 p->v_bal > -1 ? 0 : 1;
1031 p->v_bal = 0;
1032 break;
1033 default:
1034 break;
1035 }
1036 break;
1037 default:
1038 break;
1039 }
1040 }
1041 /*
1042 * If from insert, then we terminate when p is balanced. If from
1043 * delete, then we terminate when p is unbalanced.
1044 */
1045 if ((p->v_bal == 0) ^ d)
1046 break;
1047 }
1048}
1049
1050void
1051plist(p, what)
1052 register struct varent *p;
1053 int what;
1054{
1055 register struct varent *c;
1056 register int len;
1057
1058 if (setintr)
1059#ifdef BSDSIGS
1060 (void) sigsetmask(sigblock((sigmask_t) 0) & ~sigmask(SIGINT));
1061#else /* !BSDSIGS */
1062 (void) sigrelse(SIGINT);
1063#endif /* BSDSIGS */
1064
1065 for (;;) {
1066 while (p->v_left)
1067 p = p->v_left;
1068x:
1069 if (p->v_parent == 0) /* is it the header? */
1070 return;
1071 if ((p->v_flags & what) != 0) {
1072 len = blklen(p->vec);
1073 xprintf("%S\t", p->v_name);
1074 if (len != 1)
1075 xputchar('(');
1076 blkpr(p->vec);
1077 if (len != 1)
1078 xputchar(')');
1079 xputchar('\n');
1080 }
1081 if (p->v_right) {
1082 p = p->v_right;
1083 continue;
1084 }
1085 do {
1086 c = p;
1087 p = p->v_parent;
1088 } while (p->v_right == c);
1089 goto x;
1090 }
1091}
1092
1093#if defined(KANJI) && defined(SHORT_STRINGS) && defined(DSPMBYTE)
1094bool dspmbyte_ls;
1095
1096void
1097update_dspmbyte_vars()
1098{
1099 int lp, iskcode;
1100 Char *dstr1;
1101 struct varent *vp;
1102
1103 /* if variable "nokanji" is set, multi-byte display is disabled */
1104 if ((vp = adrof(CHECK_MBYTEVAR)) && !adrof(STRnokanji)) {
1105 _enable_mbdisp = 1;
1106 dstr1 = vp->vec[0];
1107 if(eq (dstr1, STRKSJIS))
1108 iskcode = 1;
1109 else if (eq(dstr1, STRKEUC))
1110 iskcode = 2;
1111 else if (eq(dstr1, STRKBIG5))
1112 iskcode = 3;
1113 else if ((dstr1[0] - '0') >= 0 && (dstr1[0] - '0') <= 3) {
1114 iskcode = 0;
1115 }
1116 else {
1117 xprintf(CGETS(18, 2,
1118 "Warning: unknown multibyte display; using default(euc(JP))\n"));
1119 iskcode = 2;
1120 }
1121 if (dstr1 && vp->vec[1] && eq(vp->vec[1], STRls))
1122 dspmbyte_ls = 1;
1123 else
1124 dspmbyte_ls = 0;
1125 for (lp = 0; lp < 256 && iskcode > 0; lp++) {
1126 switch (iskcode) {
1127 case 1:
1128 /* Shift-JIS */
1129 _cmap[lp] = _cmap_mbyte[lp];
1130 _mbmap[lp] = _mbmap_sjis[lp];
1131 break;
1132 case 2:
1133 /* 2 ... euc */
1134 _cmap[lp] = _cmap_mbyte[lp];
1135 _mbmap[lp] = _mbmap_euc[lp];
1136 break;
1137 case 3:
1138 /* 3 ... big5 */
1139 _cmap[lp] = _cmap_mbyte[lp];
1140 _mbmap[lp] = _mbmap_big5[lp];
1141 break;
1142 default:
1143 xprintf(CGETS(18, 3,
1144 "Warning: unknown multibyte code %d; multibyte disabled\n"),
1145 iskcode);
1146 _cmap[lp] = _cmap_c[lp];
1147 _mbmap[lp] = 0; /* Default map all 0 */
1148 _enable_mbdisp = 0;
1149 break;
1150 }
1151 }
1152 if (iskcode == 0) {
1153 /* check original table */
1154 if (Strlen(dstr1) != 256) {
1155 xprintf(CGETS(18, 4,
1156 "Warning: Invalid multibyte table length (%d); multibyte disabled\n"),
1157 Strlen(dstr1));
1158 _enable_mbdisp = 0;
1159 }
1160 for (lp = 0; lp < 256 && _enable_mbdisp == 1; lp++) {
1161 if (!((dstr1[lp] - '0') >= 0 && (dstr1[lp] - '0') <= 3)) {
1162 xprintf(CGETS(18, 4,
1163 "Warning: bad multibyte code at offset +%d; multibyte diabled\n"),
1164 lp);
1165 _enable_mbdisp = 0;
1166 break;
1167 }
1168 }
1169 /* set original table */
1170 for (lp = 0; lp < 256; lp++) {
1171 if (_enable_mbdisp == 1) {
1172 _cmap[lp] = _cmap_mbyte[lp];
1173 _mbmap[lp] = (unsigned short) ((dstr1[lp] - '0') & 0x0f);
1174 }
1175 else {
1176 _cmap[lp] = _cmap_c[lp];
1177 _mbmap[lp] = 0; /* Default map all 0 */
1178 }
1179 }
1180 }
1181 }
1182 else {
1183 for (lp = 0; lp < 256; lp++) {
1184 _cmap[lp] = _cmap_c[lp];
1185 _mbmap[lp] = 0; /* Default map all 0 */
1186 }
1187 _enable_mbdisp = 0;
1188 dspmbyte_ls = 0;
1189 }
1190#ifdef MBYTEDEBUG /* Sorry, use for beta testing */
1191 {
1192 Char mbmapstr[300];
1193 for (lp = 0; lp < 256; lp++) {
1194 mbmapstr[lp] = _mbmap[lp] + '0';
1195 mbmapstr[lp+1] = 0;
1196 }
1197 set(STRmbytemap, Strsave(mbmapstr), VAR_READWRITE);
1198 }
1199#endif /* MBYTEMAP */
1200}
1201
1202/* dspkanji/dspmbyte autosetting */
1203/* PATCH IDEA FROM Issei.Suzuki VERY THANKS */
1204void
1205autoset_dspmbyte(pcp)
1206 Char *pcp;
1207{
1208 int i;
1209 struct dspm_autoset_Table {
1210 Char *n;
1211 Char *v;
1212 } dspmt[] = {
1213 { STRLANGEUCJP, STRKEUC },
1214 { STRLANGEUCKR, STRKEUC },
1215 { STRLANGEUCZH, STRKEUC },
1215 { STRLANGEUCJPB, STRKEUC },
1216 { STRLANGEUCKRB, STRKEUC },
1216 { STRLANGEUCJPB, STRKEUC },
1217 { STRLANGEUCKRB, STRKEUC },
1218 { STRLANGEUCZHB, STRKEUC },
1217 { STRLANGSJIS, STRKSJIS },
1218 { STRLANGSJISB, STRKSJIS },
1219 { STRLANGBIG5, STRKBIG5 },
1220 { NULL, NULL }
1221 };
1222
1223 if (*pcp == '\0')
1224 return;
1225
1226 for (i = 0; dspmt[i].n; i++) {
1227 if (eq(pcp, dspmt[i].n)) {
1228 set(CHECK_MBYTEVAR, Strsave(dspmt[i].v), VAR_READWRITE);
1229 update_dspmbyte_vars();
1230 break;
1231 }
1232 }
1233}
1234#endif
1219 { STRLANGSJIS, STRKSJIS },
1220 { STRLANGSJISB, STRKSJIS },
1221 { STRLANGBIG5, STRKBIG5 },
1222 { NULL, NULL }
1223 };
1224
1225 if (*pcp == '\0')
1226 return;
1227
1228 for (i = 0; dspmt[i].n; i++) {
1229 if (eq(pcp, dspmt[i].n)) {
1230 set(CHECK_MBYTEVAR, Strsave(dspmt[i].v), VAR_READWRITE);
1231 update_dspmbyte_vars();
1232 break;
1233 }
1234 }
1235}
1236#endif