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