17c478bd9Sstevel@tonic-gate /*
26c02b4a4Smuffin * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
37c478bd9Sstevel@tonic-gate * Use is subject to license terms.
47c478bd9Sstevel@tonic-gate */
57c478bd9Sstevel@tonic-gate
67c478bd9Sstevel@tonic-gate /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
77c478bd9Sstevel@tonic-gate /* All Rights Reserved */
87c478bd9Sstevel@tonic-gate
97c478bd9Sstevel@tonic-gate /*
107c478bd9Sstevel@tonic-gate * Copyright (c) 1980 Regents of the University of California.
117c478bd9Sstevel@tonic-gate * All rights reserved. The Berkeley Software License Agreement
127c478bd9Sstevel@tonic-gate * specifies the terms and conditions for redistribution.
137c478bd9Sstevel@tonic-gate */
147c478bd9Sstevel@tonic-gate
157c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
167c478bd9Sstevel@tonic-gate
177c478bd9Sstevel@tonic-gate #include "sh.h"
187c478bd9Sstevel@tonic-gate #include "sh.tconst.h"
196c02b4a4Smuffin extern int didchdir;
207c478bd9Sstevel@tonic-gate
217c478bd9Sstevel@tonic-gate /*
227c478bd9Sstevel@tonic-gate * C Shell
237c478bd9Sstevel@tonic-gate */
247c478bd9Sstevel@tonic-gate
256c02b4a4Smuffin void asx(tchar *, int, tchar *);
266c02b4a4Smuffin void putn1(int);
276c02b4a4Smuffin void set(tchar *, tchar *);
286c02b4a4Smuffin void set1(tchar *, tchar **, struct varent *);
296c02b4a4Smuffin void setq(tchar *, tchar **, struct varent *);
306c02b4a4Smuffin void unset1(tchar *[], struct varent *);
316c02b4a4Smuffin void unsetv1(struct varent *);
326c02b4a4Smuffin void exportpath(tchar **);
336c02b4a4Smuffin void balance(struct varent *, int, int);
346c02b4a4Smuffin tchar *operate(tchar, tchar *, tchar *);
356c02b4a4Smuffin tchar *getinx(tchar *, int *);
366c02b4a4Smuffin tchar *xset(tchar *, tchar ***);
376c02b4a4Smuffin struct varent *getvx(tchar *, int);
386c02b4a4Smuffin
396c02b4a4Smuffin void
doset(tchar ** v)406c02b4a4Smuffin doset(tchar **v)
417c478bd9Sstevel@tonic-gate {
426c02b4a4Smuffin tchar *p;
437c478bd9Sstevel@tonic-gate tchar *vp, op;
447c478bd9Sstevel@tonic-gate tchar **vecp;
457c478bd9Sstevel@tonic-gate bool hadsub;
467c478bd9Sstevel@tonic-gate int subscr;
477c478bd9Sstevel@tonic-gate tchar *retp;
487c478bd9Sstevel@tonic-gate
497c478bd9Sstevel@tonic-gate #ifdef TRACE
507c478bd9Sstevel@tonic-gate tprintf("TRACE- doset()\n");
517c478bd9Sstevel@tonic-gate #endif
527c478bd9Sstevel@tonic-gate v++;
537c478bd9Sstevel@tonic-gate p = *v++;
547c478bd9Sstevel@tonic-gate if (p == 0) {
557c478bd9Sstevel@tonic-gate prvars();
567c478bd9Sstevel@tonic-gate return;
577c478bd9Sstevel@tonic-gate }
587c478bd9Sstevel@tonic-gate do {
597c478bd9Sstevel@tonic-gate hadsub = 0;
607c478bd9Sstevel@tonic-gate /*
617c478bd9Sstevel@tonic-gate * check for proper variable syntax
627c478bd9Sstevel@tonic-gate * must be alphanumeric, start with a letter and
637c478bd9Sstevel@tonic-gate * be at most 20 characters
647c478bd9Sstevel@tonic-gate */
657c478bd9Sstevel@tonic-gate for (vp = p; alnum(*p); p++)
667c478bd9Sstevel@tonic-gate continue;
677c478bd9Sstevel@tonic-gate if (vp == p || !letter(*vp))
687c478bd9Sstevel@tonic-gate goto setsyn;
697c478bd9Sstevel@tonic-gate if ((p - vp) > MAX_VAR_LEN)
707c478bd9Sstevel@tonic-gate bferr("Variable name too long");
717c478bd9Sstevel@tonic-gate if (*p == '[') {
727c478bd9Sstevel@tonic-gate hadsub++;
737c478bd9Sstevel@tonic-gate p = getinx(p, &subscr);
747c478bd9Sstevel@tonic-gate }
757c478bd9Sstevel@tonic-gate if (op = *p) {
767c478bd9Sstevel@tonic-gate *p++ = 0;
777c478bd9Sstevel@tonic-gate if (*p == 0 && *v && **v == '(')
787c478bd9Sstevel@tonic-gate p = *v++;
797c478bd9Sstevel@tonic-gate } else if (*v && eq(*v, S_EQ /* "=" */)) {
807c478bd9Sstevel@tonic-gate op = '=', v++;
817c478bd9Sstevel@tonic-gate if (*v)
827c478bd9Sstevel@tonic-gate p = *v++;
837c478bd9Sstevel@tonic-gate }
847c478bd9Sstevel@tonic-gate if (op && op != '=')
857c478bd9Sstevel@tonic-gate setsyn:
867c478bd9Sstevel@tonic-gate bferr("Syntax error");
877c478bd9Sstevel@tonic-gate if (eq(p, S_LPAR /* "(" */)) {
886c02b4a4Smuffin tchar **e = v;
897c478bd9Sstevel@tonic-gate
907c478bd9Sstevel@tonic-gate if (hadsub)
917c478bd9Sstevel@tonic-gate goto setsyn;
927c478bd9Sstevel@tonic-gate for (;;) {
937c478bd9Sstevel@tonic-gate if (!*e)
947c478bd9Sstevel@tonic-gate bferr("Missing )");
957c478bd9Sstevel@tonic-gate if (**e == ')')
967c478bd9Sstevel@tonic-gate break;
977c478bd9Sstevel@tonic-gate e++;
987c478bd9Sstevel@tonic-gate }
997c478bd9Sstevel@tonic-gate p = *e;
1007c478bd9Sstevel@tonic-gate *e = 0;
1017c478bd9Sstevel@tonic-gate vecp = saveblk(v);
1027c478bd9Sstevel@tonic-gate set1(vp, vecp, &shvhed);
1037c478bd9Sstevel@tonic-gate *e = p;
1047c478bd9Sstevel@tonic-gate v = e + 1;
1057c478bd9Sstevel@tonic-gate } else if (hadsub) {
1067c478bd9Sstevel@tonic-gate retp = savestr(p);
1077c478bd9Sstevel@tonic-gate asx(vp, subscr, retp);
1087c478bd9Sstevel@tonic-gate xfree(retp);
1097c478bd9Sstevel@tonic-gate retp = 0;
1107c478bd9Sstevel@tonic-gate } else
1117c478bd9Sstevel@tonic-gate set(vp, savestr(p));
1127c478bd9Sstevel@tonic-gate if (eq(vp, S_path /* "path" */)) {
1137c478bd9Sstevel@tonic-gate exportpath(adrof(S_path /* "path" */)->vec);
1147c478bd9Sstevel@tonic-gate dohash(xhash);
1157c478bd9Sstevel@tonic-gate } else if (eq(vp, S_histchars /* "histchars" */)) {
1166c02b4a4Smuffin tchar *p = value(S_histchars /* "histchars" */);
1177c478bd9Sstevel@tonic-gate HIST = *p++;
1187c478bd9Sstevel@tonic-gate HISTSUB = *p;
1197c478bd9Sstevel@tonic-gate } else if (eq(vp, S_user /* "user" */))
1207c478bd9Sstevel@tonic-gate local_setenv(S_USER /* "USER" */, value(vp));
1217c478bd9Sstevel@tonic-gate else if (eq(vp, S_term /* "term" */))
1227c478bd9Sstevel@tonic-gate local_setenv(S_TERM /* "TERM" */, value(vp));
1237c478bd9Sstevel@tonic-gate else if (eq(vp, S_home /* "home" */))
1247c478bd9Sstevel@tonic-gate local_setenv(S_HOME /* "HOME" */, value(vp));
1257c478bd9Sstevel@tonic-gate #ifdef FILEC
1267c478bd9Sstevel@tonic-gate else if (eq(vp, S_filec /* "filec" */))
1277c478bd9Sstevel@tonic-gate filec = 1;
1287c478bd9Sstevel@tonic-gate else if (eq(vp, S_cdpath /* "cdpath" */))
1297c478bd9Sstevel@tonic-gate dohash(xhash2);
1307c478bd9Sstevel@tonic-gate #endif
1317c478bd9Sstevel@tonic-gate } while (p = *v++);
1327c478bd9Sstevel@tonic-gate }
1337c478bd9Sstevel@tonic-gate
1347c478bd9Sstevel@tonic-gate tchar *
getinx(tchar * cp,int * ip)1356c02b4a4Smuffin getinx(tchar *cp, int *ip)
1367c478bd9Sstevel@tonic-gate {
1377c478bd9Sstevel@tonic-gate
1387c478bd9Sstevel@tonic-gate #ifdef TRACE
1397c478bd9Sstevel@tonic-gate tprintf("TRACE- getinx()\n");
1407c478bd9Sstevel@tonic-gate #endif
1417c478bd9Sstevel@tonic-gate *ip = 0;
1427c478bd9Sstevel@tonic-gate *cp++ = 0;
1437c478bd9Sstevel@tonic-gate while (*cp && digit(*cp))
1447c478bd9Sstevel@tonic-gate *ip = *ip * 10 + *cp++ - '0';
1457c478bd9Sstevel@tonic-gate if (*cp++ != ']')
1467c478bd9Sstevel@tonic-gate bferr("Subscript error");
1477c478bd9Sstevel@tonic-gate return (cp);
1487c478bd9Sstevel@tonic-gate }
1497c478bd9Sstevel@tonic-gate
1506c02b4a4Smuffin void
asx(tchar * vp,int subscr,tchar * p)1516c02b4a4Smuffin asx(tchar *vp, int subscr, tchar *p)
1527c478bd9Sstevel@tonic-gate {
1536c02b4a4Smuffin struct varent *v = getvx(vp, subscr);
1547c478bd9Sstevel@tonic-gate
1557c478bd9Sstevel@tonic-gate #ifdef TRACE
1567c478bd9Sstevel@tonic-gate tprintf("TRACE- asx()\n");
1577c478bd9Sstevel@tonic-gate #endif
1587c478bd9Sstevel@tonic-gate xfree(v->vec[subscr - 1]);
1597c478bd9Sstevel@tonic-gate v->vec[subscr - 1] = globone(p);
1607c478bd9Sstevel@tonic-gate }
1617c478bd9Sstevel@tonic-gate
1627c478bd9Sstevel@tonic-gate struct varent *
getvx(tchar * vp,int subscr)1636c02b4a4Smuffin getvx(tchar *vp, int subscr)
1647c478bd9Sstevel@tonic-gate {
1656c02b4a4Smuffin struct varent *v = adrof(vp);
1667c478bd9Sstevel@tonic-gate
1677c478bd9Sstevel@tonic-gate #ifdef TRACE
1687c478bd9Sstevel@tonic-gate tprintf("TRACE- getvx()\n");
1697c478bd9Sstevel@tonic-gate #endif
1707c478bd9Sstevel@tonic-gate if (v == 0)
1717c478bd9Sstevel@tonic-gate udvar(vp);
1727c478bd9Sstevel@tonic-gate if (subscr < 1 || subscr > blklen(v->vec))
1737c478bd9Sstevel@tonic-gate bferr("Subscript out of range");
1747c478bd9Sstevel@tonic-gate return (v);
1757c478bd9Sstevel@tonic-gate }
1767c478bd9Sstevel@tonic-gate
1777c478bd9Sstevel@tonic-gate tchar plusplus[2] = { '1', 0 };
1787c478bd9Sstevel@tonic-gate
1796c02b4a4Smuffin void
dolet(tchar ** v)1806c02b4a4Smuffin dolet(tchar **v)
1817c478bd9Sstevel@tonic-gate {
1826c02b4a4Smuffin tchar *p;
1837c478bd9Sstevel@tonic-gate tchar *vp, c, op;
1847c478bd9Sstevel@tonic-gate bool hadsub;
1857c478bd9Sstevel@tonic-gate int subscr;
1867c478bd9Sstevel@tonic-gate
1877c478bd9Sstevel@tonic-gate v++;
1887c478bd9Sstevel@tonic-gate p = *v++;
1897c478bd9Sstevel@tonic-gate if (p == 0) {
1907c478bd9Sstevel@tonic-gate prvars();
1917c478bd9Sstevel@tonic-gate return;
1927c478bd9Sstevel@tonic-gate }
1937c478bd9Sstevel@tonic-gate do {
1947c478bd9Sstevel@tonic-gate hadsub = 0;
1957c478bd9Sstevel@tonic-gate for (vp = p; alnum(*p); p++)
1967c478bd9Sstevel@tonic-gate continue;
1977c478bd9Sstevel@tonic-gate if (vp == p || !letter(*vp))
1987c478bd9Sstevel@tonic-gate goto letsyn;
1997c478bd9Sstevel@tonic-gate if (*p == '[') {
2007c478bd9Sstevel@tonic-gate hadsub++;
2017c478bd9Sstevel@tonic-gate p = getinx(p, &subscr);
2027c478bd9Sstevel@tonic-gate }
2037c478bd9Sstevel@tonic-gate if (*p == 0 && *v)
2047c478bd9Sstevel@tonic-gate p = *v++;
2057c478bd9Sstevel@tonic-gate if (op = *p)
2067c478bd9Sstevel@tonic-gate *p++ = 0;
2077c478bd9Sstevel@tonic-gate else
2087c478bd9Sstevel@tonic-gate goto letsyn;
2097c478bd9Sstevel@tonic-gate vp = savestr(vp);
2107c478bd9Sstevel@tonic-gate if (op == '=') {
2117c478bd9Sstevel@tonic-gate c = '=';
2127c478bd9Sstevel@tonic-gate p = xset(p, &v);
2137c478bd9Sstevel@tonic-gate } else {
2147c478bd9Sstevel@tonic-gate c = *p++;
2157c478bd9Sstevel@tonic-gate /* if (any(c, "+-")) { */
2167c478bd9Sstevel@tonic-gate if (c == '+' || c == '-') {
2177c478bd9Sstevel@tonic-gate if (c != op || *p)
2187c478bd9Sstevel@tonic-gate goto letsyn;
2197c478bd9Sstevel@tonic-gate p = plusplus;
2207c478bd9Sstevel@tonic-gate } else {
2217c478bd9Sstevel@tonic-gate /* if (any(op, "<>")) { */
2227c478bd9Sstevel@tonic-gate if (op == '<' || op == '>') {
2237c478bd9Sstevel@tonic-gate if (c != op)
2247c478bd9Sstevel@tonic-gate goto letsyn;
2257c478bd9Sstevel@tonic-gate c = *p++;
2267c478bd9Sstevel@tonic-gate letsyn:
2277c478bd9Sstevel@tonic-gate bferr("Syntax error");
2287c478bd9Sstevel@tonic-gate }
2297c478bd9Sstevel@tonic-gate if (c != '=')
2307c478bd9Sstevel@tonic-gate goto letsyn;
2317c478bd9Sstevel@tonic-gate p = xset(p, &v);
2327c478bd9Sstevel@tonic-gate }
2337c478bd9Sstevel@tonic-gate }
2347c478bd9Sstevel@tonic-gate if (op == '=')
2357c478bd9Sstevel@tonic-gate if (hadsub)
2367c478bd9Sstevel@tonic-gate asx(vp, subscr, p);
2377c478bd9Sstevel@tonic-gate else
2387c478bd9Sstevel@tonic-gate set(vp, p);
2397c478bd9Sstevel@tonic-gate else
2407c478bd9Sstevel@tonic-gate if (hadsub)
2417c478bd9Sstevel@tonic-gate #ifndef V6
2427c478bd9Sstevel@tonic-gate /* avoid bug in vax CC */
2437c478bd9Sstevel@tonic-gate {
2447c478bd9Sstevel@tonic-gate struct varent *gv = getvx(vp, subscr);
2457c478bd9Sstevel@tonic-gate
2467c478bd9Sstevel@tonic-gate asx(vp, subscr, operate(op, gv->vec[subscr - 1], p));
2477c478bd9Sstevel@tonic-gate }
2487c478bd9Sstevel@tonic-gate #else
2497c478bd9Sstevel@tonic-gate asx(vp, subscr, operate(op, getvx(vp, subscr)->vec[subscr - 1], p));
2507c478bd9Sstevel@tonic-gate #endif
2517c478bd9Sstevel@tonic-gate else
2527c478bd9Sstevel@tonic-gate set(vp, operate(op, value(vp), p));
2537c478bd9Sstevel@tonic-gate if (eq(vp, S_path /* "path" */)) {
2547c478bd9Sstevel@tonic-gate exportpath(adrof(S_path /* "path" */)->vec);
2557c478bd9Sstevel@tonic-gate dohash(xhash);
2567c478bd9Sstevel@tonic-gate }
2577c478bd9Sstevel@tonic-gate
2587c478bd9Sstevel@tonic-gate if (eq(vp, S_cdpath /* "cdpath" */))
2597c478bd9Sstevel@tonic-gate dohash(xhash2);
2607c478bd9Sstevel@tonic-gate
261*65b0c20eSnakanon xfree(vp);
2627c478bd9Sstevel@tonic-gate if (c != '=')
263*65b0c20eSnakanon xfree(p);
2647c478bd9Sstevel@tonic-gate } while (p = *v++);
2657c478bd9Sstevel@tonic-gate }
2667c478bd9Sstevel@tonic-gate
2677c478bd9Sstevel@tonic-gate tchar *
xset(tchar * cp,tchar *** vp)2686c02b4a4Smuffin xset(tchar *cp, tchar ***vp)
2697c478bd9Sstevel@tonic-gate {
2706c02b4a4Smuffin tchar *dp;
2717c478bd9Sstevel@tonic-gate
2727c478bd9Sstevel@tonic-gate #ifdef TRACE
2737c478bd9Sstevel@tonic-gate tprintf("TRACE- xset()\n");
2747c478bd9Sstevel@tonic-gate #endif
2757c478bd9Sstevel@tonic-gate if (*cp) {
2767c478bd9Sstevel@tonic-gate dp = savestr(cp);
2777c478bd9Sstevel@tonic-gate --(*vp);
2787c478bd9Sstevel@tonic-gate xfree(**vp);
2797c478bd9Sstevel@tonic-gate **vp = dp;
2807c478bd9Sstevel@tonic-gate }
2817c478bd9Sstevel@tonic-gate return (putn(exp(vp)));
2827c478bd9Sstevel@tonic-gate }
2837c478bd9Sstevel@tonic-gate
2847c478bd9Sstevel@tonic-gate tchar *
operate(tchar op,tchar * vp,tchar * p)2856c02b4a4Smuffin operate(tchar op, tchar *vp, tchar *p)
2867c478bd9Sstevel@tonic-gate {
2877c478bd9Sstevel@tonic-gate tchar opr[2];
2887c478bd9Sstevel@tonic-gate tchar *vec[5];
2896c02b4a4Smuffin tchar **v = vec;
2907c478bd9Sstevel@tonic-gate tchar **vecp = v;
2916c02b4a4Smuffin int i;
2927c478bd9Sstevel@tonic-gate
2937c478bd9Sstevel@tonic-gate if (op != '=') {
2947c478bd9Sstevel@tonic-gate if (*vp)
2957c478bd9Sstevel@tonic-gate *v++ = vp;
2967c478bd9Sstevel@tonic-gate opr[0] = op;
2977c478bd9Sstevel@tonic-gate opr[1] = 0;
2987c478bd9Sstevel@tonic-gate *v++ = opr;
2997c478bd9Sstevel@tonic-gate if (op == '<' || op == '>')
3007c478bd9Sstevel@tonic-gate *v++ = opr;
3017c478bd9Sstevel@tonic-gate }
3027c478bd9Sstevel@tonic-gate *v++ = p;
3037c478bd9Sstevel@tonic-gate *v++ = 0;
3047c478bd9Sstevel@tonic-gate i = exp(&vecp);
3057c478bd9Sstevel@tonic-gate if (*vecp)
3067c478bd9Sstevel@tonic-gate bferr("Expression syntax");
3077c478bd9Sstevel@tonic-gate return (putn(i));
3087c478bd9Sstevel@tonic-gate }
3097c478bd9Sstevel@tonic-gate
3107c478bd9Sstevel@tonic-gate static tchar *putp;
3117c478bd9Sstevel@tonic-gate
3127c478bd9Sstevel@tonic-gate tchar *
putn(int n)3136c02b4a4Smuffin putn(int n)
3147c478bd9Sstevel@tonic-gate {
3157c478bd9Sstevel@tonic-gate static tchar number[15];
3167c478bd9Sstevel@tonic-gate
3177c478bd9Sstevel@tonic-gate #ifdef TRACE
3187c478bd9Sstevel@tonic-gate tprintf("TRACE- putn()\n");
3197c478bd9Sstevel@tonic-gate #endif
3207c478bd9Sstevel@tonic-gate putp = number;
3217c478bd9Sstevel@tonic-gate if (n < 0) {
3227c478bd9Sstevel@tonic-gate n = -n;
3237c478bd9Sstevel@tonic-gate *putp++ = '-';
3247c478bd9Sstevel@tonic-gate }
3257c478bd9Sstevel@tonic-gate if (sizeof (int) == 2 && n == -32768) {
3267c478bd9Sstevel@tonic-gate *putp++ = '3';
3277c478bd9Sstevel@tonic-gate n = 2768;
3287c478bd9Sstevel@tonic-gate #ifdef pdp11
3297c478bd9Sstevel@tonic-gate }
3307c478bd9Sstevel@tonic-gate #else
3317c478bd9Sstevel@tonic-gate } else if (sizeof (int) == 4 && n == 0x80000000) {
3327c478bd9Sstevel@tonic-gate *putp++ = '2';
3337c478bd9Sstevel@tonic-gate n = 147483648;
3347c478bd9Sstevel@tonic-gate }
3357c478bd9Sstevel@tonic-gate #endif
3367c478bd9Sstevel@tonic-gate putn1(n);
3377c478bd9Sstevel@tonic-gate *putp = 0;
3387c478bd9Sstevel@tonic-gate return (savestr(number));
3397c478bd9Sstevel@tonic-gate }
3407c478bd9Sstevel@tonic-gate
3416c02b4a4Smuffin void
putn1(int n)3426c02b4a4Smuffin putn1(int n)
3437c478bd9Sstevel@tonic-gate {
3447c478bd9Sstevel@tonic-gate #ifdef TRACE
3457c478bd9Sstevel@tonic-gate tprintf("TRACE- putn1()\n");
3467c478bd9Sstevel@tonic-gate #endif
3477c478bd9Sstevel@tonic-gate if (n > 9)
3487c478bd9Sstevel@tonic-gate putn1(n / 10);
3497c478bd9Sstevel@tonic-gate *putp++ = n % 10 + '0';
3507c478bd9Sstevel@tonic-gate }
3517c478bd9Sstevel@tonic-gate
3526c02b4a4Smuffin int
getn(tchar * cp)3536c02b4a4Smuffin getn(tchar *cp)
3547c478bd9Sstevel@tonic-gate {
3556c02b4a4Smuffin int n;
3567c478bd9Sstevel@tonic-gate int sign;
3577c478bd9Sstevel@tonic-gate
3587c478bd9Sstevel@tonic-gate #ifdef TRACE
3597c478bd9Sstevel@tonic-gate tprintf("TRACE- getn()\n");
3607c478bd9Sstevel@tonic-gate #endif
3617c478bd9Sstevel@tonic-gate sign = 0;
3627c478bd9Sstevel@tonic-gate if (cp[0] == '+' && cp[1])
3637c478bd9Sstevel@tonic-gate cp++;
3647c478bd9Sstevel@tonic-gate if (*cp == '-') {
3657c478bd9Sstevel@tonic-gate sign++;
3667c478bd9Sstevel@tonic-gate cp++;
3677c478bd9Sstevel@tonic-gate if (!digit(*cp))
3687c478bd9Sstevel@tonic-gate goto badnum;
3697c478bd9Sstevel@tonic-gate }
3707c478bd9Sstevel@tonic-gate n = 0;
3717c478bd9Sstevel@tonic-gate while (digit(*cp))
3727c478bd9Sstevel@tonic-gate n = n * 10 + *cp++ - '0';
3737c478bd9Sstevel@tonic-gate if (*cp)
3747c478bd9Sstevel@tonic-gate goto badnum;
3757c478bd9Sstevel@tonic-gate return (sign ? -n : n);
3767c478bd9Sstevel@tonic-gate badnum:
3777c478bd9Sstevel@tonic-gate bferr("Badly formed number");
3787c478bd9Sstevel@tonic-gate return (0);
3797c478bd9Sstevel@tonic-gate }
3807c478bd9Sstevel@tonic-gate
3817c478bd9Sstevel@tonic-gate tchar *
value1(tchar * var,struct varent * head)3826c02b4a4Smuffin value1(tchar *var, struct varent *head)
3837c478bd9Sstevel@tonic-gate {
3846c02b4a4Smuffin struct varent *vp;
3857c478bd9Sstevel@tonic-gate
3867c478bd9Sstevel@tonic-gate #ifdef TRACE
3877c478bd9Sstevel@tonic-gate tprintf("TRACE- value1()\n");
3887c478bd9Sstevel@tonic-gate #endif
3897c478bd9Sstevel@tonic-gate vp = adrof1(var, head);
3907c478bd9Sstevel@tonic-gate return (vp == 0 || vp->vec[0] == 0 ? S_ /* "" */ : vp->vec[0]);
3917c478bd9Sstevel@tonic-gate }
3927c478bd9Sstevel@tonic-gate
3937c478bd9Sstevel@tonic-gate struct varent *
madrof(tchar * pat,struct varent * vp)3946c02b4a4Smuffin madrof(tchar *pat, struct varent *vp)
3957c478bd9Sstevel@tonic-gate {
3966c02b4a4Smuffin struct varent *vp1;
3977c478bd9Sstevel@tonic-gate
3987c478bd9Sstevel@tonic-gate #ifdef TRACE
3997c478bd9Sstevel@tonic-gate tprintf("TRACE- madrof()\n");
4007c478bd9Sstevel@tonic-gate #endif
4017c478bd9Sstevel@tonic-gate for (; vp; vp = vp->v_right) {
4027c478bd9Sstevel@tonic-gate if (vp->v_left && (vp1 = madrof(pat, vp->v_left)))
4037c478bd9Sstevel@tonic-gate return vp1;
4047c478bd9Sstevel@tonic-gate if (Gmatch(vp->v_name, pat))
4057c478bd9Sstevel@tonic-gate return vp;
4067c478bd9Sstevel@tonic-gate }
4077c478bd9Sstevel@tonic-gate return vp;
4087c478bd9Sstevel@tonic-gate }
4097c478bd9Sstevel@tonic-gate
4107c478bd9Sstevel@tonic-gate struct varent *
adrof1(tchar * name,struct varent * v)4116c02b4a4Smuffin adrof1(tchar *name, struct varent *v)
4127c478bd9Sstevel@tonic-gate {
4136c02b4a4Smuffin int cmp;
4147c478bd9Sstevel@tonic-gate
4157c478bd9Sstevel@tonic-gate #ifdef TRACE
4167c478bd9Sstevel@tonic-gate tprintf("TRACE- adrof1()\n");
4177c478bd9Sstevel@tonic-gate #endif
4187c478bd9Sstevel@tonic-gate v = v->v_left;
4197c478bd9Sstevel@tonic-gate while (v && ((cmp = *name - *v->v_name) ||
4207c478bd9Sstevel@tonic-gate (cmp = strcmp_(name, v->v_name))))
4217c478bd9Sstevel@tonic-gate if (cmp < 0)
4227c478bd9Sstevel@tonic-gate v = v->v_left;
4237c478bd9Sstevel@tonic-gate else
4247c478bd9Sstevel@tonic-gate v = v->v_right;
4257c478bd9Sstevel@tonic-gate return v;
4267c478bd9Sstevel@tonic-gate }
4277c478bd9Sstevel@tonic-gate
4287c478bd9Sstevel@tonic-gate /*
4297c478bd9Sstevel@tonic-gate * The caller is responsible for putting value in a safe place
4307c478bd9Sstevel@tonic-gate */
4316c02b4a4Smuffin void
set(tchar * var,tchar * val)4326c02b4a4Smuffin set(tchar *var, tchar *val)
4337c478bd9Sstevel@tonic-gate {
4346c02b4a4Smuffin tchar **vec = (tchar **)xalloc(2 * sizeof (tchar **));
4357c478bd9Sstevel@tonic-gate
4367c478bd9Sstevel@tonic-gate #ifdef TRACE
4377c478bd9Sstevel@tonic-gate tprintf("TRACE- set()\n");
4387c478bd9Sstevel@tonic-gate #endif
4397c478bd9Sstevel@tonic-gate vec[0] = onlyread(val) ? savestr(val) : val;
4407c478bd9Sstevel@tonic-gate vec[1] = 0;
4417c478bd9Sstevel@tonic-gate set1(var, vec, &shvhed);
4427c478bd9Sstevel@tonic-gate }
4437c478bd9Sstevel@tonic-gate
4446c02b4a4Smuffin void
set1(tchar * var,tchar ** vec,struct varent * head)4456c02b4a4Smuffin set1(tchar *var, tchar **vec, struct varent *head)
4467c478bd9Sstevel@tonic-gate {
4476c02b4a4Smuffin tchar **oldv = vec;
4487c478bd9Sstevel@tonic-gate
4497c478bd9Sstevel@tonic-gate #ifdef TRACE
4507c478bd9Sstevel@tonic-gate tprintf("TRACE- set1()\n");
4517c478bd9Sstevel@tonic-gate #endif
4527c478bd9Sstevel@tonic-gate gflag = 0;
453*65b0c20eSnakanon /*
454*65b0c20eSnakanon * If setting cwd variable via "set cwd=/tmp/something"
4557c478bd9Sstevel@tonic-gate * then do globbing. But if we are setting the cwd
4567c478bd9Sstevel@tonic-gate * becuz of a cd, chdir, pushd, popd, do not do globbing.
4577c478bd9Sstevel@tonic-gate */
4587c478bd9Sstevel@tonic-gate if ((!(eq(var, S_cwd))) || (eq(var, S_cwd) && (didchdir == 0)))
4597c478bd9Sstevel@tonic-gate {
4607c478bd9Sstevel@tonic-gate tglob(oldv);
4617c478bd9Sstevel@tonic-gate }
4627c478bd9Sstevel@tonic-gate if (gflag) {
4637c478bd9Sstevel@tonic-gate vec = glob(oldv);
4647c478bd9Sstevel@tonic-gate if (vec == 0) {
4657c478bd9Sstevel@tonic-gate bferr("No match");
4667c478bd9Sstevel@tonic-gate blkfree(oldv);
4677c478bd9Sstevel@tonic-gate return;
4687c478bd9Sstevel@tonic-gate }
4697c478bd9Sstevel@tonic-gate blkfree(oldv);
4707c478bd9Sstevel@tonic-gate gargv = 0;
4717c478bd9Sstevel@tonic-gate }
4727c478bd9Sstevel@tonic-gate setq(var, vec, head);
4737c478bd9Sstevel@tonic-gate }
4747c478bd9Sstevel@tonic-gate
4756c02b4a4Smuffin void
setq(tchar * name,tchar ** vec,struct varent * p)4766c02b4a4Smuffin setq(tchar *name, tchar **vec, struct varent *p)
4777c478bd9Sstevel@tonic-gate {
4786c02b4a4Smuffin struct varent *c;
4796c02b4a4Smuffin int f;
4807c478bd9Sstevel@tonic-gate
4817c478bd9Sstevel@tonic-gate #ifdef TRACE
4827c478bd9Sstevel@tonic-gate tprintf("TRACE- setq()\n");
4837c478bd9Sstevel@tonic-gate #endif
4847c478bd9Sstevel@tonic-gate f = 0; /* tree hangs off the header's left link */
4857c478bd9Sstevel@tonic-gate while (c = p->v_link[f]) {
4867c478bd9Sstevel@tonic-gate if ((f = *name - *c->v_name) == 0 &&
4877c478bd9Sstevel@tonic-gate (f = strcmp_(name, c->v_name)) == 0) {
4887c478bd9Sstevel@tonic-gate blkfree(c->vec);
4897c478bd9Sstevel@tonic-gate goto found;
4907c478bd9Sstevel@tonic-gate }
4917c478bd9Sstevel@tonic-gate p = c;
4927c478bd9Sstevel@tonic-gate f = f > 0;
4937c478bd9Sstevel@tonic-gate }
4947c478bd9Sstevel@tonic-gate p->v_link[f] = c = (struct varent *)xalloc(sizeof (struct varent));
4957c478bd9Sstevel@tonic-gate c->v_name = savestr(name);
4967c478bd9Sstevel@tonic-gate c->v_bal = 0;
4977c478bd9Sstevel@tonic-gate c->v_left = c->v_right = 0;
4987c478bd9Sstevel@tonic-gate c->v_parent = p;
4997c478bd9Sstevel@tonic-gate balance(p, f, 0);
5007c478bd9Sstevel@tonic-gate found:
5017c478bd9Sstevel@tonic-gate trim(c->vec = vec);
5027c478bd9Sstevel@tonic-gate }
5037c478bd9Sstevel@tonic-gate
5046c02b4a4Smuffin void
unset(tchar * v[])5056c02b4a4Smuffin unset(tchar *v[])
5067c478bd9Sstevel@tonic-gate {
5077c478bd9Sstevel@tonic-gate
5087c478bd9Sstevel@tonic-gate #ifdef TRACE
5097c478bd9Sstevel@tonic-gate tprintf("TRACE- unset()\n");
5107c478bd9Sstevel@tonic-gate #endif
5117c478bd9Sstevel@tonic-gate unset1(v, &shvhed);
5127c478bd9Sstevel@tonic-gate if (adrof(S_histchars /* "histchars" */) == 0) {
5137c478bd9Sstevel@tonic-gate HIST = '!';
5147c478bd9Sstevel@tonic-gate HISTSUB = '^';
5157c478bd9Sstevel@tonic-gate }
5167c478bd9Sstevel@tonic-gate #ifdef FILEC
5177c478bd9Sstevel@tonic-gate if (adrof(S_filec /* "filec" */) == 0)
5187c478bd9Sstevel@tonic-gate filec = 0;
5197c478bd9Sstevel@tonic-gate #endif
5207c478bd9Sstevel@tonic-gate }
5217c478bd9Sstevel@tonic-gate
5226c02b4a4Smuffin void
unset1(tchar * v[],struct varent * head)5236c02b4a4Smuffin unset1(tchar *v[], struct varent *head)
5247c478bd9Sstevel@tonic-gate {
5256c02b4a4Smuffin struct varent *vp;
5266c02b4a4Smuffin int cnt;
5277c478bd9Sstevel@tonic-gate
5287c478bd9Sstevel@tonic-gate #ifdef TRACE
5297c478bd9Sstevel@tonic-gate tprintf("TRACE- unset1()\n");
5307c478bd9Sstevel@tonic-gate #endif
5317c478bd9Sstevel@tonic-gate while (*++v) {
5327c478bd9Sstevel@tonic-gate cnt = 0;
5337c478bd9Sstevel@tonic-gate while (vp = madrof(*v, head->v_left))
5347c478bd9Sstevel@tonic-gate unsetv1(vp), cnt++;
5357c478bd9Sstevel@tonic-gate if (cnt == 0)
5367c478bd9Sstevel@tonic-gate setname(*v);
5377c478bd9Sstevel@tonic-gate }
5387c478bd9Sstevel@tonic-gate }
5397c478bd9Sstevel@tonic-gate
5406c02b4a4Smuffin void
unsetv(tchar * var)5416c02b4a4Smuffin unsetv(tchar *var)
5427c478bd9Sstevel@tonic-gate {
5436c02b4a4Smuffin struct varent *vp;
5447c478bd9Sstevel@tonic-gate
5457c478bd9Sstevel@tonic-gate #ifdef TRACE
5467c478bd9Sstevel@tonic-gate tprintf("TRACE- unsetv()\n");
5477c478bd9Sstevel@tonic-gate #endif
5487c478bd9Sstevel@tonic-gate if ((vp = adrof1(var, &shvhed)) == 0)
5497c478bd9Sstevel@tonic-gate udvar(var);
5507c478bd9Sstevel@tonic-gate unsetv1(vp);
5517c478bd9Sstevel@tonic-gate }
5527c478bd9Sstevel@tonic-gate
5536c02b4a4Smuffin void
unsetv1(struct varent * p)5546c02b4a4Smuffin unsetv1(struct varent *p)
5557c478bd9Sstevel@tonic-gate {
5566c02b4a4Smuffin struct varent *c, *pp;
5576c02b4a4Smuffin int f;
5587c478bd9Sstevel@tonic-gate
5597c478bd9Sstevel@tonic-gate #ifdef TRACE
5607c478bd9Sstevel@tonic-gate tprintf("TRACE- unsetv1()\n");
5617c478bd9Sstevel@tonic-gate #endif
5627c478bd9Sstevel@tonic-gate /*
5637c478bd9Sstevel@tonic-gate * Free associated memory first to avoid complications.
5647c478bd9Sstevel@tonic-gate */
5657c478bd9Sstevel@tonic-gate blkfree(p->vec);
566*65b0c20eSnakanon xfree(p->v_name);
5677c478bd9Sstevel@tonic-gate /*
5687c478bd9Sstevel@tonic-gate * If p is missing one child, then we can move the other
5697c478bd9Sstevel@tonic-gate * into where p is. Otherwise, we find the predecessor
5707c478bd9Sstevel@tonic-gate * of p, which is guaranteed to have no right child, copy
5717c478bd9Sstevel@tonic-gate * it into p, and move it's left child into it.
5727c478bd9Sstevel@tonic-gate */
5737c478bd9Sstevel@tonic-gate if (p->v_right == 0)
5747c478bd9Sstevel@tonic-gate c = p->v_left;
5757c478bd9Sstevel@tonic-gate else if (p->v_left == 0)
5767c478bd9Sstevel@tonic-gate c = p->v_right;
5777c478bd9Sstevel@tonic-gate else {
5787c478bd9Sstevel@tonic-gate for (c = p->v_left; c->v_right; c = c->v_right)
5797c478bd9Sstevel@tonic-gate ;
5807c478bd9Sstevel@tonic-gate p->v_name = c->v_name;
5817c478bd9Sstevel@tonic-gate p->vec = c->vec;
5827c478bd9Sstevel@tonic-gate p = c;
5837c478bd9Sstevel@tonic-gate c = p->v_left;
5847c478bd9Sstevel@tonic-gate }
5857c478bd9Sstevel@tonic-gate /*
5867c478bd9Sstevel@tonic-gate * Move c into where p is.
5877c478bd9Sstevel@tonic-gate */
5887c478bd9Sstevel@tonic-gate pp = p->v_parent;
5897c478bd9Sstevel@tonic-gate f = pp->v_right == p;
5907c478bd9Sstevel@tonic-gate if (pp->v_link[f] = c)
5917c478bd9Sstevel@tonic-gate c->v_parent = pp;
5927c478bd9Sstevel@tonic-gate /*
5937c478bd9Sstevel@tonic-gate * Free the deleted node, and rebalance.
5947c478bd9Sstevel@tonic-gate */
595*65b0c20eSnakanon xfree(p);
5967c478bd9Sstevel@tonic-gate balance(pp, f, 1);
5977c478bd9Sstevel@tonic-gate }
5987c478bd9Sstevel@tonic-gate
5996c02b4a4Smuffin void
setNS(tchar * cp)6006c02b4a4Smuffin setNS(tchar *cp)
6017c478bd9Sstevel@tonic-gate {
6027c478bd9Sstevel@tonic-gate #ifdef TRACE
6037c478bd9Sstevel@tonic-gate tprintf("TRACE- setNS()\n");
6047c478bd9Sstevel@tonic-gate #endif
6057c478bd9Sstevel@tonic-gate
6067c478bd9Sstevel@tonic-gate set(cp, S_ /* "" */);
6077c478bd9Sstevel@tonic-gate }
6087c478bd9Sstevel@tonic-gate
6096c02b4a4Smuffin void
shift(tchar ** v)6106c02b4a4Smuffin shift(tchar **v)
6117c478bd9Sstevel@tonic-gate {
6126c02b4a4Smuffin struct varent *argv;
6136c02b4a4Smuffin tchar *name;
6147c478bd9Sstevel@tonic-gate
6157c478bd9Sstevel@tonic-gate #ifdef TRACE
6167c478bd9Sstevel@tonic-gate tprintf("TRACE- shift()\n");
6177c478bd9Sstevel@tonic-gate #endif
6187c478bd9Sstevel@tonic-gate v++;
6197c478bd9Sstevel@tonic-gate name = *v;
6207c478bd9Sstevel@tonic-gate if (name == 0)
6217c478bd9Sstevel@tonic-gate name = S_argv /* "argv" */;
6227c478bd9Sstevel@tonic-gate else
6237c478bd9Sstevel@tonic-gate (void) strip(name);
6247c478bd9Sstevel@tonic-gate argv = adrof(name);
6257c478bd9Sstevel@tonic-gate if (argv == 0)
6267c478bd9Sstevel@tonic-gate udvar(name);
6277c478bd9Sstevel@tonic-gate if (argv->vec[0] == 0)
6287c478bd9Sstevel@tonic-gate bferr("No more words");
6297c478bd9Sstevel@tonic-gate lshift(argv->vec, 1);
6307c478bd9Sstevel@tonic-gate }
6317c478bd9Sstevel@tonic-gate
6326c02b4a4Smuffin void
exportpath(tchar ** val)6336c02b4a4Smuffin exportpath(tchar **val)
6347c478bd9Sstevel@tonic-gate {
6357c478bd9Sstevel@tonic-gate tchar exppath[PATHSIZ];
6367c478bd9Sstevel@tonic-gate
6377c478bd9Sstevel@tonic-gate #ifdef TRACE
6387c478bd9Sstevel@tonic-gate tprintf("TRACE- exportpath()\n");
6397c478bd9Sstevel@tonic-gate #endif
6407c478bd9Sstevel@tonic-gate exppath[0] = 0;
6417c478bd9Sstevel@tonic-gate if (val)
6427c478bd9Sstevel@tonic-gate while (*val) {
6437c478bd9Sstevel@tonic-gate if (strlen_(*val) + strlen_(exppath) + 2 > PATHSIZ) {
6447c478bd9Sstevel@tonic-gate printf("Warning: ridiculously long PATH truncated\n");
6457c478bd9Sstevel@tonic-gate break;
6467c478bd9Sstevel@tonic-gate }
6477c478bd9Sstevel@tonic-gate (void) strcat_(exppath, *val++);
6487c478bd9Sstevel@tonic-gate if (*val == 0 || eq(*val, S_RPAR /* ")" */))
6497c478bd9Sstevel@tonic-gate break;
6507c478bd9Sstevel@tonic-gate (void) strcat_(exppath, S_COLON /* ":" */);
6517c478bd9Sstevel@tonic-gate }
6527c478bd9Sstevel@tonic-gate local_setenv(S_PATH /* "PATH" */, exppath);
6537c478bd9Sstevel@tonic-gate }
6547c478bd9Sstevel@tonic-gate
6557c478bd9Sstevel@tonic-gate /* macros to do single rotations on node p */
6567c478bd9Sstevel@tonic-gate #define rright(p) (\
6577c478bd9Sstevel@tonic-gate t = (p)->v_left,\
6587c478bd9Sstevel@tonic-gate (t)->v_parent = (p)->v_parent,\
6597c478bd9Sstevel@tonic-gate ((p)->v_left = t->v_right) ? (t->v_right->v_parent = (p)) : 0,\
6607c478bd9Sstevel@tonic-gate (t->v_right = (p))->v_parent = t,\
6617c478bd9Sstevel@tonic-gate (p) = t)
6627c478bd9Sstevel@tonic-gate #define rleft(p) (\
6637c478bd9Sstevel@tonic-gate t = (p)->v_right,\
6647c478bd9Sstevel@tonic-gate (t)->v_parent = (p)->v_parent,\
6657c478bd9Sstevel@tonic-gate ((p)->v_right = t->v_left) ? (t->v_left->v_parent = (p)) : 0,\
6667c478bd9Sstevel@tonic-gate (t->v_left = (p))->v_parent = t,\
6677c478bd9Sstevel@tonic-gate (p) = t)
6687c478bd9Sstevel@tonic-gate
6697c478bd9Sstevel@tonic-gate /*
6707c478bd9Sstevel@tonic-gate * Rebalance a tree, starting at p and up.
6717c478bd9Sstevel@tonic-gate * F == 0 means we've come from p's left child.
6727c478bd9Sstevel@tonic-gate * D == 1 means we've just done a delete, otherwise an insert.
6737c478bd9Sstevel@tonic-gate */
6746c02b4a4Smuffin void
balance(struct varent * p,int f,int d)6756c02b4a4Smuffin balance(struct varent *p, int f, int d)
6767c478bd9Sstevel@tonic-gate {
6776c02b4a4Smuffin struct varent *pp;
6786c02b4a4Smuffin struct varent *t; /* used by the rotate macros */
6796c02b4a4Smuffin int ff;
6807c478bd9Sstevel@tonic-gate
6817c478bd9Sstevel@tonic-gate #ifdef TRACE
6827c478bd9Sstevel@tonic-gate tprintf("TRACE- balance()\n");
6837c478bd9Sstevel@tonic-gate #endif
6847c478bd9Sstevel@tonic-gate /*
6857c478bd9Sstevel@tonic-gate * Ok, from here on, p is the node we're operating on;
6867c478bd9Sstevel@tonic-gate * pp is it's parent; f is the branch of p from which we have come;
6877c478bd9Sstevel@tonic-gate * ff is the branch of pp which is p.
6887c478bd9Sstevel@tonic-gate */
6897c478bd9Sstevel@tonic-gate for (; pp = p->v_parent; p = pp, f = ff) {
6907c478bd9Sstevel@tonic-gate ff = pp->v_right == p;
6917c478bd9Sstevel@tonic-gate if (f ^ d) { /* right heavy */
6927c478bd9Sstevel@tonic-gate switch (p->v_bal) {
6937c478bd9Sstevel@tonic-gate case -1: /* was left heavy */
6947c478bd9Sstevel@tonic-gate p->v_bal = 0;
6957c478bd9Sstevel@tonic-gate break;
6967c478bd9Sstevel@tonic-gate case 0: /* was balanced */
6977c478bd9Sstevel@tonic-gate p->v_bal = 1;
6987c478bd9Sstevel@tonic-gate break;
6997c478bd9Sstevel@tonic-gate case 1: /* was already right heavy */
7007c478bd9Sstevel@tonic-gate switch (p->v_right->v_bal) {
7017c478bd9Sstevel@tonic-gate case 1: /* sigle rotate */
7027c478bd9Sstevel@tonic-gate pp->v_link[ff] = rleft(p);
7037c478bd9Sstevel@tonic-gate p->v_left->v_bal = 0;
7047c478bd9Sstevel@tonic-gate p->v_bal = 0;
7057c478bd9Sstevel@tonic-gate break;
7067c478bd9Sstevel@tonic-gate case 0: /* single rotate */
7077c478bd9Sstevel@tonic-gate pp->v_link[ff] = rleft(p);
7087c478bd9Sstevel@tonic-gate p->v_left->v_bal = 1;
7097c478bd9Sstevel@tonic-gate p->v_bal = -1;
7107c478bd9Sstevel@tonic-gate break;
7117c478bd9Sstevel@tonic-gate case -1: /* double rotate */
7127c478bd9Sstevel@tonic-gate rright(p->v_right);
7137c478bd9Sstevel@tonic-gate pp->v_link[ff] = rleft(p);
7147c478bd9Sstevel@tonic-gate p->v_left->v_bal =
7157c478bd9Sstevel@tonic-gate p->v_bal < 1 ? 0 : -1;
7167c478bd9Sstevel@tonic-gate p->v_right->v_bal =
7177c478bd9Sstevel@tonic-gate p->v_bal > -1 ? 0 : 1;
7187c478bd9Sstevel@tonic-gate p->v_bal = 0;
7197c478bd9Sstevel@tonic-gate break;
7207c478bd9Sstevel@tonic-gate }
7217c478bd9Sstevel@tonic-gate break;
7227c478bd9Sstevel@tonic-gate }
7237c478bd9Sstevel@tonic-gate } else { /* left heavy */
7247c478bd9Sstevel@tonic-gate switch (p->v_bal) {
7257c478bd9Sstevel@tonic-gate case 1: /* was right heavy */
7267c478bd9Sstevel@tonic-gate p->v_bal = 0;
7277c478bd9Sstevel@tonic-gate break;
7287c478bd9Sstevel@tonic-gate case 0: /* was balanced */
7297c478bd9Sstevel@tonic-gate p->v_bal = -1;
7307c478bd9Sstevel@tonic-gate break;
7317c478bd9Sstevel@tonic-gate case -1: /* was already left heavy */
7327c478bd9Sstevel@tonic-gate switch (p->v_left->v_bal) {
7337c478bd9Sstevel@tonic-gate case -1: /* single rotate */
7347c478bd9Sstevel@tonic-gate pp->v_link[ff] = rright(p);
7357c478bd9Sstevel@tonic-gate p->v_right->v_bal = 0;
7367c478bd9Sstevel@tonic-gate p->v_bal = 0;
7377c478bd9Sstevel@tonic-gate break;
7387c478bd9Sstevel@tonic-gate case 0: /* signle rotate */
7397c478bd9Sstevel@tonic-gate pp->v_link[ff] = rright(p);
7407c478bd9Sstevel@tonic-gate p->v_right->v_bal = -1;
7417c478bd9Sstevel@tonic-gate p->v_bal = 1;
7427c478bd9Sstevel@tonic-gate break;
7437c478bd9Sstevel@tonic-gate case 1: /* double rotate */
7447c478bd9Sstevel@tonic-gate rleft(p->v_left);
7457c478bd9Sstevel@tonic-gate pp->v_link[ff] = rright(p);
7467c478bd9Sstevel@tonic-gate p->v_left->v_bal =
7477c478bd9Sstevel@tonic-gate p->v_bal < 1 ? 0 : -1;
7487c478bd9Sstevel@tonic-gate p->v_right->v_bal =
7497c478bd9Sstevel@tonic-gate p->v_bal > -1 ? 0 : 1;
7507c478bd9Sstevel@tonic-gate p->v_bal = 0;
7517c478bd9Sstevel@tonic-gate break;
7527c478bd9Sstevel@tonic-gate }
7537c478bd9Sstevel@tonic-gate break;
7547c478bd9Sstevel@tonic-gate }
7557c478bd9Sstevel@tonic-gate }
7567c478bd9Sstevel@tonic-gate /*
7577c478bd9Sstevel@tonic-gate * If from insert, then we terminate when p is balanced.
7587c478bd9Sstevel@tonic-gate * If from delete, then we terminate when p is unbalanced.
7597c478bd9Sstevel@tonic-gate */
7607c478bd9Sstevel@tonic-gate if ((p->v_bal == 0) ^ d)
7617c478bd9Sstevel@tonic-gate break;
7627c478bd9Sstevel@tonic-gate }
7637c478bd9Sstevel@tonic-gate }
7647c478bd9Sstevel@tonic-gate
7656c02b4a4Smuffin void
plist(struct varent * p)7666c02b4a4Smuffin plist(struct varent *p)
7677c478bd9Sstevel@tonic-gate {
7686c02b4a4Smuffin struct varent *c;
7696c02b4a4Smuffin int len;
7707c478bd9Sstevel@tonic-gate
7717c478bd9Sstevel@tonic-gate #ifdef TRACE
7727c478bd9Sstevel@tonic-gate tprintf("TRACE- plist()\n");
7737c478bd9Sstevel@tonic-gate #endif
7747c478bd9Sstevel@tonic-gate if (setintr)
7757c478bd9Sstevel@tonic-gate (void) sigsetmask(sigblock(0) & ~ sigmask(SIGINT));
7767c478bd9Sstevel@tonic-gate for (;;) {
7777c478bd9Sstevel@tonic-gate while (p->v_left)
7787c478bd9Sstevel@tonic-gate p = p->v_left;
7797c478bd9Sstevel@tonic-gate x:
7807c478bd9Sstevel@tonic-gate if (p->v_parent == 0) /* is it the header? */
7817c478bd9Sstevel@tonic-gate return;
7827c478bd9Sstevel@tonic-gate len = blklen(p->vec);
7837c478bd9Sstevel@tonic-gate printf("%t", p->v_name);
7847c478bd9Sstevel@tonic-gate Putchar('\t');
7857c478bd9Sstevel@tonic-gate if (len != 1)
7867c478bd9Sstevel@tonic-gate Putchar('(');
7877c478bd9Sstevel@tonic-gate blkpr(p->vec);
7887c478bd9Sstevel@tonic-gate if (len != 1)
7897c478bd9Sstevel@tonic-gate Putchar(')');
7907c478bd9Sstevel@tonic-gate Putchar('\n');
7917c478bd9Sstevel@tonic-gate if (p->v_right) {
7927c478bd9Sstevel@tonic-gate p = p->v_right;
7937c478bd9Sstevel@tonic-gate continue;
7947c478bd9Sstevel@tonic-gate }
7957c478bd9Sstevel@tonic-gate do {
7967c478bd9Sstevel@tonic-gate c = p;
7977c478bd9Sstevel@tonic-gate p = p->v_parent;
7987c478bd9Sstevel@tonic-gate } while (p->v_right == c);
7997c478bd9Sstevel@tonic-gate goto x;
8007c478bd9Sstevel@tonic-gate }
8017c478bd9Sstevel@tonic-gate }
802