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