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