1 0 stevel /* 2 356 muffin * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 3 0 stevel * Use is subject to license terms. 4 0 stevel */ 5 0 stevel 6 0 stevel /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 7 0 stevel /* All Rights Reserved */ 8 0 stevel 9 0 stevel /* 10 0 stevel * Copyright (c) 1980 Regents of the University of California. 11 0 stevel * All rights reserved. The Berkeley Software License Agreement 12 0 stevel * specifies the terms and conditions for redistribution. 13 0 stevel */ 14 0 stevel 15 0 stevel #pragma ident "%Z%%M% %I% %E% SMI" 16 0 stevel 17 0 stevel #include "sh.h" 18 0 stevel #include "sh.tconst.h" 19 356 muffin extern int didchdir; 20 0 stevel 21 0 stevel /* 22 0 stevel * C Shell 23 0 stevel */ 24 0 stevel 25 356 muffin void asx(tchar *, int, tchar *); 26 356 muffin void putn1(int); 27 356 muffin void set(tchar *, tchar *); 28 356 muffin void set1(tchar *, tchar **, struct varent *); 29 356 muffin void setq(tchar *, tchar **, struct varent *); 30 356 muffin void unset1(tchar *[], struct varent *); 31 356 muffin void unsetv1(struct varent *); 32 356 muffin void exportpath(tchar **); 33 356 muffin void balance(struct varent *, int, int); 34 356 muffin tchar *operate(tchar, tchar *, tchar *); 35 356 muffin tchar *getinx(tchar *, int *); 36 356 muffin tchar *xset(tchar *, tchar ***); 37 356 muffin struct varent *getvx(tchar *, int); 38 356 muffin 39 356 muffin void 40 356 muffin doset(tchar **v) 41 0 stevel { 42 356 muffin tchar *p; 43 0 stevel tchar *vp, op; 44 0 stevel tchar **vecp; 45 0 stevel bool hadsub; 46 0 stevel int subscr; 47 0 stevel tchar *retp; 48 0 stevel 49 0 stevel #ifdef TRACE 50 0 stevel tprintf("TRACE- doset()\n"); 51 0 stevel #endif 52 0 stevel v++; 53 0 stevel p = *v++; 54 0 stevel if (p == 0) { 55 0 stevel prvars(); 56 0 stevel return; 57 0 stevel } 58 0 stevel do { 59 0 stevel hadsub = 0; 60 0 stevel /* 61 0 stevel * check for proper variable syntax 62 0 stevel * must be alphanumeric, start with a letter and 63 0 stevel * be at most 20 characters 64 0 stevel */ 65 0 stevel for (vp = p; alnum(*p); p++) 66 0 stevel continue; 67 0 stevel if (vp == p || !letter(*vp)) 68 0 stevel goto setsyn; 69 559 nakanon if ((p - vp) > MAX_VAR_LEN) 70 0 stevel bferr("Variable name too long"); 71 0 stevel if (*p == '[') { 72 0 stevel hadsub++; 73 0 stevel p = getinx(p, &subscr); 74 0 stevel } 75 0 stevel if (op = *p) { 76 0 stevel *p++ = 0; 77 0 stevel if (*p == 0 && *v && **v == '(') 78 0 stevel p = *v++; 79 559 nakanon } else if (*v && eq(*v, S_EQ /* "=" */)) { 80 0 stevel op = '=', v++; 81 0 stevel if (*v) 82 0 stevel p = *v++; 83 0 stevel } 84 0 stevel if (op && op != '=') 85 0 stevel setsyn: 86 0 stevel bferr("Syntax error"); 87 559 nakanon if (eq(p, S_LPAR /* "(" */)) { 88 356 muffin tchar **e = v; 89 0 stevel 90 0 stevel if (hadsub) 91 0 stevel goto setsyn; 92 0 stevel for (;;) { 93 0 stevel if (!*e) 94 0 stevel bferr("Missing )"); 95 0 stevel if (**e == ')') 96 0 stevel break; 97 0 stevel e++; 98 0 stevel } 99 0 stevel p = *e; 100 0 stevel *e = 0; 101 0 stevel vecp = saveblk(v); 102 0 stevel set1(vp, vecp, &shvhed); 103 0 stevel *e = p; 104 0 stevel v = e + 1; 105 0 stevel } else if (hadsub) { 106 0 stevel retp = savestr(p); 107 0 stevel asx(vp, subscr, retp); 108 0 stevel xfree(retp); 109 0 stevel retp = 0; 110 0 stevel } else 111 0 stevel set(vp, savestr(p)); 112 559 nakanon if (eq(vp, S_path /* "path" */)) { 113 559 nakanon exportpath(adrof(S_path /* "path" */)->vec); 114 0 stevel dohash(xhash); 115 559 nakanon } else if (eq(vp, S_histchars /* "histchars" */)) { 116 559 nakanon tchar *p = value(S_histchars /* "histchars" */); 117 0 stevel HIST = *p++; 118 0 stevel HISTSUB = *p; 119 559 nakanon } else if (eq(vp, S_user /* "user" */)) 120 559 nakanon local_setenv(S_USER /* "USER" */, value(vp)); 121 559 nakanon else if (eq(vp, S_term /* "term" */)) 122 559 nakanon local_setenv(S_TERM /* "TERM" */, value(vp)); 123 559 nakanon else if (eq(vp, S_home /* "home" */)) 124 559 nakanon local_setenv(S_HOME /* "HOME" */, value(vp)); 125 0 stevel #ifdef FILEC 126 559 nakanon else if (eq(vp, S_filec /* "filec" */)) 127 0 stevel filec = 1; 128 559 nakanon else if (eq(vp, S_cdpath /* "cdpath" */)) 129 0 stevel dohash(xhash2); 130 0 stevel #endif 131 0 stevel } while (p = *v++); 132 0 stevel } 133 0 stevel 134 0 stevel tchar * 135 356 muffin getinx(tchar *cp, int *ip) 136 0 stevel { 137 0 stevel 138 0 stevel #ifdef TRACE 139 0 stevel tprintf("TRACE- getinx()\n"); 140 0 stevel #endif 141 0 stevel *ip = 0; 142 0 stevel *cp++ = 0; 143 0 stevel while (*cp && digit(*cp)) 144 0 stevel *ip = *ip * 10 + *cp++ - '0'; 145 0 stevel if (*cp++ != ']') 146 0 stevel bferr("Subscript error"); 147 0 stevel return (cp); 148 0 stevel } 149 0 stevel 150 356 muffin void 151 356 muffin asx(tchar *vp, int subscr, tchar *p) 152 0 stevel { 153 356 muffin struct varent *v = getvx(vp, subscr); 154 0 stevel 155 0 stevel #ifdef TRACE 156 0 stevel tprintf("TRACE- asx()\n"); 157 0 stevel #endif 158 0 stevel xfree(v->vec[subscr - 1]); 159 0 stevel v->vec[subscr - 1] = globone(p); 160 0 stevel } 161 0 stevel 162 0 stevel struct varent * 163 356 muffin getvx(tchar *vp, int subscr) 164 0 stevel { 165 356 muffin struct varent *v = adrof(vp); 166 0 stevel 167 0 stevel #ifdef TRACE 168 0 stevel tprintf("TRACE- getvx()\n"); 169 0 stevel #endif 170 0 stevel if (v == 0) 171 0 stevel udvar(vp); 172 0 stevel if (subscr < 1 || subscr > blklen(v->vec)) 173 0 stevel bferr("Subscript out of range"); 174 0 stevel return (v); 175 0 stevel } 176 0 stevel 177 0 stevel tchar plusplus[2] = { '1', 0 }; 178 0 stevel 179 356 muffin void 180 356 muffin dolet(tchar **v) 181 0 stevel { 182 356 muffin tchar *p; 183 0 stevel tchar *vp, c, op; 184 0 stevel bool hadsub; 185 0 stevel int subscr; 186 0 stevel 187 0 stevel v++; 188 0 stevel p = *v++; 189 0 stevel if (p == 0) { 190 0 stevel prvars(); 191 0 stevel return; 192 0 stevel } 193 0 stevel do { 194 0 stevel hadsub = 0; 195 0 stevel for (vp = p; alnum(*p); p++) 196 0 stevel continue; 197 0 stevel if (vp == p || !letter(*vp)) 198 0 stevel goto letsyn; 199 0 stevel if (*p == '[') { 200 0 stevel hadsub++; 201 0 stevel p = getinx(p, &subscr); 202 0 stevel } 203 0 stevel if (*p == 0 && *v) 204 0 stevel p = *v++; 205 0 stevel if (op = *p) 206 0 stevel *p++ = 0; 207 0 stevel else 208 0 stevel goto letsyn; 209 0 stevel vp = savestr(vp); 210 0 stevel if (op == '=') { 211 0 stevel c = '='; 212 0 stevel p = xset(p, &v); 213 0 stevel } else { 214 0 stevel c = *p++; 215 0 stevel /* if (any(c, "+-")) { */ 216 0 stevel if (c == '+' || c == '-') { 217 0 stevel if (c != op || *p) 218 0 stevel goto letsyn; 219 0 stevel p = plusplus; 220 0 stevel } else { 221 559 nakanon /* if (any(op, "<>")) { */ 222 0 stevel if (op == '<' || op == '>') { 223 0 stevel if (c != op) 224 0 stevel goto letsyn; 225 0 stevel c = *p++; 226 0 stevel letsyn: 227 0 stevel bferr("Syntax error"); 228 0 stevel } 229 0 stevel if (c != '=') 230 0 stevel goto letsyn; 231 0 stevel p = xset(p, &v); 232 0 stevel } 233 0 stevel } 234 0 stevel if (op == '=') 235 0 stevel if (hadsub) 236 0 stevel asx(vp, subscr, p); 237 0 stevel else 238 0 stevel set(vp, p); 239 0 stevel else 240 0 stevel if (hadsub) 241 0 stevel #ifndef V6 242 0 stevel /* avoid bug in vax CC */ 243 0 stevel { 244 0 stevel struct varent *gv = getvx(vp, subscr); 245 0 stevel 246 0 stevel asx(vp, subscr, operate(op, gv->vec[subscr - 1], p)); 247 0 stevel } 248 0 stevel #else 249 0 stevel asx(vp, subscr, operate(op, getvx(vp, subscr)->vec[subscr - 1], p)); 250 0 stevel #endif 251 0 stevel else 252 0 stevel set(vp, operate(op, value(vp), p)); 253 559 nakanon if (eq(vp, S_path /* "path" */)) { 254 559 nakanon exportpath(adrof(S_path /* "path" */)->vec); 255 0 stevel dohash(xhash); 256 0 stevel } 257 0 stevel 258 559 nakanon if (eq(vp, S_cdpath /* "cdpath" */)) 259 0 stevel dohash(xhash2); 260 0 stevel 261 559 nakanon xfree(vp); 262 0 stevel if (c != '=') 263 559 nakanon xfree(p); 264 0 stevel } while (p = *v++); 265 0 stevel } 266 0 stevel 267 0 stevel tchar * 268 356 muffin xset(tchar *cp, tchar ***vp) 269 0 stevel { 270 356 muffin tchar *dp; 271 0 stevel 272 0 stevel #ifdef TRACE 273 0 stevel tprintf("TRACE- xset()\n"); 274 0 stevel #endif 275 0 stevel if (*cp) { 276 0 stevel dp = savestr(cp); 277 0 stevel --(*vp); 278 0 stevel xfree(**vp); 279 0 stevel **vp = dp; 280 0 stevel } 281 0 stevel return (putn(exp(vp))); 282 0 stevel } 283 0 stevel 284 0 stevel tchar * 285 356 muffin operate(tchar op, tchar *vp, tchar *p) 286 0 stevel { 287 0 stevel tchar opr[2]; 288 0 stevel tchar *vec[5]; 289 356 muffin tchar **v = vec; 290 0 stevel tchar **vecp = v; 291 356 muffin int i; 292 0 stevel 293 0 stevel if (op != '=') { 294 0 stevel if (*vp) 295 0 stevel *v++ = vp; 296 0 stevel opr[0] = op; 297 0 stevel opr[1] = 0; 298 0 stevel *v++ = opr; 299 0 stevel if (op == '<' || op == '>') 300 0 stevel *v++ = opr; 301 0 stevel } 302 0 stevel *v++ = p; 303 0 stevel *v++ = 0; 304 0 stevel i = exp(&vecp); 305 0 stevel if (*vecp) 306 0 stevel bferr("Expression syntax"); 307 0 stevel return (putn(i)); 308 0 stevel } 309 0 stevel 310 0 stevel static tchar *putp; 311 559 nakanon 312 0 stevel tchar * 313 356 muffin putn(int n) 314 0 stevel { 315 0 stevel static tchar number[15]; 316 0 stevel 317 0 stevel #ifdef TRACE 318 0 stevel tprintf("TRACE- putn()\n"); 319 0 stevel #endif 320 0 stevel putp = number; 321 0 stevel if (n < 0) { 322 0 stevel n = -n; 323 0 stevel *putp++ = '-'; 324 0 stevel } 325 0 stevel if (sizeof (int) == 2 && n == -32768) { 326 0 stevel *putp++ = '3'; 327 0 stevel n = 2768; 328 0 stevel #ifdef pdp11 329 0 stevel } 330 0 stevel #else 331 0 stevel } else if (sizeof (int) == 4 && n == 0x80000000) { 332 0 stevel *putp++ = '2'; 333 0 stevel n = 147483648; 334 0 stevel } 335 0 stevel #endif 336 0 stevel putn1(n); 337 0 stevel *putp = 0; 338 0 stevel return (savestr(number)); 339 0 stevel } 340 0 stevel 341 356 muffin void 342 356 muffin putn1(int n) 343 0 stevel { 344 0 stevel #ifdef TRACE 345 0 stevel tprintf("TRACE- putn1()\n"); 346 0 stevel #endif 347 0 stevel if (n > 9) 348 0 stevel putn1(n / 10); 349 0 stevel *putp++ = n % 10 + '0'; 350 0 stevel } 351 0 stevel 352 356 muffin int 353 356 muffin getn(tchar *cp) 354 0 stevel { 355 356 muffin int n; 356 0 stevel int sign; 357 0 stevel 358 0 stevel #ifdef TRACE 359 0 stevel tprintf("TRACE- getn()\n"); 360 0 stevel #endif 361 0 stevel sign = 0; 362 0 stevel if (cp[0] == '+' && cp[1]) 363 0 stevel cp++; 364 0 stevel if (*cp == '-') { 365 0 stevel sign++; 366 0 stevel cp++; 367 0 stevel if (!digit(*cp)) 368 0 stevel goto badnum; 369 0 stevel } 370 0 stevel n = 0; 371 0 stevel while (digit(*cp)) 372 0 stevel n = n * 10 + *cp++ - '0'; 373 0 stevel if (*cp) 374 0 stevel goto badnum; 375 0 stevel return (sign ? -n : n); 376 0 stevel badnum: 377 0 stevel bferr("Badly formed number"); 378 0 stevel return (0); 379 0 stevel } 380 0 stevel 381 0 stevel tchar * 382 356 muffin value1(tchar *var, struct varent *head) 383 0 stevel { 384 356 muffin struct varent *vp; 385 0 stevel 386 0 stevel #ifdef TRACE 387 0 stevel tprintf("TRACE- value1()\n"); 388 0 stevel #endif 389 0 stevel vp = adrof1(var, head); 390 559 nakanon return (vp == 0 || vp->vec[0] == 0 ? S_ /* "" */ : vp->vec[0]); 391 0 stevel } 392 0 stevel 393 0 stevel struct varent * 394 356 muffin madrof(tchar *pat, struct varent *vp) 395 0 stevel { 396 356 muffin struct varent *vp1; 397 0 stevel 398 0 stevel #ifdef TRACE 399 0 stevel tprintf("TRACE- madrof()\n"); 400 0 stevel #endif 401 0 stevel for (; vp; vp = vp->v_right) { 402 0 stevel if (vp->v_left && (vp1 = madrof(pat, vp->v_left))) 403 0 stevel return vp1; 404 0 stevel if (Gmatch(vp->v_name, pat)) 405 0 stevel return vp; 406 0 stevel } 407 0 stevel return vp; 408 0 stevel } 409 0 stevel 410 0 stevel struct varent * 411 356 muffin adrof1(tchar *name, struct varent *v) 412 0 stevel { 413 356 muffin int cmp; 414 0 stevel 415 0 stevel #ifdef TRACE 416 0 stevel tprintf("TRACE- adrof1()\n"); 417 0 stevel #endif 418 0 stevel v = v->v_left; 419 0 stevel while (v && ((cmp = *name - *v->v_name) || 420 559 nakanon (cmp = strcmp_(name, v->v_name)))) 421 0 stevel if (cmp < 0) 422 0 stevel v = v->v_left; 423 0 stevel else 424 0 stevel v = v->v_right; 425 0 stevel return v; 426 0 stevel } 427 0 stevel 428 0 stevel /* 429 0 stevel * The caller is responsible for putting value in a safe place 430 0 stevel */ 431 356 muffin void 432 356 muffin set(tchar *var, tchar *val) 433 0 stevel { 434 559 nakanon tchar **vec = (tchar **)xalloc(2 * sizeof (tchar **)); 435 0 stevel 436 0 stevel #ifdef TRACE 437 0 stevel tprintf("TRACE- set()\n"); 438 0 stevel #endif 439 0 stevel vec[0] = onlyread(val) ? savestr(val) : val; 440 0 stevel vec[1] = 0; 441 0 stevel set1(var, vec, &shvhed); 442 0 stevel } 443 0 stevel 444 356 muffin void 445 356 muffin set1(tchar *var, tchar **vec, struct varent *head) 446 0 stevel { 447 356 muffin tchar **oldv = vec; 448 0 stevel 449 0 stevel #ifdef TRACE 450 0 stevel tprintf("TRACE- set1()\n"); 451 0 stevel #endif 452 0 stevel gflag = 0; 453 559 nakanon /* 454 559 nakanon * If setting cwd variable via "set cwd=/tmp/something" 455 0 stevel * then do globbing. But if we are setting the cwd 456 559 nakanon * becuz of a cd, chdir, pushd, popd, do not do globbing. 457 0 stevel */ 458 559 nakanon if ((!(eq(var, S_cwd))) || (eq(var, S_cwd) && (didchdir == 0))) 459 0 stevel { 460 559 nakanon tglob(oldv); 461 0 stevel } 462 0 stevel if (gflag) { 463 0 stevel vec = glob(oldv); 464 0 stevel if (vec == 0) { 465 0 stevel bferr("No match"); 466 0 stevel blkfree(oldv); 467 0 stevel return; 468 0 stevel } 469 0 stevel blkfree(oldv); 470 0 stevel gargv = 0; 471 0 stevel } 472 0 stevel setq(var, vec, head); 473 0 stevel } 474 0 stevel 475 356 muffin void 476 356 muffin setq(tchar *name, tchar **vec, struct varent *p) 477 0 stevel { 478 356 muffin struct varent *c; 479 356 muffin int f; 480 0 stevel 481 0 stevel #ifdef TRACE 482 0 stevel tprintf("TRACE- setq()\n"); 483 0 stevel #endif 484 0 stevel f = 0; /* tree hangs off the header's left link */ 485 0 stevel while (c = p->v_link[f]) { 486 0 stevel if ((f = *name - *c->v_name) == 0 && 487 0 stevel (f = strcmp_(name, c->v_name)) == 0) { 488 0 stevel blkfree(c->vec); 489 0 stevel goto found; 490 0 stevel } 491 0 stevel p = c; 492 0 stevel f = f > 0; 493 0 stevel } 494 0 stevel p->v_link[f] = c = (struct varent *)xalloc(sizeof (struct varent)); 495 0 stevel c->v_name = savestr(name); 496 0 stevel c->v_bal = 0; 497 0 stevel c->v_left = c->v_right = 0; 498 0 stevel c->v_parent = p; 499 0 stevel balance(p, f, 0); 500 0 stevel found: 501 0 stevel trim(c->vec = vec); 502 0 stevel } 503 0 stevel 504 356 muffin void 505 356 muffin unset(tchar *v[]) 506 0 stevel { 507 0 stevel 508 0 stevel #ifdef TRACE 509 0 stevel tprintf("TRACE- unset()\n"); 510 0 stevel #endif 511 0 stevel unset1(v, &shvhed); 512 559 nakanon if (adrof(S_histchars /* "histchars" */) == 0) { 513 0 stevel HIST = '!'; 514 0 stevel HISTSUB = '^'; 515 0 stevel } 516 0 stevel #ifdef FILEC 517 559 nakanon if (adrof(S_filec /* "filec" */) == 0) 518 0 stevel filec = 0; 519 0 stevel #endif 520 0 stevel } 521 0 stevel 522 356 muffin void 523 356 muffin unset1(tchar *v[], struct varent *head) 524 0 stevel { 525 356 muffin struct varent *vp; 526 356 muffin int cnt; 527 0 stevel 528 0 stevel #ifdef TRACE 529 0 stevel tprintf("TRACE- unset1()\n"); 530 0 stevel #endif 531 0 stevel while (*++v) { 532 0 stevel cnt = 0; 533 0 stevel while (vp = madrof(*v, head->v_left)) 534 0 stevel unsetv1(vp), cnt++; 535 0 stevel if (cnt == 0) 536 0 stevel setname(*v); 537 0 stevel } 538 0 stevel } 539 0 stevel 540 356 muffin void 541 356 muffin unsetv(tchar *var) 542 0 stevel { 543 356 muffin struct varent *vp; 544 0 stevel 545 0 stevel #ifdef TRACE 546 0 stevel tprintf("TRACE- unsetv()\n"); 547 0 stevel #endif 548 0 stevel if ((vp = adrof1(var, &shvhed)) == 0) 549 0 stevel udvar(var); 550 0 stevel unsetv1(vp); 551 0 stevel } 552 0 stevel 553 356 muffin void 554 356 muffin unsetv1(struct varent *p) 555 0 stevel { 556 356 muffin struct varent *c, *pp; 557 356 muffin int f; 558 0 stevel 559 0 stevel #ifdef TRACE 560 0 stevel tprintf("TRACE- unsetv1()\n"); 561 0 stevel #endif 562 0 stevel /* 563 0 stevel * Free associated memory first to avoid complications. 564 0 stevel */ 565 0 stevel blkfree(p->vec); 566 559 nakanon xfree(p->v_name); 567 0 stevel /* 568 0 stevel * If p is missing one child, then we can move the other 569 0 stevel * into where p is. Otherwise, we find the predecessor 570 0 stevel * of p, which is guaranteed to have no right child, copy 571 0 stevel * it into p, and move it's left child into it. 572 0 stevel */ 573 0 stevel if (p->v_right == 0) 574 0 stevel c = p->v_left; 575 0 stevel else if (p->v_left == 0) 576 0 stevel c = p->v_right; 577 0 stevel else { 578 0 stevel for (c = p->v_left; c->v_right; c = c->v_right) 579 0 stevel ; 580 0 stevel p->v_name = c->v_name; 581 0 stevel p->vec = c->vec; 582 0 stevel p = c; 583 0 stevel c = p->v_left; 584 0 stevel } 585 0 stevel /* 586 0 stevel * Move c into where p is. 587 0 stevel */ 588 0 stevel pp = p->v_parent; 589 0 stevel f = pp->v_right == p; 590 0 stevel if (pp->v_link[f] = c) 591 0 stevel c->v_parent = pp; 592 0 stevel /* 593 0 stevel * Free the deleted node, and rebalance. 594 0 stevel */ 595 559 nakanon xfree(p); 596 0 stevel balance(pp, f, 1); 597 0 stevel } 598 0 stevel 599 356 muffin void 600 356 muffin setNS(tchar *cp) 601 0 stevel { 602 0 stevel #ifdef TRACE 603 0 stevel tprintf("TRACE- setNS()\n"); 604 0 stevel #endif 605 0 stevel 606 559 nakanon set(cp, S_ /* "" */); 607 0 stevel } 608 0 stevel 609 356 muffin void 610 356 muffin shift(tchar **v) 611 0 stevel { 612 356 muffin struct varent *argv; 613 356 muffin tchar *name; 614 0 stevel 615 0 stevel #ifdef TRACE 616 0 stevel tprintf("TRACE- shift()\n"); 617 0 stevel #endif 618 0 stevel v++; 619 0 stevel name = *v; 620 0 stevel if (name == 0) 621 559 nakanon name = S_argv /* "argv" */; 622 0 stevel else 623 0 stevel (void) strip(name); 624 0 stevel argv = adrof(name); 625 0 stevel if (argv == 0) 626 0 stevel udvar(name); 627 0 stevel if (argv->vec[0] == 0) 628 0 stevel bferr("No more words"); 629 0 stevel lshift(argv->vec, 1); 630 0 stevel } 631 0 stevel 632 356 muffin void 633 356 muffin exportpath(tchar **val) 634 0 stevel { 635 0 stevel tchar exppath[PATHSIZ]; 636 0 stevel 637 0 stevel #ifdef TRACE 638 0 stevel tprintf("TRACE- exportpath()\n"); 639 0 stevel #endif 640 0 stevel exppath[0] = 0; 641 0 stevel if (val) 642 0 stevel while (*val) { 643 0 stevel if (strlen_(*val) + strlen_(exppath) + 2 > PATHSIZ) { 644 0 stevel printf("Warning: ridiculously long PATH truncated\n"); 645 0 stevel break; 646 0 stevel } 647 0 stevel (void) strcat_(exppath, *val++); 648 559 nakanon if (*val == 0 || eq(*val, S_RPAR /* ")" */)) 649 0 stevel break; 650 559 nakanon (void) strcat_(exppath, S_COLON /* ":" */); 651 0 stevel } 652 559 nakanon local_setenv(S_PATH /* "PATH" */, exppath); 653 0 stevel } 654 0 stevel 655 0 stevel /* macros to do single rotations on node p */ 656 559 nakanon #define rright(p) (\ 657 0 stevel t = (p)->v_left,\ 658 0 stevel (t)->v_parent = (p)->v_parent,\ 659 0 stevel ((p)->v_left = t->v_right) ? (t->v_right->v_parent = (p)) : 0,\ 660 0 stevel (t->v_right = (p))->v_parent = t,\ 661 0 stevel (p) = t) 662 559 nakanon #define rleft(p) (\ 663 0 stevel t = (p)->v_right,\ 664 0 stevel (t)->v_parent = (p)->v_parent,\ 665 0 stevel ((p)->v_right = t->v_left) ? (t->v_left->v_parent = (p)) : 0,\ 666 0 stevel (t->v_left = (p))->v_parent = t,\ 667 0 stevel (p) = t) 668 0 stevel 669 0 stevel /* 670 0 stevel * Rebalance a tree, starting at p and up. 671 0 stevel * F == 0 means we've come from p's left child. 672 0 stevel * D == 1 means we've just done a delete, otherwise an insert. 673 0 stevel */ 674 356 muffin void 675 356 muffin balance(struct varent *p, int f, int d) 676 0 stevel { 677 356 muffin struct varent *pp; 678 356 muffin struct varent *t; /* used by the rotate macros */ 679 356 muffin int ff; 680 0 stevel 681 0 stevel #ifdef TRACE 682 0 stevel tprintf("TRACE- balance()\n"); 683 0 stevel #endif 684 0 stevel /* 685 0 stevel * Ok, from here on, p is the node we're operating on; 686 0 stevel * pp is it's parent; f is the branch of p from which we have come; 687 0 stevel * ff is the branch of pp which is p. 688 0 stevel */ 689 0 stevel for (; pp = p->v_parent; p = pp, f = ff) { 690 0 stevel ff = pp->v_right == p; 691 0 stevel if (f ^ d) { /* right heavy */ 692 0 stevel switch (p->v_bal) { 693 0 stevel case -1: /* was left heavy */ 694 0 stevel p->v_bal = 0; 695 0 stevel break; 696 0 stevel case 0: /* was balanced */ 697 0 stevel p->v_bal = 1; 698 0 stevel break; 699 0 stevel case 1: /* was already right heavy */ 700 0 stevel switch (p->v_right->v_bal) { 701 0 stevel case 1: /* sigle rotate */ 702 0 stevel pp->v_link[ff] = rleft(p); 703 0 stevel p->v_left->v_bal = 0; 704 0 stevel p->v_bal = 0; 705 0 stevel break; 706 0 stevel case 0: /* single rotate */ 707 0 stevel pp->v_link[ff] = rleft(p); 708 0 stevel p->v_left->v_bal = 1; 709 0 stevel p->v_bal = -1; 710 0 stevel break; 711 0 stevel case -1: /* double rotate */ 712 0 stevel rright(p->v_right); 713 0 stevel pp->v_link[ff] = rleft(p); 714 0 stevel p->v_left->v_bal = 715 0 stevel p->v_bal < 1 ? 0 : -1; 716 0 stevel p->v_right->v_bal = 717 0 stevel p->v_bal > -1 ? 0 : 1; 718 0 stevel p->v_bal = 0; 719 0 stevel break; 720 0 stevel } 721 0 stevel break; 722 0 stevel } 723 0 stevel } else { /* left heavy */ 724 0 stevel switch (p->v_bal) { 725 0 stevel case 1: /* was right heavy */ 726 0 stevel p->v_bal = 0; 727 0 stevel break; 728 0 stevel case 0: /* was balanced */ 729 0 stevel p->v_bal = -1; 730 0 stevel break; 731 0 stevel case -1: /* was already left heavy */ 732 0 stevel switch (p->v_left->v_bal) { 733 0 stevel case -1: /* single rotate */ 734 0 stevel pp->v_link[ff] = rright(p); 735 0 stevel p->v_right->v_bal = 0; 736 0 stevel p->v_bal = 0; 737 0 stevel break; 738 0 stevel case 0: /* signle rotate */ 739 0 stevel pp->v_link[ff] = rright(p); 740 0 stevel p->v_right->v_bal = -1; 741 0 stevel p->v_bal = 1; 742 0 stevel break; 743 0 stevel case 1: /* double rotate */ 744 0 stevel rleft(p->v_left); 745 0 stevel pp->v_link[ff] = rright(p); 746 0 stevel p->v_left->v_bal = 747 0 stevel p->v_bal < 1 ? 0 : -1; 748 0 stevel p->v_right->v_bal = 749 0 stevel p->v_bal > -1 ? 0 : 1; 750 0 stevel p->v_bal = 0; 751 0 stevel break; 752 0 stevel } 753 0 stevel break; 754 0 stevel } 755 0 stevel } 756 0 stevel /* 757 0 stevel * If from insert, then we terminate when p is balanced. 758 0 stevel * If from delete, then we terminate when p is unbalanced. 759 0 stevel */ 760 0 stevel if ((p->v_bal == 0) ^ d) 761 0 stevel break; 762 0 stevel } 763 0 stevel } 764 0 stevel 765 356 muffin void 766 356 muffin plist(struct varent *p) 767 0 stevel { 768 356 muffin struct varent *c; 769 356 muffin int len; 770 0 stevel 771 0 stevel #ifdef TRACE 772 0 stevel tprintf("TRACE- plist()\n"); 773 0 stevel #endif 774 0 stevel if (setintr) 775 0 stevel (void) sigsetmask(sigblock(0) & ~ sigmask(SIGINT)); 776 0 stevel for (;;) { 777 0 stevel while (p->v_left) 778 0 stevel p = p->v_left; 779 0 stevel x: 780 0 stevel if (p->v_parent == 0) /* is it the header? */ 781 0 stevel return; 782 0 stevel len = blklen(p->vec); 783 0 stevel printf("%t", p->v_name); 784 0 stevel Putchar('\t'); 785 0 stevel if (len != 1) 786 0 stevel Putchar('('); 787 0 stevel blkpr(p->vec); 788 0 stevel if (len != 1) 789 0 stevel Putchar(')'); 790 0 stevel Putchar('\n'); 791 0 stevel if (p->v_right) { 792 0 stevel p = p->v_right; 793 0 stevel continue; 794 0 stevel } 795 0 stevel do { 796 0 stevel c = p; 797 0 stevel p = p->v_parent; 798 0 stevel } while (p->v_right == c); 799 0 stevel goto x; 800 0 stevel } 801 0 stevel } 802