1*35179Smarc /*
2*35179Smarc 
3*35179Smarc  *      Copyright (c) 1984, 1985, 1986 AT&T
4*35179Smarc  *      All Rights Reserved
5*35179Smarc 
6*35179Smarc  *      THIS IS UNPUBLISHED PROPRIETARY SOURCE
7*35179Smarc  *      CODE OF AT&T.
8*35179Smarc  *      The copyright notice above does not
9*35179Smarc  *      evidence any actual or intended
10*35179Smarc  *      publication of such source code.
11*35179Smarc 
12*35179Smarc  */
13*35179Smarc /* @(#)arith.c	1.1 */
14*35179Smarc 
15*35179Smarc /*
16*35179Smarc  *   ARITH.C
17*35179Smarc  *
18*35179Smarc  *   Programmer:  D. G. Korn
19*35179Smarc  *
20*35179Smarc  *        Owner:  D. A. Lambeth
21*35179Smarc  *
22*35179Smarc  *         Date:  April 17, 1980
23*35179Smarc  *
24*35179Smarc  *
25*35179Smarc  *
26*35179Smarc  *   AEVAL (STRING)
27*35179Smarc  *
28*35179Smarc  *        Evaluate STRING as an arithmetic expression (possibly
29*35179Smarc  *        containing variables from trees in NAMEP) and return its value.
30*35179Smarc  *
31*35179Smarc  *   LOOKUP (NAME)
32*35179Smarc  *
33*35179Smarc  *        Return a pointer to the shell-owned Namnod in TREE
34*35179Smarc  *        whose namid is NAME.  If TYPE is non-zero, a new Namnod
35*35179Smarc  *        with the given namid will be inserted, when none is found.
36*35179Smarc  *
37*35179Smarc  *   These functions are indirectly mutually recursive.
38*35179Smarc  *
39*35179Smarc  *
40*35179Smarc  *
41*35179Smarc  *   See Also:  LET(I), findnod(III)
42*35179Smarc  */
43*35179Smarc 
44*35179Smarc #ifdef KSHELL
45*35179Smarc #include	"shtype.h"
46*35179Smarc #else
47*35179Smarc #include	<ctype.h>
48*35179Smarc #endif	/* KSHELL */
49*35179Smarc #include	<stdio.h>
50*35179Smarc #include	"name.h"
51*35179Smarc #include        "flags.h"
52*35179Smarc 
53*35179Smarc #define getchr()	(*(unsigned char*)strg++)
54*35179Smarc #define seekto(loc)	(strg=(loc))
55*35179Smarc #define ungetc()	(--strg)
56*35179Smarc #define peekc()		(*strg)
57*35179Smarc #define MAXLOOP	10
58*35179Smarc 
59*35179Smarc extern union Namval *aget_up();
60*35179Smarc extern char	*bracket_match();
61*35179Smarc extern char	*valup();
62*35179Smarc extern void	failed();
63*35179Smarc extern struct Namnod *findnod();
64*35179Smarc #ifdef  NAME_SCOPE
65*35179Smarc extern struct Namnod *copy_nod();
66*35179Smarc #endif
67*35179Smarc struct Namnod *lookup();
68*35179Smarc 
69*35179Smarc static long arith();
70*35179Smarc static void aerror();
71*35179Smarc 
72*35179Smarc static char *strg	=	0;
73*35179Smarc static int level	= 0;
74*35179Smarc 
75*35179Smarc /*
76*35179Smarc  *   AEVAL (STRING)
77*35179Smarc  *
78*35179Smarc  *        char *STRING;
79*35179Smarc  *
80*35179Smarc  *
81*35179Smarc  *   Evaluate string as an arithmetic expression (possibly
82*35179Smarc  *   containing variables from trees in NAMEP) and return its
83*35179Smarc  *   value as a long int.  STRING can be anything acceptable to
84*35179Smarc  *   the LET(I) builtin of the shell.
85*35179Smarc  *
86*35179Smarc  */
87*35179Smarc 
aeval(string)88*35179Smarc long aeval(string)
89*35179Smarc char *string;
90*35179Smarc {
91*35179Smarc 	long r;
92*35179Smarc 	long arith();
93*35179Smarc 	char *ostr;
94*35179Smarc 	ostr = strg;
95*35179Smarc 	if(level++ > MAXLOOP)
96*35179Smarc 		aerror(string,badnum);
97*35179Smarc 	strg = string;
98*35179Smarc 	r = arith(0);
99*35179Smarc 	strg = ostr;
100*35179Smarc 	level--;
101*35179Smarc 	return(r);
102*35179Smarc }
103*35179Smarc 
104*35179Smarc /*
105*35179Smarc  *   ARITH (PREC)
106*35179Smarc  *
107*35179Smarc  *        int PREC;
108*35179Smarc  *
109*35179Smarc  *   Evaluate the expression given in the global pointer strg
110*35179Smarc  *   as an arithmetic expression, to PREC digits.  The form
111*35179Smarc  *   of strg is as is given for the LET builtin.
112*35179Smarc  */
113*35179Smarc 
arith(prec)114*35179Smarc static long int arith(prec)
115*35179Smarc {
116*35179Smarc 	register int c;
117*35179Smarc #ifdef pdp11
118*35179Smarc 	long r;
119*35179Smarc 	long rr;
120*35179Smarc #else
121*35179Smarc 	register long r;
122*35179Smarc 	register long rr;
123*35179Smarc #endif
124*35179Smarc 	int base;
125*35179Smarc 	char *ostr;
126*35179Smarc 	char dot = 0;
127*35179Smarc 
128*35179Smarc  /* ignore whitespace */
129*35179Smarc 	while((c=getchr()),isspace(c));
130*35179Smarc 	if(c==0)
131*35179Smarc 		goto done;
132*35179Smarc 	ostr = (strg-1);
133*35179Smarc 	r = 0;
134*35179Smarc 	if(c == '-')
135*35179Smarc 		r = -arith(8);
136*35179Smarc 	else if(c == '!')
137*35179Smarc 		r = !arith(7);
138*35179Smarc 	else if(isalpha(c))
139*35179Smarc 	{
140*35179Smarc 		int oldc;
141*35179Smarc 		char *varname,*sp;
142*35179Smarc 		varname = ostr;
143*35179Smarc 		for(;isalnum(c);c=getchr());
144*35179Smarc 		if(c == '[')
145*35179Smarc 		{
146*35179Smarc 			seekto(bracket_match(ungetc()));
147*35179Smarc 			c = getchr();
148*35179Smarc 			if(c == 0)
149*35179Smarc 				aerror(varname,subscript);
150*35179Smarc 			c = getchr();
151*35179Smarc 		}
152*35179Smarc 		/* null terminate variable name */
153*35179Smarc 		sp = (strg-1);
154*35179Smarc 		*sp = 0;
155*35179Smarc 		/* skip over whitespace */
156*35179Smarc 		for(oldc = c;isspace(c);c = getchr());
157*35179Smarc 		if(c == '='&& peekc() != '=')
158*35179Smarc 			asslong(lookup(varname),r=arith(2));
159*35179Smarc 		else
160*35179Smarc 		{
161*35179Smarc 			char *str;
162*35179Smarc 			register struct Namnod *np = lookup(varname);
163*35179Smarc 			register union Namval *up;
164*35179Smarc 			ungetc();
165*35179Smarc                 	if (attest (np, INT_GER))
166*35179Smarc 			{
167*35179Smarc #ifdef NAME_SCOPE
168*35179Smarc 				if (attest (np,C_WRITE))
169*35179Smarc 					np = copy_nod(np,1);
170*35179Smarc #endif
171*35179Smarc 				up= &np->value.namval;
172*35179Smarc 				if(attest(np,IN_DIR))
173*35179Smarc 					up = up->up;
174*35179Smarc 				if(attest (np, (BLT_NOD)))
175*35179Smarc 					r = (long)((*up->fp->f_vp)());
176*35179Smarc 				else if(up->lp==NULL)
177*35179Smarc 					r = 0;
178*35179Smarc 				else
179*35179Smarc 	                        	r = *up->lp;
180*35179Smarc 			}
181*35179Smarc 		 else
182*35179Smarc 			{
183*35179Smarc 				if((str=valup(np))==0 || *str==0)
184*35179Smarc 					aerror(varname,badnum);
185*35179Smarc 				r = aeval(str);
186*35179Smarc 			}
187*35179Smarc 		}
188*35179Smarc 		*sp = oldc;
189*35179Smarc 	}
190*35179Smarc 	else
191*35179Smarc 	{
192*35179Smarc 		base = 10;
193*35179Smarc 		ungetc();
194*35179Smarc 		lastbase = base;
195*35179Smarc 	}
196*35179Smarc 
197*35179Smarc 	while((c=getchr()) && c != ']')
198*35179Smarc 	{
199*35179Smarc 		switch(c)
200*35179Smarc 		{
201*35179Smarc 			case ')':
202*35179Smarc 				if(prec)
203*35179Smarc 					goto done;
204*35179Smarc 				else
205*35179Smarc 					aerror(ostr,synmsg);
206*35179Smarc 
207*35179Smarc 			case '(':
208*35179Smarc 				r = arith(1);
209*35179Smarc 				if((c=getchr()) != ')')
210*35179Smarc 					aerror(ostr,synmsg);
211*35179Smarc 				break;
212*35179Smarc 
213*35179Smarc 			case '=':	case '!':
214*35179Smarc 				if(prec > 3)
215*35179Smarc 					goto done;
216*35179Smarc 				if(getchr() != '=')
217*35179Smarc 					aerror(ostr,synmsg);
218*35179Smarc 				rr = arith(4);
219*35179Smarc 				if(c == '=')
220*35179Smarc 					r = r == rr;
221*35179Smarc 				else
222*35179Smarc 					r = r != rr;
223*35179Smarc 				break;
224*35179Smarc 
225*35179Smarc 			case	'<':	case	'>':
226*35179Smarc 				if(prec > 4)
227*35179Smarc 					goto done;
228*35179Smarc 				if(peekc() == '=')
229*35179Smarc 				{
230*35179Smarc 					getchr();
231*35179Smarc 					rr = arith(5);
232*35179Smarc 					if(c == '<')
233*35179Smarc 						r = r <= rr;
234*35179Smarc 					else
235*35179Smarc 						r = r >= rr;
236*35179Smarc 					break;
237*35179Smarc 				}
238*35179Smarc 				rr = arith(5);
239*35179Smarc 				if(c == '<')
240*35179Smarc 					r = r < rr;
241*35179Smarc 				else
242*35179Smarc 					r = r > rr;
243*35179Smarc 				break;
244*35179Smarc 
245*35179Smarc 			case '+':	case '-':
246*35179Smarc 				if(prec > 5)
247*35179Smarc 					goto done;
248*35179Smarc 				rr = arith(6);
249*35179Smarc 				if(c == '+')
250*35179Smarc 					r +=  rr;
251*35179Smarc 				else
252*35179Smarc 					r -= rr;
253*35179Smarc 				break;
254*35179Smarc 
255*35179Smarc 			case '*':	case '/':	case '%':
256*35179Smarc 				if(prec > 6)
257*35179Smarc 					goto done;
258*35179Smarc 				rr = arith(7);
259*35179Smarc 				if (c == '*')
260*35179Smarc 					r *= rr;
261*35179Smarc 				else if(rr == 0)
262*35179Smarc 					aerror(ostr,divzero);
263*35179Smarc 				else if (c == '/')
264*35179Smarc 					r /= rr;
265*35179Smarc 				else
266*35179Smarc 					r %= rr;
267*35179Smarc 				break;
268*35179Smarc 
269*35179Smarc 			case ' ':	case '\n':	case '\t':
270*35179Smarc 				break;
271*35179Smarc 
272*35179Smarc 			case '#':
273*35179Smarc 				lastbase = base = r;
274*35179Smarc 				r = 0;
275*35179Smarc 				break;
276*35179Smarc 
277*35179Smarc 			case '.':
278*35179Smarc 				if(dot++==0)
279*35179Smarc 					continue;
280*35179Smarc 
281*35179Smarc 			default:
282*35179Smarc 			{
283*35179Smarc 				register int d;
284*35179Smarc 				for(d=0; hdigits[d] && c != hdigits[d];d++);
285*35179Smarc 				d >>= 1;
286*35179Smarc 				if( d < base )
287*35179Smarc 				{
288*35179Smarc 					if(dot==0)
289*35179Smarc 						r = base*r + d;
290*35179Smarc 				}
291*35179Smarc 				else
292*35179Smarc 					aerror(ostr,badnum);
293*35179Smarc 			}
294*35179Smarc 		}
295*35179Smarc 	}
296*35179Smarc done:
297*35179Smarc 	ungetc();
298*35179Smarc 	return(r);
299*35179Smarc }
300*35179Smarc 
aerror(name,msg)301*35179Smarc static void aerror(name,msg)
302*35179Smarc char *name,*msg;
303*35179Smarc {
304*35179Smarc 	level = 0;
305*35179Smarc 	failed(name,msg);
306*35179Smarc }
307*35179Smarc 
308*35179Smarc /*
309*35179Smarc  * lookup name and return Namnod pointer with this name.
310*35179Smarc  * If none exists, it will be created.
311*35179Smarc  */
312*35179Smarc 
lookup(name)313*35179Smarc struct Namnod *lookup(name)
314*35179Smarc char *name;
315*35179Smarc {
316*35179Smarc 	register struct Namnod *np = NULL;
317*35179Smarc 	register struct Amemory *ap;
318*35179Smarc 	register struct Amemory *app = namep;
319*35179Smarc 	int type = 0;
320*35179Smarc 	while((ap=app) && np==NULL)
321*35179Smarc 	{
322*35179Smarc 		app = app->nexttree;
323*35179Smarc  		np =findnod(name,ap,type|(app==NULL));
324*35179Smarc 		type = RE_USE;
325*35179Smarc 	}
326*35179Smarc 	return(np);
327*35179Smarc }
328*35179Smarc 
329