xref: /illumos-gate/usr/src/cmd/csh/sh.set.c (revision 6c02b4a4)
17c478bd9Sstevel@tonic-gate /*
2*6c02b4a4Smuffin  * 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"
19*6c02b4a4Smuffin extern int	didchdir;
207c478bd9Sstevel@tonic-gate 
217c478bd9Sstevel@tonic-gate /*
227c478bd9Sstevel@tonic-gate  * C Shell
237c478bd9Sstevel@tonic-gate  */
247c478bd9Sstevel@tonic-gate 
25*6c02b4a4Smuffin void	asx(tchar *, int, tchar *);
26*6c02b4a4Smuffin void	putn1(int);
27*6c02b4a4Smuffin void	set(tchar *, tchar *);
28*6c02b4a4Smuffin void	set1(tchar *, tchar **, struct varent *);
29*6c02b4a4Smuffin void	setq(tchar *, tchar **, struct varent *);
30*6c02b4a4Smuffin void	unset1(tchar *[], struct varent *);
31*6c02b4a4Smuffin void	unsetv1(struct varent *);
32*6c02b4a4Smuffin void	exportpath(tchar **);
33*6c02b4a4Smuffin void	balance(struct varent *, int, int);
34*6c02b4a4Smuffin tchar	*operate(tchar, tchar *, tchar *);
35*6c02b4a4Smuffin tchar	*getinx(tchar *, int *);
36*6c02b4a4Smuffin tchar	*xset(tchar *, tchar ***);
37*6c02b4a4Smuffin struct varent	*getvx(tchar *, int);
38*6c02b4a4Smuffin 
39*6c02b4a4Smuffin void
40*6c02b4a4Smuffin doset(tchar **v)
417c478bd9Sstevel@tonic-gate {
42*6c02b4a4Smuffin 	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/*"("*/)) {
88*6c02b4a4Smuffin 			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"*/)) {
116*6c02b4a4Smuffin 			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 *
135*6c02b4a4Smuffin 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 
150*6c02b4a4Smuffin void
151*6c02b4a4Smuffin asx(tchar *vp, int subscr, tchar *p)
1527c478bd9Sstevel@tonic-gate {
153*6c02b4a4Smuffin 	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 *
163*6c02b4a4Smuffin getvx(tchar *vp, int subscr)
1647c478bd9Sstevel@tonic-gate {
165*6c02b4a4Smuffin 	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 
179*6c02b4a4Smuffin void
180*6c02b4a4Smuffin dolet(tchar **v)
1817c478bd9Sstevel@tonic-gate {
182*6c02b4a4Smuffin 	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 
2617c478bd9Sstevel@tonic-gate 		XFREE(vp)
2627c478bd9Sstevel@tonic-gate 		if (c != '=')
2637c478bd9Sstevel@tonic-gate 			XFREE(p)
2647c478bd9Sstevel@tonic-gate 	} while (p = *v++);
2657c478bd9Sstevel@tonic-gate }
2667c478bd9Sstevel@tonic-gate 
2677c478bd9Sstevel@tonic-gate tchar *
268*6c02b4a4Smuffin xset(tchar *cp, tchar ***vp)
2697c478bd9Sstevel@tonic-gate {
270*6c02b4a4Smuffin 	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 *
285*6c02b4a4Smuffin operate(tchar op, tchar *vp, tchar *p)
2867c478bd9Sstevel@tonic-gate {
2877c478bd9Sstevel@tonic-gate 	tchar opr[2];
2887c478bd9Sstevel@tonic-gate 	tchar *vec[5];
289*6c02b4a4Smuffin 	tchar **v = vec;
2907c478bd9Sstevel@tonic-gate 	tchar **vecp = v;
291*6c02b4a4Smuffin 	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 *
313*6c02b4a4Smuffin 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 
341*6c02b4a4Smuffin void
342*6c02b4a4Smuffin 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 
352*6c02b4a4Smuffin int
353*6c02b4a4Smuffin getn(tchar *cp)
3547c478bd9Sstevel@tonic-gate {
355*6c02b4a4Smuffin 	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 *
382*6c02b4a4Smuffin value1(tchar *var, struct varent *head)
3837c478bd9Sstevel@tonic-gate {
384*6c02b4a4Smuffin 	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 *
394*6c02b4a4Smuffin madrof(tchar *pat, struct varent *vp)
3957c478bd9Sstevel@tonic-gate {
396*6c02b4a4Smuffin 	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 *
411*6c02b4a4Smuffin adrof1(tchar *name, struct varent *v)
4127c478bd9Sstevel@tonic-gate {
413*6c02b4a4Smuffin 	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  */
431*6c02b4a4Smuffin void
432*6c02b4a4Smuffin set(tchar *var, tchar *val)
4337c478bd9Sstevel@tonic-gate {
434*6c02b4a4Smuffin 	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 
444*6c02b4a4Smuffin void
445*6c02b4a4Smuffin set1(tchar *var, tchar **vec, struct varent *head)
4467c478bd9Sstevel@tonic-gate {
447*6c02b4a4Smuffin 	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;
4537c478bd9Sstevel@tonic-gate 	/* If setting cwd variable via "set cwd=/tmp/something"
4547c478bd9Sstevel@tonic-gate 	 * then do globbing.  But if we are setting the cwd
4557c478bd9Sstevel@tonic-gate  	 * becuz of a cd, chdir, pushd, popd, do not do globbing.
4567c478bd9Sstevel@tonic-gate 	 */
4577c478bd9Sstevel@tonic-gate 	if ( (!(eq(var,S_cwd))) || (eq(var,S_cwd) && (didchdir == 0)) )
4587c478bd9Sstevel@tonic-gate 		{
4597c478bd9Sstevel@tonic-gate         	tglob(oldv);
4607c478bd9Sstevel@tonic-gate 		}
4617c478bd9Sstevel@tonic-gate 	if (gflag) {
4627c478bd9Sstevel@tonic-gate 		vec = glob(oldv);
4637c478bd9Sstevel@tonic-gate 		if (vec == 0) {
4647c478bd9Sstevel@tonic-gate 			bferr("No match");
4657c478bd9Sstevel@tonic-gate 			blkfree(oldv);
4667c478bd9Sstevel@tonic-gate 			return;
4677c478bd9Sstevel@tonic-gate 		}
4687c478bd9Sstevel@tonic-gate 		blkfree(oldv);
4697c478bd9Sstevel@tonic-gate 		gargv = 0;
4707c478bd9Sstevel@tonic-gate 	}
4717c478bd9Sstevel@tonic-gate 	setq(var, vec, head);
4727c478bd9Sstevel@tonic-gate }
4737c478bd9Sstevel@tonic-gate 
474*6c02b4a4Smuffin void
475*6c02b4a4Smuffin setq(tchar *name, tchar **vec, struct varent *p)
4767c478bd9Sstevel@tonic-gate {
477*6c02b4a4Smuffin 	struct varent *c;
478*6c02b4a4Smuffin 	int f;
4797c478bd9Sstevel@tonic-gate 
4807c478bd9Sstevel@tonic-gate #ifdef TRACE
4817c478bd9Sstevel@tonic-gate 	tprintf("TRACE- setq()\n");
4827c478bd9Sstevel@tonic-gate #endif
4837c478bd9Sstevel@tonic-gate 	f = 0;			/* tree hangs off the header's left link */
4847c478bd9Sstevel@tonic-gate 	while (c = p->v_link[f]) {
4857c478bd9Sstevel@tonic-gate 		if ((f = *name - *c->v_name) == 0 &&
4867c478bd9Sstevel@tonic-gate 		    (f = strcmp_(name, c->v_name)) == 0) {
4877c478bd9Sstevel@tonic-gate 			blkfree(c->vec);
4887c478bd9Sstevel@tonic-gate 			goto found;
4897c478bd9Sstevel@tonic-gate 		}
4907c478bd9Sstevel@tonic-gate 		p = c;
4917c478bd9Sstevel@tonic-gate 		f = f > 0;
4927c478bd9Sstevel@tonic-gate 	}
4937c478bd9Sstevel@tonic-gate 	p->v_link[f] = c = (struct varent *)xalloc(sizeof (struct varent));
4947c478bd9Sstevel@tonic-gate 	c->v_name = savestr(name);
4957c478bd9Sstevel@tonic-gate 	c->v_bal = 0;
4967c478bd9Sstevel@tonic-gate 	c->v_left = c->v_right = 0;
4977c478bd9Sstevel@tonic-gate 	c->v_parent = p;
4987c478bd9Sstevel@tonic-gate 	balance(p, f, 0);
4997c478bd9Sstevel@tonic-gate found:
5007c478bd9Sstevel@tonic-gate 	trim(c->vec = vec);
5017c478bd9Sstevel@tonic-gate }
5027c478bd9Sstevel@tonic-gate 
503*6c02b4a4Smuffin void
504*6c02b4a4Smuffin unset(tchar *v[])
5057c478bd9Sstevel@tonic-gate {
5067c478bd9Sstevel@tonic-gate 
5077c478bd9Sstevel@tonic-gate #ifdef TRACE
5087c478bd9Sstevel@tonic-gate 	tprintf("TRACE- unset()\n");
5097c478bd9Sstevel@tonic-gate #endif
5107c478bd9Sstevel@tonic-gate 	unset1(v, &shvhed);
5117c478bd9Sstevel@tonic-gate 	if (adrof(S_histchars/*"histchars"*/) == 0) {
5127c478bd9Sstevel@tonic-gate 		HIST = '!';
5137c478bd9Sstevel@tonic-gate 		HISTSUB = '^';
5147c478bd9Sstevel@tonic-gate 	}
5157c478bd9Sstevel@tonic-gate #ifdef FILEC
5167c478bd9Sstevel@tonic-gate 	if (adrof(S_filec/*"filec"*/) == 0)
5177c478bd9Sstevel@tonic-gate 		filec = 0;
5187c478bd9Sstevel@tonic-gate #endif
5197c478bd9Sstevel@tonic-gate }
5207c478bd9Sstevel@tonic-gate 
521*6c02b4a4Smuffin void
522*6c02b4a4Smuffin unset1(tchar *v[], struct varent *head)
5237c478bd9Sstevel@tonic-gate {
524*6c02b4a4Smuffin 	struct varent *vp;
525*6c02b4a4Smuffin 	int cnt;
5267c478bd9Sstevel@tonic-gate 
5277c478bd9Sstevel@tonic-gate #ifdef TRACE
5287c478bd9Sstevel@tonic-gate 	tprintf("TRACE- unset1()\n");
5297c478bd9Sstevel@tonic-gate #endif
5307c478bd9Sstevel@tonic-gate 	while (*++v) {
5317c478bd9Sstevel@tonic-gate 		cnt = 0;
5327c478bd9Sstevel@tonic-gate 		while (vp = madrof(*v, head->v_left))
5337c478bd9Sstevel@tonic-gate 			unsetv1(vp), cnt++;
5347c478bd9Sstevel@tonic-gate 		if (cnt == 0)
5357c478bd9Sstevel@tonic-gate 			setname(*v);
5367c478bd9Sstevel@tonic-gate 	}
5377c478bd9Sstevel@tonic-gate }
5387c478bd9Sstevel@tonic-gate 
539*6c02b4a4Smuffin void
540*6c02b4a4Smuffin unsetv(tchar *var)
5417c478bd9Sstevel@tonic-gate {
542*6c02b4a4Smuffin 	struct varent *vp;
5437c478bd9Sstevel@tonic-gate 
5447c478bd9Sstevel@tonic-gate #ifdef TRACE
5457c478bd9Sstevel@tonic-gate 	tprintf("TRACE- unsetv()\n");
5467c478bd9Sstevel@tonic-gate #endif
5477c478bd9Sstevel@tonic-gate 	if ((vp = adrof1(var, &shvhed)) == 0)
5487c478bd9Sstevel@tonic-gate 		udvar(var);
5497c478bd9Sstevel@tonic-gate 	unsetv1(vp);
5507c478bd9Sstevel@tonic-gate }
5517c478bd9Sstevel@tonic-gate 
552*6c02b4a4Smuffin void
553*6c02b4a4Smuffin unsetv1(struct varent *p)
5547c478bd9Sstevel@tonic-gate {
555*6c02b4a4Smuffin 	struct varent *c, *pp;
556*6c02b4a4Smuffin 	int f;
5577c478bd9Sstevel@tonic-gate 
5587c478bd9Sstevel@tonic-gate #ifdef TRACE
5597c478bd9Sstevel@tonic-gate 	tprintf("TRACE- unsetv1()\n");
5607c478bd9Sstevel@tonic-gate #endif
5617c478bd9Sstevel@tonic-gate 	/*
5627c478bd9Sstevel@tonic-gate 	 * Free associated memory first to avoid complications.
5637c478bd9Sstevel@tonic-gate 	 */
5647c478bd9Sstevel@tonic-gate 	blkfree(p->vec);
5657c478bd9Sstevel@tonic-gate 	XFREE(p->v_name);
5667c478bd9Sstevel@tonic-gate 	/*
5677c478bd9Sstevel@tonic-gate 	 * If p is missing one child, then we can move the other
5687c478bd9Sstevel@tonic-gate 	 * into where p is.  Otherwise, we find the predecessor
5697c478bd9Sstevel@tonic-gate 	 * of p, which is guaranteed to have no right child, copy
5707c478bd9Sstevel@tonic-gate 	 * it into p, and move it's left child into it.
5717c478bd9Sstevel@tonic-gate 	 */
5727c478bd9Sstevel@tonic-gate 	if (p->v_right == 0)
5737c478bd9Sstevel@tonic-gate 		c = p->v_left;
5747c478bd9Sstevel@tonic-gate 	else if (p->v_left == 0)
5757c478bd9Sstevel@tonic-gate 		c = p->v_right;
5767c478bd9Sstevel@tonic-gate 	else {
5777c478bd9Sstevel@tonic-gate 		for (c = p->v_left; c->v_right; c = c->v_right)
5787c478bd9Sstevel@tonic-gate 			;
5797c478bd9Sstevel@tonic-gate 		p->v_name = c->v_name;
5807c478bd9Sstevel@tonic-gate 		p->vec = c->vec;
5817c478bd9Sstevel@tonic-gate 		p = c;
5827c478bd9Sstevel@tonic-gate 		c = p->v_left;
5837c478bd9Sstevel@tonic-gate 	}
5847c478bd9Sstevel@tonic-gate 	/*
5857c478bd9Sstevel@tonic-gate 	 * Move c into where p is.
5867c478bd9Sstevel@tonic-gate 	 */
5877c478bd9Sstevel@tonic-gate 	pp = p->v_parent;
5887c478bd9Sstevel@tonic-gate 	f = pp->v_right == p;
5897c478bd9Sstevel@tonic-gate 	if (pp->v_link[f] = c)
5907c478bd9Sstevel@tonic-gate 		c->v_parent = pp;
5917c478bd9Sstevel@tonic-gate 	/*
5927c478bd9Sstevel@tonic-gate 	 * Free the deleted node, and rebalance.
5937c478bd9Sstevel@tonic-gate 	 */
5947c478bd9Sstevel@tonic-gate 	XFREE( (tchar *)p);
5957c478bd9Sstevel@tonic-gate 	balance(pp, f, 1);
5967c478bd9Sstevel@tonic-gate }
5977c478bd9Sstevel@tonic-gate 
598*6c02b4a4Smuffin void
599*6c02b4a4Smuffin setNS(tchar *cp)
6007c478bd9Sstevel@tonic-gate {
6017c478bd9Sstevel@tonic-gate #ifdef TRACE
6027c478bd9Sstevel@tonic-gate 	tprintf("TRACE- setNS()\n");
6037c478bd9Sstevel@tonic-gate #endif
6047c478bd9Sstevel@tonic-gate 
6057c478bd9Sstevel@tonic-gate 	set(cp, S_/*""*/);
6067c478bd9Sstevel@tonic-gate }
6077c478bd9Sstevel@tonic-gate 
608*6c02b4a4Smuffin void
609*6c02b4a4Smuffin shift(tchar **v)
6107c478bd9Sstevel@tonic-gate {
611*6c02b4a4Smuffin 	struct varent *argv;
612*6c02b4a4Smuffin 	tchar *name;
6137c478bd9Sstevel@tonic-gate 
6147c478bd9Sstevel@tonic-gate #ifdef TRACE
6157c478bd9Sstevel@tonic-gate 	tprintf("TRACE- shift()\n");
6167c478bd9Sstevel@tonic-gate #endif
6177c478bd9Sstevel@tonic-gate 	v++;
6187c478bd9Sstevel@tonic-gate 	name = *v;
6197c478bd9Sstevel@tonic-gate 	if (name == 0)
6207c478bd9Sstevel@tonic-gate 		name = S_argv/*"argv"*/;
6217c478bd9Sstevel@tonic-gate 	else
6227c478bd9Sstevel@tonic-gate 		(void) strip(name);
6237c478bd9Sstevel@tonic-gate 	argv = adrof(name);
6247c478bd9Sstevel@tonic-gate 	if (argv == 0)
6257c478bd9Sstevel@tonic-gate 		udvar(name);
6267c478bd9Sstevel@tonic-gate 	if (argv->vec[0] == 0)
6277c478bd9Sstevel@tonic-gate 		bferr("No more words");
6287c478bd9Sstevel@tonic-gate 	lshift(argv->vec, 1);
6297c478bd9Sstevel@tonic-gate }
6307c478bd9Sstevel@tonic-gate 
631*6c02b4a4Smuffin void
632*6c02b4a4Smuffin exportpath(tchar **val)
6337c478bd9Sstevel@tonic-gate {
6347c478bd9Sstevel@tonic-gate 	tchar exppath[PATHSIZ];
6357c478bd9Sstevel@tonic-gate 
6367c478bd9Sstevel@tonic-gate #ifdef TRACE
6377c478bd9Sstevel@tonic-gate 	tprintf("TRACE- exportpath()\n");
6387c478bd9Sstevel@tonic-gate #endif
6397c478bd9Sstevel@tonic-gate 	exppath[0] = 0;
6407c478bd9Sstevel@tonic-gate 	if (val)
6417c478bd9Sstevel@tonic-gate 		while (*val) {
6427c478bd9Sstevel@tonic-gate 			if (strlen_(*val) + strlen_(exppath) + 2 > PATHSIZ) {
6437c478bd9Sstevel@tonic-gate 				printf("Warning: ridiculously long PATH truncated\n");
6447c478bd9Sstevel@tonic-gate 				break;
6457c478bd9Sstevel@tonic-gate 			}
6467c478bd9Sstevel@tonic-gate 			(void) strcat_(exppath, *val++);
6477c478bd9Sstevel@tonic-gate 			if (*val == 0 || eq(*val, S_RPAR/*")"*/))
6487c478bd9Sstevel@tonic-gate 				break;
6497c478bd9Sstevel@tonic-gate 			(void) strcat_(exppath, S_COLON/*":"*/);
6507c478bd9Sstevel@tonic-gate 		}
6517c478bd9Sstevel@tonic-gate 	local_setenv(S_PATH/*"PATH"*/, exppath);
6527c478bd9Sstevel@tonic-gate }
6537c478bd9Sstevel@tonic-gate 
6547c478bd9Sstevel@tonic-gate 	/* macros to do single rotations on node p */
6557c478bd9Sstevel@tonic-gate #define rright(p) (\
6567c478bd9Sstevel@tonic-gate 	t = (p)->v_left,\
6577c478bd9Sstevel@tonic-gate 	(t)->v_parent = (p)->v_parent,\
6587c478bd9Sstevel@tonic-gate 	((p)->v_left = t->v_right) ? (t->v_right->v_parent = (p)) : 0,\
6597c478bd9Sstevel@tonic-gate 	(t->v_right = (p))->v_parent = t,\
6607c478bd9Sstevel@tonic-gate 	(p) = t)
6617c478bd9Sstevel@tonic-gate #define rleft(p) (\
6627c478bd9Sstevel@tonic-gate 	t = (p)->v_right,\
6637c478bd9Sstevel@tonic-gate 	(t)->v_parent = (p)->v_parent,\
6647c478bd9Sstevel@tonic-gate 	((p)->v_right = t->v_left) ? (t->v_left->v_parent = (p)) : 0,\
6657c478bd9Sstevel@tonic-gate 	(t->v_left = (p))->v_parent = t,\
6667c478bd9Sstevel@tonic-gate 	(p) = t)
6677c478bd9Sstevel@tonic-gate 
6687c478bd9Sstevel@tonic-gate /*
6697c478bd9Sstevel@tonic-gate  * Rebalance a tree, starting at p and up.
6707c478bd9Sstevel@tonic-gate  * F == 0 means we've come from p's left child.
6717c478bd9Sstevel@tonic-gate  * D == 1 means we've just done a delete, otherwise an insert.
6727c478bd9Sstevel@tonic-gate  */
673*6c02b4a4Smuffin void
674*6c02b4a4Smuffin balance(struct varent *p, int f, int d)
6757c478bd9Sstevel@tonic-gate {
676*6c02b4a4Smuffin 	struct varent *pp;
677*6c02b4a4Smuffin 	struct varent *t;		/* used by the rotate macros */
678*6c02b4a4Smuffin 	int ff;
6797c478bd9Sstevel@tonic-gate 
6807c478bd9Sstevel@tonic-gate #ifdef TRACE
6817c478bd9Sstevel@tonic-gate 	tprintf("TRACE- balance()\n");
6827c478bd9Sstevel@tonic-gate #endif
6837c478bd9Sstevel@tonic-gate 	/*
6847c478bd9Sstevel@tonic-gate 	 * Ok, from here on, p is the node we're operating on;
6857c478bd9Sstevel@tonic-gate 	 * pp is it's parent; f is the branch of p from which we have come;
6867c478bd9Sstevel@tonic-gate 	 * ff is the branch of pp which is p.
6877c478bd9Sstevel@tonic-gate 	 */
6887c478bd9Sstevel@tonic-gate 	for (; pp = p->v_parent; p = pp, f = ff) {
6897c478bd9Sstevel@tonic-gate 		ff = pp->v_right == p;
6907c478bd9Sstevel@tonic-gate 		if (f ^ d) {		/* right heavy */
6917c478bd9Sstevel@tonic-gate 			switch (p->v_bal) {
6927c478bd9Sstevel@tonic-gate 			case -1:		/* was left heavy */
6937c478bd9Sstevel@tonic-gate 				p->v_bal = 0;
6947c478bd9Sstevel@tonic-gate 				break;
6957c478bd9Sstevel@tonic-gate 			case 0:			/* was balanced */
6967c478bd9Sstevel@tonic-gate 				p->v_bal = 1;
6977c478bd9Sstevel@tonic-gate 				break;
6987c478bd9Sstevel@tonic-gate 			case 1:			/* was already right heavy */
6997c478bd9Sstevel@tonic-gate 				switch (p->v_right->v_bal) {
7007c478bd9Sstevel@tonic-gate 				case 1:			/* sigle rotate */
7017c478bd9Sstevel@tonic-gate 					pp->v_link[ff] = rleft(p);
7027c478bd9Sstevel@tonic-gate 					p->v_left->v_bal = 0;
7037c478bd9Sstevel@tonic-gate 					p->v_bal = 0;
7047c478bd9Sstevel@tonic-gate 					break;
7057c478bd9Sstevel@tonic-gate 				case 0:			/* single rotate */
7067c478bd9Sstevel@tonic-gate 					pp->v_link[ff] = rleft(p);
7077c478bd9Sstevel@tonic-gate 					p->v_left->v_bal = 1;
7087c478bd9Sstevel@tonic-gate 					p->v_bal = -1;
7097c478bd9Sstevel@tonic-gate 					break;
7107c478bd9Sstevel@tonic-gate 				case -1:		/* double rotate */
7117c478bd9Sstevel@tonic-gate 					rright(p->v_right);
7127c478bd9Sstevel@tonic-gate 					pp->v_link[ff] = rleft(p);
7137c478bd9Sstevel@tonic-gate 					p->v_left->v_bal =
7147c478bd9Sstevel@tonic-gate 						p->v_bal < 1 ? 0 : -1;
7157c478bd9Sstevel@tonic-gate 					p->v_right->v_bal =
7167c478bd9Sstevel@tonic-gate 						p->v_bal > -1 ? 0 : 1;
7177c478bd9Sstevel@tonic-gate 					p->v_bal = 0;
7187c478bd9Sstevel@tonic-gate 					break;
7197c478bd9Sstevel@tonic-gate 				}
7207c478bd9Sstevel@tonic-gate 				break;
7217c478bd9Sstevel@tonic-gate 			}
7227c478bd9Sstevel@tonic-gate 		} else {		/* left heavy */
7237c478bd9Sstevel@tonic-gate 			switch (p->v_bal) {
7247c478bd9Sstevel@tonic-gate 			case 1:			/* was right heavy */
7257c478bd9Sstevel@tonic-gate 				p->v_bal = 0;
7267c478bd9Sstevel@tonic-gate 				break;
7277c478bd9Sstevel@tonic-gate 			case 0:			/* was balanced */
7287c478bd9Sstevel@tonic-gate 				p->v_bal = -1;
7297c478bd9Sstevel@tonic-gate 				break;
7307c478bd9Sstevel@tonic-gate 			case -1:		/* was already left heavy */
7317c478bd9Sstevel@tonic-gate 				switch (p->v_left->v_bal) {
7327c478bd9Sstevel@tonic-gate 				case -1:		/* single rotate */
7337c478bd9Sstevel@tonic-gate 					pp->v_link[ff] = rright(p);
7347c478bd9Sstevel@tonic-gate 					p->v_right->v_bal = 0;
7357c478bd9Sstevel@tonic-gate 					p->v_bal = 0;
7367c478bd9Sstevel@tonic-gate 					break;
7377c478bd9Sstevel@tonic-gate 				case 0:			/* signle rotate */
7387c478bd9Sstevel@tonic-gate 					pp->v_link[ff] = rright(p);
7397c478bd9Sstevel@tonic-gate 					p->v_right->v_bal = -1;
7407c478bd9Sstevel@tonic-gate 					p->v_bal = 1;
7417c478bd9Sstevel@tonic-gate 					break;
7427c478bd9Sstevel@tonic-gate 				case 1:			/* double rotate */
7437c478bd9Sstevel@tonic-gate 					rleft(p->v_left);
7447c478bd9Sstevel@tonic-gate 					pp->v_link[ff] = rright(p);
7457c478bd9Sstevel@tonic-gate 					p->v_left->v_bal =
7467c478bd9Sstevel@tonic-gate 						p->v_bal < 1 ? 0 : -1;
7477c478bd9Sstevel@tonic-gate 					p->v_right->v_bal =
7487c478bd9Sstevel@tonic-gate 						p->v_bal > -1 ? 0 : 1;
7497c478bd9Sstevel@tonic-gate 					p->v_bal = 0;
7507c478bd9Sstevel@tonic-gate 					break;
7517c478bd9Sstevel@tonic-gate 				}
7527c478bd9Sstevel@tonic-gate 				break;
7537c478bd9Sstevel@tonic-gate 			}
7547c478bd9Sstevel@tonic-gate 		}
7557c478bd9Sstevel@tonic-gate 		/*
7567c478bd9Sstevel@tonic-gate 		 * If from insert, then we terminate when p is balanced.
7577c478bd9Sstevel@tonic-gate 		 * If from delete, then we terminate when p is unbalanced.
7587c478bd9Sstevel@tonic-gate 		 */
7597c478bd9Sstevel@tonic-gate 		if ((p->v_bal == 0) ^ d)
7607c478bd9Sstevel@tonic-gate 			break;
7617c478bd9Sstevel@tonic-gate 	}
7627c478bd9Sstevel@tonic-gate }
7637c478bd9Sstevel@tonic-gate 
764*6c02b4a4Smuffin void
765*6c02b4a4Smuffin plist(struct varent *p)
7667c478bd9Sstevel@tonic-gate {
767*6c02b4a4Smuffin 	struct varent *c;
768*6c02b4a4Smuffin 	int len;
7697c478bd9Sstevel@tonic-gate 
7707c478bd9Sstevel@tonic-gate #ifdef TRACE
7717c478bd9Sstevel@tonic-gate 	tprintf("TRACE- plist()\n");
7727c478bd9Sstevel@tonic-gate #endif
7737c478bd9Sstevel@tonic-gate 	if (setintr)
7747c478bd9Sstevel@tonic-gate 		(void) sigsetmask(sigblock(0) & ~ sigmask(SIGINT));
7757c478bd9Sstevel@tonic-gate 	for (;;) {
7767c478bd9Sstevel@tonic-gate 		while (p->v_left)
7777c478bd9Sstevel@tonic-gate 			p = p->v_left;
7787c478bd9Sstevel@tonic-gate 	x:
7797c478bd9Sstevel@tonic-gate 		if (p->v_parent == 0)		/* is it the header? */
7807c478bd9Sstevel@tonic-gate 			return;
7817c478bd9Sstevel@tonic-gate 		len = blklen(p->vec);
7827c478bd9Sstevel@tonic-gate 		printf("%t", p->v_name);
7837c478bd9Sstevel@tonic-gate 		Putchar('\t');
7847c478bd9Sstevel@tonic-gate 		if (len != 1)
7857c478bd9Sstevel@tonic-gate 			Putchar('(');
7867c478bd9Sstevel@tonic-gate 		blkpr(p->vec);
7877c478bd9Sstevel@tonic-gate 		if (len != 1)
7887c478bd9Sstevel@tonic-gate 			Putchar(')');
7897c478bd9Sstevel@tonic-gate 		Putchar('\n');
7907c478bd9Sstevel@tonic-gate 		if (p->v_right) {
7917c478bd9Sstevel@tonic-gate 			p = p->v_right;
7927c478bd9Sstevel@tonic-gate 			continue;
7937c478bd9Sstevel@tonic-gate 		}
7947c478bd9Sstevel@tonic-gate 		do {
7957c478bd9Sstevel@tonic-gate 			c = p;
7967c478bd9Sstevel@tonic-gate 			p = p->v_parent;
7977c478bd9Sstevel@tonic-gate 		} while (p->v_right == c);
7987c478bd9Sstevel@tonic-gate 		goto x;
7997c478bd9Sstevel@tonic-gate 	}
8007c478bd9Sstevel@tonic-gate }
801