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