xref: /illumos-gate/usr/src/cmd/csh/sh.set.c (revision 258f91c6)
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 #include "sh.h"
167c478bd9Sstevel@tonic-gate #include "sh.tconst.h"
177c478bd9Sstevel@tonic-gate 
187c478bd9Sstevel@tonic-gate /*
197c478bd9Sstevel@tonic-gate  * C Shell
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate 
226c02b4a4Smuffin void	asx(tchar *, int, tchar *);
236c02b4a4Smuffin void	putn1(int);
246c02b4a4Smuffin void	set(tchar *, tchar *);
256c02b4a4Smuffin void	set1(tchar *, tchar **, struct varent *);
266c02b4a4Smuffin void	setq(tchar *, tchar **, struct varent *);
276c02b4a4Smuffin void	unset1(tchar *[], struct varent *);
286c02b4a4Smuffin void	unsetv1(struct varent *);
296c02b4a4Smuffin void	exportpath(tchar **);
306c02b4a4Smuffin void	balance(struct varent *, int, int);
316c02b4a4Smuffin tchar	*operate(tchar, tchar *, tchar *);
326c02b4a4Smuffin tchar	*getinx(tchar *, int *);
336c02b4a4Smuffin tchar	*xset(tchar *, tchar ***);
346c02b4a4Smuffin struct varent	*getvx(tchar *, int);
356c02b4a4Smuffin 
366c02b4a4Smuffin void
doset(tchar ** v)376c02b4a4Smuffin doset(tchar **v)
387c478bd9Sstevel@tonic-gate {
396c02b4a4Smuffin 	tchar *p;
407c478bd9Sstevel@tonic-gate 	tchar *vp, op;
417c478bd9Sstevel@tonic-gate 	tchar **vecp;
427c478bd9Sstevel@tonic-gate 	bool hadsub;
437c478bd9Sstevel@tonic-gate 	int subscr;
447c478bd9Sstevel@tonic-gate 	tchar *retp;
457c478bd9Sstevel@tonic-gate 
467c478bd9Sstevel@tonic-gate #ifdef TRACE
477c478bd9Sstevel@tonic-gate 	tprintf("TRACE- doset()\n");
487c478bd9Sstevel@tonic-gate #endif
497c478bd9Sstevel@tonic-gate 	v++;
507c478bd9Sstevel@tonic-gate 	p = *v++;
517c478bd9Sstevel@tonic-gate 	if (p == 0) {
527c478bd9Sstevel@tonic-gate 		prvars();
537c478bd9Sstevel@tonic-gate 		return;
547c478bd9Sstevel@tonic-gate 	}
557c478bd9Sstevel@tonic-gate 	do {
567c478bd9Sstevel@tonic-gate 		hadsub = 0;
577c478bd9Sstevel@tonic-gate 		/*
587c478bd9Sstevel@tonic-gate 		 * check for proper variable syntax
597c478bd9Sstevel@tonic-gate 		 * must be alphanumeric, start with a letter and
607c478bd9Sstevel@tonic-gate 		 * be at most 20 characters
617c478bd9Sstevel@tonic-gate 		 */
627c478bd9Sstevel@tonic-gate 		for (vp = p; alnum(*p); p++)
637c478bd9Sstevel@tonic-gate 			continue;
647c478bd9Sstevel@tonic-gate 		if (vp == p || !letter(*vp))
657c478bd9Sstevel@tonic-gate 			goto setsyn;
66*65b0c20eSnakanon 		if ((p - vp) > MAX_VAR_LEN)
677c478bd9Sstevel@tonic-gate 			bferr("Variable name too long");
687c478bd9Sstevel@tonic-gate 		if (*p == '[') {
697c478bd9Sstevel@tonic-gate 			hadsub++;
707c478bd9Sstevel@tonic-gate 			p = getinx(p, &subscr);
717c478bd9Sstevel@tonic-gate 		}
727c478bd9Sstevel@tonic-gate 		if (op = *p) {
737c478bd9Sstevel@tonic-gate 			*p++ = 0;
747c478bd9Sstevel@tonic-gate 			if (*p == 0 && *v && **v == '(')
757c478bd9Sstevel@tonic-gate 				p = *v++;
76*65b0c20eSnakanon 		} else if (*v && eq(*v, S_EQ /* "=" */)) {
777c478bd9Sstevel@tonic-gate 			op = '=', v++;
787c478bd9Sstevel@tonic-gate 			if (*v)
797c478bd9Sstevel@tonic-gate 				p = *v++;
807c478bd9Sstevel@tonic-gate 		}
817c478bd9Sstevel@tonic-gate 		if (op && op != '=')
827c478bd9Sstevel@tonic-gate setsyn:
837c478bd9Sstevel@tonic-gate 			bferr("Syntax error");
84*65b0c20eSnakanon 		if (eq(p, S_LPAR /* "(" */)) {
856c02b4a4Smuffin 			tchar **e = v;
867c478bd9Sstevel@tonic-gate 
877c478bd9Sstevel@tonic-gate 			if (hadsub)
887c478bd9Sstevel@tonic-gate 				goto setsyn;
897c478bd9Sstevel@tonic-gate 			for (;;) {
907c478bd9Sstevel@tonic-gate 				if (!*e)
917c478bd9Sstevel@tonic-gate 					bferr("Missing )");
927c478bd9Sstevel@tonic-gate 				if (**e == ')')
937c478bd9Sstevel@tonic-gate 					break;
947c478bd9Sstevel@tonic-gate 				e++;
957c478bd9Sstevel@tonic-gate 			}
967c478bd9Sstevel@tonic-gate 			p = *e;
977c478bd9Sstevel@tonic-gate 			*e = 0;
987c478bd9Sstevel@tonic-gate 			vecp = saveblk(v);
997c478bd9Sstevel@tonic-gate 			set1(vp, vecp, &shvhed);
1007c478bd9Sstevel@tonic-gate 			*e = p;
1017c478bd9Sstevel@tonic-gate 			v = e + 1;
1027c478bd9Sstevel@tonic-gate 		} else if (hadsub) {
1037c478bd9Sstevel@tonic-gate 			retp = savestr(p);
1047c478bd9Sstevel@tonic-gate 			asx(vp, subscr, retp);
1057c478bd9Sstevel@tonic-gate 			xfree(retp);
1067c478bd9Sstevel@tonic-gate 			retp = 0;
1077c478bd9Sstevel@tonic-gate 		} else
1087c478bd9Sstevel@tonic-gate 			set(vp, savestr(p));
109*65b0c20eSnakanon 		if (eq(vp, S_path /* "path" */)) {
110*65b0c20eSnakanon 			exportpath(adrof(S_path /* "path" */)->vec);
1117c478bd9Sstevel@tonic-gate 			dohash(xhash);
112*65b0c20eSnakanon 		} else if (eq(vp, S_histchars /* "histchars" */)) {
113*65b0c20eSnakanon 			tchar *p = value(S_histchars /* "histchars" */);
1147c478bd9Sstevel@tonic-gate 			HIST = *p++;
1157c478bd9Sstevel@tonic-gate 			HISTSUB = *p;
116*65b0c20eSnakanon 		} else if (eq(vp, S_user /* "user" */))
117*65b0c20eSnakanon 			local_setenv(S_USER /* "USER" */, value(vp));
118*65b0c20eSnakanon 		else if (eq(vp, S_term /* "term" */))
119*65b0c20eSnakanon 			local_setenv(S_TERM /* "TERM" */, value(vp));
120*65b0c20eSnakanon 		else if (eq(vp, S_home /* "home" */))
121*65b0c20eSnakanon 			local_setenv(S_HOME /* "HOME" */, value(vp));
1227c478bd9Sstevel@tonic-gate #ifdef FILEC
123*65b0c20eSnakanon 		else if (eq(vp, S_filec /* "filec" */))
1247c478bd9Sstevel@tonic-gate 			filec = 1;
125*65b0c20eSnakanon 		else if (eq(vp, S_cdpath /* "cdpath" */))
1267c478bd9Sstevel@tonic-gate 			dohash(xhash2);
1277c478bd9Sstevel@tonic-gate #endif
1287c478bd9Sstevel@tonic-gate 	} while (p = *v++);
1297c478bd9Sstevel@tonic-gate }
1307c478bd9Sstevel@tonic-gate 
1317c478bd9Sstevel@tonic-gate tchar *
getinx(tchar * cp,int * ip)1326c02b4a4Smuffin getinx(tchar *cp, int *ip)
1337c478bd9Sstevel@tonic-gate {
1347c478bd9Sstevel@tonic-gate 
1357c478bd9Sstevel@tonic-gate #ifdef TRACE
1367c478bd9Sstevel@tonic-gate 	tprintf("TRACE- getinx()\n");
1377c478bd9Sstevel@tonic-gate #endif
1387c478bd9Sstevel@tonic-gate 	*ip = 0;
1397c478bd9Sstevel@tonic-gate 	*cp++ = 0;
1407c478bd9Sstevel@tonic-gate 	while (*cp && digit(*cp))
1417c478bd9Sstevel@tonic-gate 		*ip = *ip * 10 + *cp++ - '0';
1427c478bd9Sstevel@tonic-gate 	if (*cp++ != ']')
1437c478bd9Sstevel@tonic-gate 		bferr("Subscript error");
1447c478bd9Sstevel@tonic-gate 	return (cp);
1457c478bd9Sstevel@tonic-gate }
1467c478bd9Sstevel@tonic-gate 
1476c02b4a4Smuffin void
asx(tchar * vp,int subscr,tchar * p)1486c02b4a4Smuffin asx(tchar *vp, int subscr, tchar *p)
1497c478bd9Sstevel@tonic-gate {
1506c02b4a4Smuffin 	struct varent *v = getvx(vp, subscr);
1517c478bd9Sstevel@tonic-gate 
1527c478bd9Sstevel@tonic-gate #ifdef TRACE
1537c478bd9Sstevel@tonic-gate 	tprintf("TRACE- asx()\n");
1547c478bd9Sstevel@tonic-gate #endif
1557c478bd9Sstevel@tonic-gate 	xfree(v->vec[subscr - 1]);
1567c478bd9Sstevel@tonic-gate 	v->vec[subscr - 1] = globone(p);
1577c478bd9Sstevel@tonic-gate }
1587c478bd9Sstevel@tonic-gate 
1597c478bd9Sstevel@tonic-gate struct varent *
getvx(tchar * vp,int subscr)1606c02b4a4Smuffin getvx(tchar *vp, int subscr)
1617c478bd9Sstevel@tonic-gate {
1626c02b4a4Smuffin 	struct varent *v = adrof(vp);
1637c478bd9Sstevel@tonic-gate 
1647c478bd9Sstevel@tonic-gate #ifdef TRACE
1657c478bd9Sstevel@tonic-gate 	tprintf("TRACE- getvx()\n");
1667c478bd9Sstevel@tonic-gate #endif
1677c478bd9Sstevel@tonic-gate 	if (v == 0)
1687c478bd9Sstevel@tonic-gate 		udvar(vp);
1697c478bd9Sstevel@tonic-gate 	if (subscr < 1 || subscr > blklen(v->vec))
1707c478bd9Sstevel@tonic-gate 		bferr("Subscript out of range");
1717c478bd9Sstevel@tonic-gate 	return (v);
1727c478bd9Sstevel@tonic-gate }
1737c478bd9Sstevel@tonic-gate 
1747c478bd9Sstevel@tonic-gate tchar plusplus[2] = { '1', 0 };
1757c478bd9Sstevel@tonic-gate 
1766c02b4a4Smuffin void
dolet(tchar ** v)1776c02b4a4Smuffin dolet(tchar **v)
1787c478bd9Sstevel@tonic-gate {
1796c02b4a4Smuffin 	tchar *p;
1807c478bd9Sstevel@tonic-gate 	tchar *vp, c, op;
1817c478bd9Sstevel@tonic-gate 	bool hadsub;
1827c478bd9Sstevel@tonic-gate 	int subscr;
1837c478bd9Sstevel@tonic-gate 
1847c478bd9Sstevel@tonic-gate 	v++;
1857c478bd9Sstevel@tonic-gate 	p = *v++;
1867c478bd9Sstevel@tonic-gate 	if (p == 0) {
1877c478bd9Sstevel@tonic-gate 		prvars();
1887c478bd9Sstevel@tonic-gate 		return;
1897c478bd9Sstevel@tonic-gate 	}
1907c478bd9Sstevel@tonic-gate 	do {
1917c478bd9Sstevel@tonic-gate 		hadsub = 0;
1927c478bd9Sstevel@tonic-gate 		for (vp = p; alnum(*p); p++)
1937c478bd9Sstevel@tonic-gate 			continue;
1947c478bd9Sstevel@tonic-gate 		if (vp == p || !letter(*vp))
1957c478bd9Sstevel@tonic-gate 			goto letsyn;
1967c478bd9Sstevel@tonic-gate 		if (*p == '[') {
1977c478bd9Sstevel@tonic-gate 			hadsub++;
1987c478bd9Sstevel@tonic-gate 			p = getinx(p, &subscr);
1997c478bd9Sstevel@tonic-gate 		}
2007c478bd9Sstevel@tonic-gate 		if (*p == 0 && *v)
2017c478bd9Sstevel@tonic-gate 			p = *v++;
2027c478bd9Sstevel@tonic-gate 		if (op = *p)
2037c478bd9Sstevel@tonic-gate 			*p++ = 0;
2047c478bd9Sstevel@tonic-gate 		else
2057c478bd9Sstevel@tonic-gate 			goto letsyn;
2067c478bd9Sstevel@tonic-gate 		vp = savestr(vp);
2077c478bd9Sstevel@tonic-gate 		if (op == '=') {
2087c478bd9Sstevel@tonic-gate 			c = '=';
2097c478bd9Sstevel@tonic-gate 			p = xset(p, &v);
2107c478bd9Sstevel@tonic-gate 		} else {
2117c478bd9Sstevel@tonic-gate 			c = *p++;
2127c478bd9Sstevel@tonic-gate 			/* if (any(c, "+-")) { */
2137c478bd9Sstevel@tonic-gate 			if (c == '+' || c == '-') {
2147c478bd9Sstevel@tonic-gate 				if (c != op || *p)
2157c478bd9Sstevel@tonic-gate 					goto letsyn;
2167c478bd9Sstevel@tonic-gate 				p = plusplus;
2177c478bd9Sstevel@tonic-gate 			} else {
218*65b0c20eSnakanon 				/* if (any(op, "<>")) { */
2197c478bd9Sstevel@tonic-gate 				if (op == '<' || op == '>') {
2207c478bd9Sstevel@tonic-gate 					if (c != op)
2217c478bd9Sstevel@tonic-gate 						goto letsyn;
2227c478bd9Sstevel@tonic-gate 					c = *p++;
2237c478bd9Sstevel@tonic-gate letsyn:
2247c478bd9Sstevel@tonic-gate 					bferr("Syntax error");
2257c478bd9Sstevel@tonic-gate 				}
2267c478bd9Sstevel@tonic-gate 				if (c != '=')
2277c478bd9Sstevel@tonic-gate 					goto letsyn;
2287c478bd9Sstevel@tonic-gate 				p = xset(p, &v);
2297c478bd9Sstevel@tonic-gate 			}
2307c478bd9Sstevel@tonic-gate 		}
2317c478bd9Sstevel@tonic-gate 		if (op == '=')
2327c478bd9Sstevel@tonic-gate 			if (hadsub)
2337c478bd9Sstevel@tonic-gate 				asx(vp, subscr, p);
2347c478bd9Sstevel@tonic-gate 			else
2357c478bd9Sstevel@tonic-gate 				set(vp, p);
2367c478bd9Sstevel@tonic-gate 		else
2377c478bd9Sstevel@tonic-gate 			if (hadsub)
2387c478bd9Sstevel@tonic-gate #ifndef V6
2397c478bd9Sstevel@tonic-gate 				/* avoid bug in vax CC */
2407c478bd9Sstevel@tonic-gate 				{
2417c478bd9Sstevel@tonic-gate 					struct varent *gv = getvx(vp, subscr);
2427c478bd9Sstevel@tonic-gate 
2437c478bd9Sstevel@tonic-gate 					asx(vp, subscr, operate(op, gv->vec[subscr - 1], p));
2447c478bd9Sstevel@tonic-gate 				}
2457c478bd9Sstevel@tonic-gate #else
2467c478bd9Sstevel@tonic-gate 				asx(vp, subscr, operate(op, getvx(vp, subscr)->vec[subscr - 1], p));
2477c478bd9Sstevel@tonic-gate #endif
2487c478bd9Sstevel@tonic-gate 			else
2497c478bd9Sstevel@tonic-gate 				set(vp, operate(op, value(vp), p));
250*65b0c20eSnakanon 		if (eq(vp, S_path /* "path" */)) {
251*65b0c20eSnakanon 			exportpath(adrof(S_path /* "path" */)->vec);
2527c478bd9Sstevel@tonic-gate 			dohash(xhash);
2537c478bd9Sstevel@tonic-gate 		}
2547c478bd9Sstevel@tonic-gate 
255*65b0c20eSnakanon 		if (eq(vp, S_cdpath /* "cdpath" */))
2567c478bd9Sstevel@tonic-gate 			dohash(xhash2);
2577c478bd9Sstevel@tonic-gate 
258*65b0c20eSnakanon 		xfree(vp);
2597c478bd9Sstevel@tonic-gate 		if (c != '=')
260*65b0c20eSnakanon 			xfree(p);
2617c478bd9Sstevel@tonic-gate 	} while (p = *v++);
2627c478bd9Sstevel@tonic-gate }
2637c478bd9Sstevel@tonic-gate 
2647c478bd9Sstevel@tonic-gate tchar *
xset(tchar * cp,tchar *** vp)2656c02b4a4Smuffin xset(tchar *cp, tchar ***vp)
2667c478bd9Sstevel@tonic-gate {
2676c02b4a4Smuffin 	tchar *dp;
2687c478bd9Sstevel@tonic-gate 
2697c478bd9Sstevel@tonic-gate #ifdef TRACE
2707c478bd9Sstevel@tonic-gate 	tprintf("TRACE- xset()\n");
2717c478bd9Sstevel@tonic-gate #endif
2727c478bd9Sstevel@tonic-gate 	if (*cp) {
2737c478bd9Sstevel@tonic-gate 		dp = savestr(cp);
2747c478bd9Sstevel@tonic-gate 		--(*vp);
2757c478bd9Sstevel@tonic-gate 		xfree(**vp);
2767c478bd9Sstevel@tonic-gate 		**vp = dp;
2777c478bd9Sstevel@tonic-gate 	}
2787c478bd9Sstevel@tonic-gate 	return (putn(exp(vp)));
2797c478bd9Sstevel@tonic-gate }
2807c478bd9Sstevel@tonic-gate 
2817c478bd9Sstevel@tonic-gate tchar *
operate(tchar op,tchar * vp,tchar * p)2826c02b4a4Smuffin operate(tchar op, tchar *vp, tchar *p)
2837c478bd9Sstevel@tonic-gate {
2847c478bd9Sstevel@tonic-gate 	tchar opr[2];
2857c478bd9Sstevel@tonic-gate 	tchar *vec[5];
2866c02b4a4Smuffin 	tchar **v = vec;
2877c478bd9Sstevel@tonic-gate 	tchar **vecp = v;
2886c02b4a4Smuffin 	int i;
2897c478bd9Sstevel@tonic-gate 
2907c478bd9Sstevel@tonic-gate 	if (op != '=') {
2917c478bd9Sstevel@tonic-gate 		if (*vp)
2927c478bd9Sstevel@tonic-gate 			*v++ = vp;
2937c478bd9Sstevel@tonic-gate 		opr[0] = op;
2947c478bd9Sstevel@tonic-gate 		opr[1] = 0;
2957c478bd9Sstevel@tonic-gate 		*v++ = opr;
2967c478bd9Sstevel@tonic-gate 		if (op == '<' || op == '>')
2977c478bd9Sstevel@tonic-gate 			*v++ = opr;
2987c478bd9Sstevel@tonic-gate 	}
2997c478bd9Sstevel@tonic-gate 	*v++ = p;
3007c478bd9Sstevel@tonic-gate 	*v++ = 0;
3017c478bd9Sstevel@tonic-gate 	i = exp(&vecp);
3027c478bd9Sstevel@tonic-gate 	if (*vecp)
3037c478bd9Sstevel@tonic-gate 		bferr("Expression syntax");
3047c478bd9Sstevel@tonic-gate 	return (putn(i));
3057c478bd9Sstevel@tonic-gate }
3067c478bd9Sstevel@tonic-gate 
3077c478bd9Sstevel@tonic-gate static tchar *putp;
308*65b0c20eSnakanon 
3097c478bd9Sstevel@tonic-gate tchar *
putn(int n)3106c02b4a4Smuffin putn(int n)
3117c478bd9Sstevel@tonic-gate {
3127c478bd9Sstevel@tonic-gate 	static tchar number[15];
3137c478bd9Sstevel@tonic-gate 
3147c478bd9Sstevel@tonic-gate #ifdef TRACE
3157c478bd9Sstevel@tonic-gate 	tprintf("TRACE- putn()\n");
3167c478bd9Sstevel@tonic-gate #endif
3177c478bd9Sstevel@tonic-gate 	putp = number;
3187c478bd9Sstevel@tonic-gate 	if (n < 0) {
3197c478bd9Sstevel@tonic-gate 		n = -n;
3207c478bd9Sstevel@tonic-gate 		*putp++ = '-';
3217c478bd9Sstevel@tonic-gate 	}
3227c478bd9Sstevel@tonic-gate 	if (sizeof (int) == 2 && n == -32768) {
3237c478bd9Sstevel@tonic-gate 		*putp++ = '3';
3247c478bd9Sstevel@tonic-gate 		n = 2768;
3257c478bd9Sstevel@tonic-gate #ifdef pdp11
3267c478bd9Sstevel@tonic-gate 	}
3277c478bd9Sstevel@tonic-gate #else
3287c478bd9Sstevel@tonic-gate 	} else if (sizeof (int) == 4 && n == 0x80000000) {
3297c478bd9Sstevel@tonic-gate 		*putp++ = '2';
3307c478bd9Sstevel@tonic-gate 		n = 147483648;
3317c478bd9Sstevel@tonic-gate 	}
3327c478bd9Sstevel@tonic-gate #endif
3337c478bd9Sstevel@tonic-gate 	putn1(n);
3347c478bd9Sstevel@tonic-gate 	*putp = 0;
3357c478bd9Sstevel@tonic-gate 	return (savestr(number));
3367c478bd9Sstevel@tonic-gate }
3377c478bd9Sstevel@tonic-gate 
3386c02b4a4Smuffin void
putn1(int n)3396c02b4a4Smuffin putn1(int n)
3407c478bd9Sstevel@tonic-gate {
3417c478bd9Sstevel@tonic-gate #ifdef TRACE
3427c478bd9Sstevel@tonic-gate 	tprintf("TRACE- putn1()\n");
3437c478bd9Sstevel@tonic-gate #endif
3447c478bd9Sstevel@tonic-gate 	if (n > 9)
3457c478bd9Sstevel@tonic-gate 		putn1(n / 10);
3467c478bd9Sstevel@tonic-gate 	*putp++ = n % 10 + '0';
3477c478bd9Sstevel@tonic-gate }
3487c478bd9Sstevel@tonic-gate 
3496c02b4a4Smuffin int
getn(tchar * cp)3506c02b4a4Smuffin getn(tchar *cp)
3517c478bd9Sstevel@tonic-gate {
3526c02b4a4Smuffin 	int n;
3537c478bd9Sstevel@tonic-gate 	int sign;
3547c478bd9Sstevel@tonic-gate 
3557c478bd9Sstevel@tonic-gate #ifdef TRACE
3567c478bd9Sstevel@tonic-gate 	tprintf("TRACE- getn()\n");
3577c478bd9Sstevel@tonic-gate #endif
3587c478bd9Sstevel@tonic-gate 	sign = 0;
3597c478bd9Sstevel@tonic-gate 	if (cp[0] == '+' && cp[1])
3607c478bd9Sstevel@tonic-gate 		cp++;
3617c478bd9Sstevel@tonic-gate 	if (*cp == '-') {
3627c478bd9Sstevel@tonic-gate 		sign++;
3637c478bd9Sstevel@tonic-gate 		cp++;
3647c478bd9Sstevel@tonic-gate 		if (!digit(*cp))
3657c478bd9Sstevel@tonic-gate 			goto badnum;
3667c478bd9Sstevel@tonic-gate 	}
3677c478bd9Sstevel@tonic-gate 	n = 0;
3687c478bd9Sstevel@tonic-gate 	while (digit(*cp))
3697c478bd9Sstevel@tonic-gate 		n = n * 10 + *cp++ - '0';
3707c478bd9Sstevel@tonic-gate 	if (*cp)
3717c478bd9Sstevel@tonic-gate 		goto badnum;
3727c478bd9Sstevel@tonic-gate 	return (sign ? -n : n);
3737c478bd9Sstevel@tonic-gate badnum:
3747c478bd9Sstevel@tonic-gate 	bferr("Badly formed number");
3757c478bd9Sstevel@tonic-gate 	return (0);
3767c478bd9Sstevel@tonic-gate }
3777c478bd9Sstevel@tonic-gate 
3787c478bd9Sstevel@tonic-gate tchar *
value1(tchar * var,struct varent * head)3796c02b4a4Smuffin value1(tchar *var, struct varent *head)
3807c478bd9Sstevel@tonic-gate {
3816c02b4a4Smuffin 	struct varent *vp;
3827c478bd9Sstevel@tonic-gate 
3837c478bd9Sstevel@tonic-gate #ifdef TRACE
3847c478bd9Sstevel@tonic-gate 	tprintf("TRACE- value1()\n");
3857c478bd9Sstevel@tonic-gate #endif
3867c478bd9Sstevel@tonic-gate 	vp = adrof1(var, head);
387*65b0c20eSnakanon 	return (vp == 0 || vp->vec[0] == 0 ? S_ /* "" */ : vp->vec[0]);
3887c478bd9Sstevel@tonic-gate }
3897c478bd9Sstevel@tonic-gate 
3907c478bd9Sstevel@tonic-gate struct varent *
madrof(tchar * pat,struct varent * vp)3916c02b4a4Smuffin madrof(tchar *pat, struct varent *vp)
3927c478bd9Sstevel@tonic-gate {
3936c02b4a4Smuffin 	struct varent *vp1;
3947c478bd9Sstevel@tonic-gate 
3957c478bd9Sstevel@tonic-gate #ifdef TRACE
3967c478bd9Sstevel@tonic-gate 	tprintf("TRACE- madrof()\n");
3977c478bd9Sstevel@tonic-gate #endif
3987c478bd9Sstevel@tonic-gate 	for (; vp; vp = vp->v_right) {
3997c478bd9Sstevel@tonic-gate 		if (vp->v_left && (vp1 = madrof(pat, vp->v_left)))
4007c478bd9Sstevel@tonic-gate 			return vp1;
4017c478bd9Sstevel@tonic-gate 		if (Gmatch(vp->v_name, pat))
4027c478bd9Sstevel@tonic-gate 			return vp;
4037c478bd9Sstevel@tonic-gate 	}
4047c478bd9Sstevel@tonic-gate 	return vp;
4057c478bd9Sstevel@tonic-gate }
4067c478bd9Sstevel@tonic-gate 
4077c478bd9Sstevel@tonic-gate struct varent *
adrof1(tchar * name,struct varent * v)4086c02b4a4Smuffin adrof1(tchar *name, struct varent *v)
4097c478bd9Sstevel@tonic-gate {
4106c02b4a4Smuffin 	int cmp;
4117c478bd9Sstevel@tonic-gate 
4127c478bd9Sstevel@tonic-gate #ifdef TRACE
4137c478bd9Sstevel@tonic-gate 	tprintf("TRACE- adrof1()\n");
4147c478bd9Sstevel@tonic-gate #endif
4157c478bd9Sstevel@tonic-gate 	v = v->v_left;
4167c478bd9Sstevel@tonic-gate 	while (v && ((cmp = *name - *v->v_name) ||
417*65b0c20eSnakanon 	    (cmp = strcmp_(name, v->v_name))))
4187c478bd9Sstevel@tonic-gate 		if (cmp < 0)
4197c478bd9Sstevel@tonic-gate 			v = v->v_left;
4207c478bd9Sstevel@tonic-gate 		else
4217c478bd9Sstevel@tonic-gate 			v = v->v_right;
4227c478bd9Sstevel@tonic-gate 	return v;
4237c478bd9Sstevel@tonic-gate }
4247c478bd9Sstevel@tonic-gate 
4257c478bd9Sstevel@tonic-gate /*
4267c478bd9Sstevel@tonic-gate  * The caller is responsible for putting value in a safe place
4277c478bd9Sstevel@tonic-gate  */
4286c02b4a4Smuffin void
set(tchar * var,tchar * val)4296c02b4a4Smuffin set(tchar *var, tchar *val)
4307c478bd9Sstevel@tonic-gate {
431*65b0c20eSnakanon 	tchar **vec =  (tchar **)xalloc(2 * sizeof (tchar **));
4327c478bd9Sstevel@tonic-gate 
4337c478bd9Sstevel@tonic-gate #ifdef TRACE
4347c478bd9Sstevel@tonic-gate 	tprintf("TRACE- set()\n");
4357c478bd9Sstevel@tonic-gate #endif
4367c478bd9Sstevel@tonic-gate 	vec[0] = onlyread(val) ? savestr(val) : val;
4377c478bd9Sstevel@tonic-gate 	vec[1] = 0;
4387c478bd9Sstevel@tonic-gate 	set1(var, vec, &shvhed);
4397c478bd9Sstevel@tonic-gate }
4407c478bd9Sstevel@tonic-gate 
4416c02b4a4Smuffin void
set1(tchar * var,tchar ** vec,struct varent * head)4426c02b4a4Smuffin set1(tchar *var, tchar **vec, struct varent *head)
4437c478bd9Sstevel@tonic-gate {
4446c02b4a4Smuffin 	tchar **oldv = vec;
4457c478bd9Sstevel@tonic-gate 
4467c478bd9Sstevel@tonic-gate #ifdef TRACE
4477c478bd9Sstevel@tonic-gate 	tprintf("TRACE- set1()\n");
4487c478bd9Sstevel@tonic-gate #endif
4497c478bd9Sstevel@tonic-gate 	gflag = 0;
450*65b0c20eSnakanon 	/*
451*65b0c20eSnakanon 	 * If setting cwd variable via "set cwd=/tmp/something"
4527c478bd9Sstevel@tonic-gate 	 * then do globbing.  But if we are setting the cwd
453*65b0c20eSnakanon 	 * becuz of a cd, chdir, pushd, popd, do not do globbing.
4547c478bd9Sstevel@tonic-gate 	 */
455*65b0c20eSnakanon 	if ((!(eq(var, S_cwd))) || (eq(var, S_cwd) && (didchdir == 0)))
4567c478bd9Sstevel@tonic-gate 		{
457*65b0c20eSnakanon 		tglob(oldv);
4587c478bd9Sstevel@tonic-gate 		}
4597c478bd9Sstevel@tonic-gate 	if (gflag) {
4607c478bd9Sstevel@tonic-gate 		vec = glob(oldv);
4617c478bd9Sstevel@tonic-gate 		if (vec == 0) {
4627c478bd9Sstevel@tonic-gate 			bferr("No match");
4637c478bd9Sstevel@tonic-gate 			blkfree(oldv);
4647c478bd9Sstevel@tonic-gate 			return;
4657c478bd9Sstevel@tonic-gate 		}
4667c478bd9Sstevel@tonic-gate 		blkfree(oldv);
4677c478bd9Sstevel@tonic-gate 		gargv = 0;
4687c478bd9Sstevel@tonic-gate 	}
4697c478bd9Sstevel@tonic-gate 	setq(var, vec, head);
4707c478bd9Sstevel@tonic-gate }
4717c478bd9Sstevel@tonic-gate 
4726c02b4a4Smuffin void
setq(tchar * name,tchar ** vec,struct varent * p)4736c02b4a4Smuffin setq(tchar *name, tchar **vec, struct varent *p)
4747c478bd9Sstevel@tonic-gate {
4756c02b4a4Smuffin 	struct varent *c;
4766c02b4a4Smuffin 	int f;
4777c478bd9Sstevel@tonic-gate 
4787c478bd9Sstevel@tonic-gate #ifdef TRACE
4797c478bd9Sstevel@tonic-gate 	tprintf("TRACE- setq()\n");
4807c478bd9Sstevel@tonic-gate #endif
4817c478bd9Sstevel@tonic-gate 	f = 0;			/* tree hangs off the header's left link */
4827c478bd9Sstevel@tonic-gate 	while (c = p->v_link[f]) {
4837c478bd9Sstevel@tonic-gate 		if ((f = *name - *c->v_name) == 0 &&
4847c478bd9Sstevel@tonic-gate 		    (f = strcmp_(name, c->v_name)) == 0) {
4857c478bd9Sstevel@tonic-gate 			blkfree(c->vec);
4867c478bd9Sstevel@tonic-gate 			goto found;
4877c478bd9Sstevel@tonic-gate 		}
4887c478bd9Sstevel@tonic-gate 		p = c;
4897c478bd9Sstevel@tonic-gate 		f = f > 0;
4907c478bd9Sstevel@tonic-gate 	}
4917c478bd9Sstevel@tonic-gate 	p->v_link[f] = c = (struct varent *)xalloc(sizeof (struct varent));
4927c478bd9Sstevel@tonic-gate 	c->v_name = savestr(name);
4937c478bd9Sstevel@tonic-gate 	c->v_bal = 0;
4947c478bd9Sstevel@tonic-gate 	c->v_left = c->v_right = 0;
4957c478bd9Sstevel@tonic-gate 	c->v_parent = p;
4967c478bd9Sstevel@tonic-gate 	balance(p, f, 0);
4977c478bd9Sstevel@tonic-gate found:
4987c478bd9Sstevel@tonic-gate 	trim(c->vec = vec);
4997c478bd9Sstevel@tonic-gate }
5007c478bd9Sstevel@tonic-gate 
5016c02b4a4Smuffin void
unset(tchar * v[])5026c02b4a4Smuffin unset(tchar *v[])
5037c478bd9Sstevel@tonic-gate {
5047c478bd9Sstevel@tonic-gate 
5057c478bd9Sstevel@tonic-gate #ifdef TRACE
5067c478bd9Sstevel@tonic-gate 	tprintf("TRACE- unset()\n");
5077c478bd9Sstevel@tonic-gate #endif
5087c478bd9Sstevel@tonic-gate 	unset1(v, &shvhed);
509*65b0c20eSnakanon 	if (adrof(S_histchars /* "histchars" */) == 0) {
5107c478bd9Sstevel@tonic-gate 		HIST = '!';
5117c478bd9Sstevel@tonic-gate 		HISTSUB = '^';
5127c478bd9Sstevel@tonic-gate 	}
5137c478bd9Sstevel@tonic-gate #ifdef FILEC
514*65b0c20eSnakanon 	if (adrof(S_filec /* "filec" */) == 0)
5157c478bd9Sstevel@tonic-gate 		filec = 0;
5167c478bd9Sstevel@tonic-gate #endif
5177c478bd9Sstevel@tonic-gate }
5187c478bd9Sstevel@tonic-gate 
5196c02b4a4Smuffin void
unset1(tchar * v[],struct varent * head)5206c02b4a4Smuffin unset1(tchar *v[], struct varent *head)
5217c478bd9Sstevel@tonic-gate {
5226c02b4a4Smuffin 	struct varent *vp;
5236c02b4a4Smuffin 	int cnt;
5247c478bd9Sstevel@tonic-gate 
5257c478bd9Sstevel@tonic-gate #ifdef TRACE
5267c478bd9Sstevel@tonic-gate 	tprintf("TRACE- unset1()\n");
5277c478bd9Sstevel@tonic-gate #endif
5287c478bd9Sstevel@tonic-gate 	while (*++v) {
5297c478bd9Sstevel@tonic-gate 		cnt = 0;
5307c478bd9Sstevel@tonic-gate 		while (vp = madrof(*v, head->v_left))
5317c478bd9Sstevel@tonic-gate 			unsetv1(vp), cnt++;
5327c478bd9Sstevel@tonic-gate 		if (cnt == 0)
5337c478bd9Sstevel@tonic-gate 			setname(*v);
5347c478bd9Sstevel@tonic-gate 	}
5357c478bd9Sstevel@tonic-gate }
5367c478bd9Sstevel@tonic-gate 
5376c02b4a4Smuffin void
unsetv(tchar * var)5386c02b4a4Smuffin unsetv(tchar *var)
5397c478bd9Sstevel@tonic-gate {
5406c02b4a4Smuffin 	struct varent *vp;
5417c478bd9Sstevel@tonic-gate 
5427c478bd9Sstevel@tonic-gate #ifdef TRACE
5437c478bd9Sstevel@tonic-gate 	tprintf("TRACE- unsetv()\n");
5447c478bd9Sstevel@tonic-gate #endif
5457c478bd9Sstevel@tonic-gate 	if ((vp = adrof1(var, &shvhed)) == 0)
5467c478bd9Sstevel@tonic-gate 		udvar(var);
5477c478bd9Sstevel@tonic-gate 	unsetv1(vp);
5487c478bd9Sstevel@tonic-gate }
5497c478bd9Sstevel@tonic-gate 
5506c02b4a4Smuffin void
unsetv1(struct varent * p)5516c02b4a4Smuffin unsetv1(struct varent *p)
5527c478bd9Sstevel@tonic-gate {
5536c02b4a4Smuffin 	struct varent *c, *pp;
5546c02b4a4Smuffin 	int f;
5557c478bd9Sstevel@tonic-gate 
5567c478bd9Sstevel@tonic-gate #ifdef TRACE
5577c478bd9Sstevel@tonic-gate 	tprintf("TRACE- unsetv1()\n");
5587c478bd9Sstevel@tonic-gate #endif
5597c478bd9Sstevel@tonic-gate 	/*
5607c478bd9Sstevel@tonic-gate 	 * Free associated memory first to avoid complications.
5617c478bd9Sstevel@tonic-gate 	 */
5627c478bd9Sstevel@tonic-gate 	blkfree(p->vec);
563*65b0c20eSnakanon 	xfree(p->v_name);
5647c478bd9Sstevel@tonic-gate 	/*
5657c478bd9Sstevel@tonic-gate 	 * If p is missing one child, then we can move the other
5667c478bd9Sstevel@tonic-gate 	 * into where p is.  Otherwise, we find the predecessor
5677c478bd9Sstevel@tonic-gate 	 * of p, which is guaranteed to have no right child, copy
5687c478bd9Sstevel@tonic-gate 	 * it into p, and move it's left child into it.
5697c478bd9Sstevel@tonic-gate 	 */
5707c478bd9Sstevel@tonic-gate 	if (p->v_right == 0)
5717c478bd9Sstevel@tonic-gate 		c = p->v_left;
5727c478bd9Sstevel@tonic-gate 	else if (p->v_left == 0)
5737c478bd9Sstevel@tonic-gate 		c = p->v_right;
5747c478bd9Sstevel@tonic-gate 	else {
5757c478bd9Sstevel@tonic-gate 		for (c = p->v_left; c->v_right; c = c->v_right)
5767c478bd9Sstevel@tonic-gate 			;
5777c478bd9Sstevel@tonic-gate 		p->v_name = c->v_name;
5787c478bd9Sstevel@tonic-gate 		p->vec = c->vec;
5797c478bd9Sstevel@tonic-gate 		p = c;
5807c478bd9Sstevel@tonic-gate 		c = p->v_left;
5817c478bd9Sstevel@tonic-gate 	}
5827c478bd9Sstevel@tonic-gate 	/*
5837c478bd9Sstevel@tonic-gate 	 * Move c into where p is.
5847c478bd9Sstevel@tonic-gate 	 */
5857c478bd9Sstevel@tonic-gate 	pp = p->v_parent;
5867c478bd9Sstevel@tonic-gate 	f = pp->v_right == p;
5877c478bd9Sstevel@tonic-gate 	if (pp->v_link[f] = c)
5887c478bd9Sstevel@tonic-gate 		c->v_parent = pp;
5897c478bd9Sstevel@tonic-gate 	/*
5907c478bd9Sstevel@tonic-gate 	 * Free the deleted node, and rebalance.
5917c478bd9Sstevel@tonic-gate 	 */
592*65b0c20eSnakanon 	xfree(p);
5937c478bd9Sstevel@tonic-gate 	balance(pp, f, 1);
5947c478bd9Sstevel@tonic-gate }
5957c478bd9Sstevel@tonic-gate 
5966c02b4a4Smuffin void
setNS(tchar * cp)5976c02b4a4Smuffin setNS(tchar *cp)
5987c478bd9Sstevel@tonic-gate {
5997c478bd9Sstevel@tonic-gate #ifdef TRACE
6007c478bd9Sstevel@tonic-gate 	tprintf("TRACE- setNS()\n");
6017c478bd9Sstevel@tonic-gate #endif
6027c478bd9Sstevel@tonic-gate 
603*65b0c20eSnakanon 	set(cp, S_ /* "" */);
6047c478bd9Sstevel@tonic-gate }
6057c478bd9Sstevel@tonic-gate 
6066c02b4a4Smuffin void
shift(tchar ** v)6076c02b4a4Smuffin shift(tchar **v)
6087c478bd9Sstevel@tonic-gate {
6096c02b4a4Smuffin 	struct varent *argv;
6106c02b4a4Smuffin 	tchar *name;
6117c478bd9Sstevel@tonic-gate 
6127c478bd9Sstevel@tonic-gate #ifdef TRACE
6137c478bd9Sstevel@tonic-gate 	tprintf("TRACE- shift()\n");
6147c478bd9Sstevel@tonic-gate #endif
6157c478bd9Sstevel@tonic-gate 	v++;
6167c478bd9Sstevel@tonic-gate 	name = *v;
6177c478bd9Sstevel@tonic-gate 	if (name == 0)
618*65b0c20eSnakanon 		name = S_argv /* "argv" */;
6197c478bd9Sstevel@tonic-gate 	else
6207c478bd9Sstevel@tonic-gate 		(void) strip(name);
6217c478bd9Sstevel@tonic-gate 	argv = adrof(name);
6227c478bd9Sstevel@tonic-gate 	if (argv == 0)
6237c478bd9Sstevel@tonic-gate 		udvar(name);
6247c478bd9Sstevel@tonic-gate 	if (argv->vec[0] == 0)
6257c478bd9Sstevel@tonic-gate 		bferr("No more words");
6267c478bd9Sstevel@tonic-gate 	lshift(argv->vec, 1);
6277c478bd9Sstevel@tonic-gate }
6287c478bd9Sstevel@tonic-gate 
6296c02b4a4Smuffin void
exportpath(tchar ** val)6306c02b4a4Smuffin exportpath(tchar **val)
6317c478bd9Sstevel@tonic-gate {
6327c478bd9Sstevel@tonic-gate 	tchar exppath[PATHSIZ];
6337c478bd9Sstevel@tonic-gate 
6347c478bd9Sstevel@tonic-gate #ifdef TRACE
6357c478bd9Sstevel@tonic-gate 	tprintf("TRACE- exportpath()\n");
6367c478bd9Sstevel@tonic-gate #endif
6377c478bd9Sstevel@tonic-gate 	exppath[0] = 0;
6387c478bd9Sstevel@tonic-gate 	if (val)
6397c478bd9Sstevel@tonic-gate 		while (*val) {
6407c478bd9Sstevel@tonic-gate 			if (strlen_(*val) + strlen_(exppath) + 2 > PATHSIZ) {
6417c478bd9Sstevel@tonic-gate 				printf("Warning: ridiculously long PATH truncated\n");
6427c478bd9Sstevel@tonic-gate 				break;
6437c478bd9Sstevel@tonic-gate 			}
6447c478bd9Sstevel@tonic-gate 			(void) strcat_(exppath, *val++);
645*65b0c20eSnakanon 			if (*val == 0 || eq(*val, S_RPAR /* ")" */))
6467c478bd9Sstevel@tonic-gate 				break;
647*65b0c20eSnakanon 			(void) strcat_(exppath, S_COLON /* ":" */);
6487c478bd9Sstevel@tonic-gate 		}
649*65b0c20eSnakanon 	local_setenv(S_PATH /* "PATH" */, exppath);
6507c478bd9Sstevel@tonic-gate }
6517c478bd9Sstevel@tonic-gate 
6527c478bd9Sstevel@tonic-gate 	/* macros to do single rotations on node p */
653*65b0c20eSnakanon #define	rright(p) (\
6547c478bd9Sstevel@tonic-gate 	t = (p)->v_left,\
6557c478bd9Sstevel@tonic-gate 	(t)->v_parent = (p)->v_parent,\
6567c478bd9Sstevel@tonic-gate 	((p)->v_left = t->v_right) ? (t->v_right->v_parent = (p)) : 0,\
6577c478bd9Sstevel@tonic-gate 	(t->v_right = (p))->v_parent = t,\
6587c478bd9Sstevel@tonic-gate 	(p) = t)
659*65b0c20eSnakanon #define	rleft(p) (\
6607c478bd9Sstevel@tonic-gate 	t = (p)->v_right,\
6617c478bd9Sstevel@tonic-gate 	(t)->v_parent = (p)->v_parent,\
6627c478bd9Sstevel@tonic-gate 	((p)->v_right = t->v_left) ? (t->v_left->v_parent = (p)) : 0,\
6637c478bd9Sstevel@tonic-gate 	(t->v_left = (p))->v_parent = t,\
6647c478bd9Sstevel@tonic-gate 	(p) = t)
6657c478bd9Sstevel@tonic-gate 
6667c478bd9Sstevel@tonic-gate /*
6677c478bd9Sstevel@tonic-gate  * Rebalance a tree, starting at p and up.
6687c478bd9Sstevel@tonic-gate  * F == 0 means we've come from p's left child.
6697c478bd9Sstevel@tonic-gate  * D == 1 means we've just done a delete, otherwise an insert.
6707c478bd9Sstevel@tonic-gate  */
6716c02b4a4Smuffin void
balance(struct varent * p,int f,int d)6726c02b4a4Smuffin balance(struct varent *p, int f, int d)
6737c478bd9Sstevel@tonic-gate {
6746c02b4a4Smuffin 	struct varent *pp;
6756c02b4a4Smuffin 	struct varent *t;		/* used by the rotate macros */
6766c02b4a4Smuffin 	int ff;
6777c478bd9Sstevel@tonic-gate 
6787c478bd9Sstevel@tonic-gate #ifdef TRACE
6797c478bd9Sstevel@tonic-gate 	tprintf("TRACE- balance()\n");
6807c478bd9Sstevel@tonic-gate #endif
6817c478bd9Sstevel@tonic-gate 	/*
6827c478bd9Sstevel@tonic-gate 	 * Ok, from here on, p is the node we're operating on;
6837c478bd9Sstevel@tonic-gate 	 * pp is it's parent; f is the branch of p from which we have come;
6847c478bd9Sstevel@tonic-gate 	 * ff is the branch of pp which is p.
6857c478bd9Sstevel@tonic-gate 	 */
6867c478bd9Sstevel@tonic-gate 	for (; pp = p->v_parent; p = pp, f = ff) {
6877c478bd9Sstevel@tonic-gate 		ff = pp->v_right == p;
6887c478bd9Sstevel@tonic-gate 		if (f ^ d) {		/* right heavy */
6897c478bd9Sstevel@tonic-gate 			switch (p->v_bal) {
6907c478bd9Sstevel@tonic-gate 			case -1:		/* was left heavy */
6917c478bd9Sstevel@tonic-gate 				p->v_bal = 0;
6927c478bd9Sstevel@tonic-gate 				break;
6937c478bd9Sstevel@tonic-gate 			case 0:			/* was balanced */
6947c478bd9Sstevel@tonic-gate 				p->v_bal = 1;
6957c478bd9Sstevel@tonic-gate 				break;
6967c478bd9Sstevel@tonic-gate 			case 1:			/* was already right heavy */
6977c478bd9Sstevel@tonic-gate 				switch (p->v_right->v_bal) {
6987c478bd9Sstevel@tonic-gate 				case 1:			/* sigle rotate */
6997c478bd9Sstevel@tonic-gate 					pp->v_link[ff] = rleft(p);
7007c478bd9Sstevel@tonic-gate 					p->v_left->v_bal = 0;
7017c478bd9Sstevel@tonic-gate 					p->v_bal = 0;
7027c478bd9Sstevel@tonic-gate 					break;
7037c478bd9Sstevel@tonic-gate 				case 0:			/* single rotate */
7047c478bd9Sstevel@tonic-gate 					pp->v_link[ff] = rleft(p);
7057c478bd9Sstevel@tonic-gate 					p->v_left->v_bal = 1;
7067c478bd9Sstevel@tonic-gate 					p->v_bal = -1;
7077c478bd9Sstevel@tonic-gate 					break;
7087c478bd9Sstevel@tonic-gate 				case -1:		/* double rotate */
7097c478bd9Sstevel@tonic-gate 					rright(p->v_right);
7107c478bd9Sstevel@tonic-gate 					pp->v_link[ff] = rleft(p);
7117c478bd9Sstevel@tonic-gate 					p->v_left->v_bal =
7127c478bd9Sstevel@tonic-gate 						p->v_bal < 1 ? 0 : -1;
7137c478bd9Sstevel@tonic-gate 					p->v_right->v_bal =
7147c478bd9Sstevel@tonic-gate 						p->v_bal > -1 ? 0 : 1;
7157c478bd9Sstevel@tonic-gate 					p->v_bal = 0;
7167c478bd9Sstevel@tonic-gate 					break;
7177c478bd9Sstevel@tonic-gate 				}
7187c478bd9Sstevel@tonic-gate 				break;
7197c478bd9Sstevel@tonic-gate 			}
7207c478bd9Sstevel@tonic-gate 		} else {		/* left heavy */
7217c478bd9Sstevel@tonic-gate 			switch (p->v_bal) {
7227c478bd9Sstevel@tonic-gate 			case 1:			/* was right heavy */
7237c478bd9Sstevel@tonic-gate 				p->v_bal = 0;
7247c478bd9Sstevel@tonic-gate 				break;
7257c478bd9Sstevel@tonic-gate 			case 0:			/* was balanced */
7267c478bd9Sstevel@tonic-gate 				p->v_bal = -1;
7277c478bd9Sstevel@tonic-gate 				break;
7287c478bd9Sstevel@tonic-gate 			case -1:		/* was already left heavy */
7297c478bd9Sstevel@tonic-gate 				switch (p->v_left->v_bal) {
7307c478bd9Sstevel@tonic-gate 				case -1:		/* single rotate */
7317c478bd9Sstevel@tonic-gate 					pp->v_link[ff] = rright(p);
7327c478bd9Sstevel@tonic-gate 					p->v_right->v_bal = 0;
7337c478bd9Sstevel@tonic-gate 					p->v_bal = 0;
7347c478bd9Sstevel@tonic-gate 					break;
7357c478bd9Sstevel@tonic-gate 				case 0:			/* signle rotate */
7367c478bd9Sstevel@tonic-gate 					pp->v_link[ff] = rright(p);
7377c478bd9Sstevel@tonic-gate 					p->v_right->v_bal = -1;
7387c478bd9Sstevel@tonic-gate 					p->v_bal = 1;
7397c478bd9Sstevel@tonic-gate 					break;
7407c478bd9Sstevel@tonic-gate 				case 1:			/* double rotate */
7417c478bd9Sstevel@tonic-gate 					rleft(p->v_left);
7427c478bd9Sstevel@tonic-gate 					pp->v_link[ff] = rright(p);
7437c478bd9Sstevel@tonic-gate 					p->v_left->v_bal =
7447c478bd9Sstevel@tonic-gate 						p->v_bal < 1 ? 0 : -1;
7457c478bd9Sstevel@tonic-gate 					p->v_right->v_bal =
7467c478bd9Sstevel@tonic-gate 						p->v_bal > -1 ? 0 : 1;
7477c478bd9Sstevel@tonic-gate 					p->v_bal = 0;
7487c478bd9Sstevel@tonic-gate 					break;
7497c478bd9Sstevel@tonic-gate 				}
7507c478bd9Sstevel@tonic-gate 				break;
7517c478bd9Sstevel@tonic-gate 			}
7527c478bd9Sstevel@tonic-gate 		}
7537c478bd9Sstevel@tonic-gate 		/*
7547c478bd9Sstevel@tonic-gate 		 * If from insert, then we terminate when p is balanced.
7557c478bd9Sstevel@tonic-gate 		 * If from delete, then we terminate when p is unbalanced.
7567c478bd9Sstevel@tonic-gate 		 */
7577c478bd9Sstevel@tonic-gate 		if ((p->v_bal == 0) ^ d)
7587c478bd9Sstevel@tonic-gate 			break;
7597c478bd9Sstevel@tonic-gate 	}
7607c478bd9Sstevel@tonic-gate }
7617c478bd9Sstevel@tonic-gate 
7626c02b4a4Smuffin void
plist(struct varent * p)7636c02b4a4Smuffin plist(struct varent *p)
7647c478bd9Sstevel@tonic-gate {
7656c02b4a4Smuffin 	struct varent *c;
7666c02b4a4Smuffin 	int len;
7677c478bd9Sstevel@tonic-gate 
7687c478bd9Sstevel@tonic-gate #ifdef TRACE
7697c478bd9Sstevel@tonic-gate 	tprintf("TRACE- plist()\n");
7707c478bd9Sstevel@tonic-gate #endif
7717c478bd9Sstevel@tonic-gate 	if (setintr)
7727c478bd9Sstevel@tonic-gate 		(void) sigsetmask(sigblock(0) & ~ sigmask(SIGINT));
7737c478bd9Sstevel@tonic-gate 	for (;;) {
7747c478bd9Sstevel@tonic-gate 		while (p->v_left)
7757c478bd9Sstevel@tonic-gate 			p = p->v_left;
7767c478bd9Sstevel@tonic-gate 	x:
7777c478bd9Sstevel@tonic-gate 		if (p->v_parent == 0)		/* is it the header? */
7787c478bd9Sstevel@tonic-gate 			return;
7797c478bd9Sstevel@tonic-gate 		len = blklen(p->vec);
7807c478bd9Sstevel@tonic-gate 		printf("%t", p->v_name);
7817c478bd9Sstevel@tonic-gate 		Putchar('\t');
7827c478bd9Sstevel@tonic-gate 		if (len != 1)
7837c478bd9Sstevel@tonic-gate 			Putchar('(');
7847c478bd9Sstevel@tonic-gate 		blkpr(p->vec);
7857c478bd9Sstevel@tonic-gate 		if (len != 1)
7867c478bd9Sstevel@tonic-gate 			Putchar(')');
7877c478bd9Sstevel@tonic-gate 		Putchar('\n');
7887c478bd9Sstevel@tonic-gate 		if (p->v_right) {
7897c478bd9Sstevel@tonic-gate 			p = p->v_right;
7907c478bd9Sstevel@tonic-gate 			continue;
7917c478bd9Sstevel@tonic-gate 		}
7927c478bd9Sstevel@tonic-gate 		do {
7937c478bd9Sstevel@tonic-gate 			c = p;
7947c478bd9Sstevel@tonic-gate 			p = p->v_parent;
7957c478bd9Sstevel@tonic-gate 		} while (p->v_right == c);
7967c478bd9Sstevel@tonic-gate 		goto x;
7977c478bd9Sstevel@tonic-gate 	}
7987c478bd9Sstevel@tonic-gate }
799