xref: /titanic_52/usr/src/cmd/csh/sh.set.c (revision 65b0c20e9bbaf87a200ce20a4decf18585e61a25)
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
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 *
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
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 *
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
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 *
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 *
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 *
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
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
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 *
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 *
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 *
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
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
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
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
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
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
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
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
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
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
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
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
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