xref: /original-bsd/old/adb/adb.tahoe/expr.c (revision e59fb703)
1 #ifndef lint
2 static	char sccsid[] = "@(#)expr.c	1.2 (Berkeley) 07/25/86";
3 #endif
4 /*
5  *
6  *	UNIX debugger
7  *
8  */
9 
10 #include "defs.h"
11 
12 MSG		BADSYM;
13 MSG		BADVAR;
14 MSG		BADKET;
15 MSG		BADSYN;
16 MSG		NOCFN;
17 MSG		NOADR;
18 MSG		BADLOC;
19 
20 ADDR		lastframe;
21 ADDR		savlastf;
22 ADDR		savframe;
23 ADDR		savpc;
24 ADDR		callpc;
25 
26 
27 
28 CHAR		*lp;
29 INT		radix;
30 STRING		errflg;
31 ADDR		localval;
32 CHAR		isymbol[1024];
33 
34 CHAR		lastc,peekc;
35 
36 L_INT		dot;
37 L_INT		ditto;
38 INT		dotinc;
39 L_INT		var[];
40 L_INT		expv;
41 
42 
43 
44 
45 expr(a)
46 {	/* term | term dyadic expr |  */
47 	REG	rc;
48 	REG	L_INT	lhs;
49 
50 	rdc(); lp--; rc=term(a);
51 
52 	WHILE rc
53 	DO  lhs = expv;
54 
55 	    switch ((int)readchar()) {
56 
57 		    case '+':
58 			term(a|1); expv += lhs; break;
59 
60 		    case '-':
61 			term(a|1); expv = lhs - expv; break;
62 
63 		    case '#':
64 			term(a|1); expv = round(lhs,expv); break;
65 
66 		    case '*':
67 			term(a|1); expv *= lhs; break;
68 
69 		    case '%':
70 			term(a|1); expv = lhs/expv; break;
71 
72 		    case '&':
73 			term(a|1); expv &= lhs; break;
74 
75 		    case '|':
76 			term(a|1); expv |= lhs; break;
77 
78 		    case ')':
79 			IF (a&2)==0 THEN error(BADKET); FI
80 
81 		    default:
82 			lp--;
83 			return(rc);
84 	    }
85 	OD
86 	return(rc);
87 }
88 
89 term(a)
90 {	/* item | monadic item | (expr) | */
91 
92 	switch ((int)readchar()) {
93 
94 		    case '*':
95 			term(a|1); expv=chkget(expv,DSP); return(1);
96 
97 		    case '@':
98 			term(a|1); expv=chkget(expv,ISP); return(1);
99 
100 		    case '-':
101 			term(a|1); expv = -expv; return(1);
102 
103 		    case '~':
104 			term(a|1); expv = ~expv; return(1);
105 
106 		    case '#':
107 			term(a|1); expv = !expv; return(1);
108 
109 		    case '(':
110 			expr(2);
111 			IF *lp!=')'
112 			THEN	error(BADSYN);
113 			ELSE	lp++; return(1);
114 			FI
115 
116 		    default:
117 			lp--;
118 			return(item(a));
119 	}
120 }
121 
122 item(a)
123 {	/* name [ . local ] | number | . | ^ | <var | <register | 'x | | */
124 	REG		base, d, regptr;
125 	CHAR		savc;
126 	REG	L_INT		frame;
127 	register struct nlist *symp;
128 
129 	readchar();
130 	IF symchar(0)
131 	THEN	readsym();
132 		IF lastc=='.'
133 		THEN	frame= *(ADDR *)(((ADDR)(&u))+FP); lastframe=0;
134 			callpc= *(ADDR *)(((ADDR)(&u))+PC);
135 			WHILE errflg==0
136 			DO  savpc=callpc;
137 				findsym(callpc,ISYM);
138 			    IF  eqsym(cursym->n_un.n_name,isymbol,'~')
139 			    THEN break;
140 			    FI
141 				callpc=get(frame-8, DSP);
142 			    lastframe=frame;
143 			    frame=get(frame, DSP)&ALIGN;
144 			    IF frame==0
145 			    THEN error(NOCFN);
146 			    FI
147 			OD
148 			savlastf=lastframe; savframe=frame;
149 			readchar();
150 			IF symchar(0)
151 			THEN	chkloc(expv=frame);
152 			FI
153 		ELIF (symp=lookup(isymbol))==0 THEN error(BADSYM);
154 		ELSE expv = symp->n_value;
155 		FI
156 		lp--;
157 
158 
159 	ELIF getnum()
160 	THEN ;
161 	ELIF lastc=='.'
162 	THEN	readchar();
163 		IF symchar(0)
164 		THEN	lastframe=savlastf; callpc=savpc;
165 			chkloc(savframe);
166 		ELSE	expv=dot;
167 		FI
168 		lp--;
169 
170 	ELIF lastc=='"'
171 	THEN	expv=ditto;
172 
173 	ELIF lastc=='+'
174 	THEN	expv=inkdot(dotinc);
175 
176 	ELIF lastc=='^'
177 	THEN	expv=inkdot(-dotinc);
178 
179 	ELIF lastc=='<'
180 	THEN	savc=rdc();
181 		IF (regptr=getreg(savc)) != -1
182 		THEN	IF kcore THEN expv = *(int *)regptr;
183 			ELSE expv= *(ADDR *)(((ADDR)(&u))+regptr); FI
184 		ELIF (base=varchk(savc)) != -1
185 		THEN	expv=var[base];
186 		ELSE	error(BADVAR);
187 		FI
188 
189 	ELIF lastc=='\''
190 	THEN	d=4; expv=0;
191 		WHILE quotchar()
192 		DO  IF d--
193 		    THEN expv <<= 8;
194 			 expv |= lastc;
195 		    ELSE error(BADSYN);
196 		    FI
197 		OD
198 
199 	ELIF a
200 	THEN	error(NOADR);
201 	ELSE lp--; return(0);
202 	FI
203 	return(1);
204 }
205 
206 /* service routines for expression reading */
207 getnum()
208 {
209 	REG base,d,frpt;
210 	UNION{REAL r; L_INT i;} real;
211 	IF (base = radix) < 0 THEN base = -base; FI
212 	IF isdigit(lastc)
213 	THEN	expv = 0;
214 		WHILE (base>10 ? isxdigit(lastc) : isdigit(lastc))
215 		DO
216 		    REG m;
217 		    m = MAXINT/base;
218 		    if(expv>m)
219 			/* avoid overflow */
220 			expv = (expv-m)*base+m*base;
221 		    else
222 			expv *= base;
223 		    IF (d=convdig(lastc))>=base ORF d<0 THEN error(BADSYN); FI
224 		    expv += d; readchar();
225 		    IF expv==0
226 		    THEN IF (lastc=='x' ORF lastc=='X')
227 				 THEN base=16; readchar();
228 				 ELIF (lastc=='t' ORF lastc=='T')
229 			     THEN base=10; readchar();
230 		    	 ELIF (lastc=='o' ORF lastc=='O')
231 		    	 THEN base=8; readchar();
232 				 FI
233 		    FI
234 		OD
235 		IF lastc=='.' ANDF (base==10 ORF expv==0)
236 		THEN	real.r=expv; frpt=0; base=10;
237 			WHILE isdigit(readchar())
238 			DO	real.r *= base; frpt++;
239 				real.r += lastc-'0';
240 			OD
241 			WHILE frpt--
242 			DO	real.r /= base; OD
243 			expv = real.i;
244 		FI
245 		peekc=lastc;
246 		return(1);
247 	ELSE return(0);
248 	FI
249 }
250 
251 readsym()
252 {
253 	REG char	*p;
254 
255 	p = isymbol;
256 	REP IF p < &isymbol[sizeof(isymbol)-1]
257 	    THEN *p++ = lastc;
258 	    FI
259 	    readchar();
260 	PER symchar(1) DONE
261 	*p++ = 0;
262 }
263 
264 convdig(c)
265 CHAR c;
266 {
267 	IF isdigit(c)
268 	THEN	return(c-'0');
269 	ELIF isxdigit(c)
270 	THEN	return(c-'a'+10);
271 	ELSE return(-1);
272 	FI
273 }
274 
275 symchar(dig)
276 {
277 	IF lastc=='\\' THEN readchar(); return(TRUE); FI
278 	return ( isalpha(lastc) ORF lastc=='_' ORF dig ANDF isdigit(lastc) );
279 }
280 
281 varchk(name)
282 REG name;
283 {
284 	IF isdigit(name) THEN return(name-'0'); FI
285 	IF isalpha(name) THEN return((name&037)-1+10); FI
286 	return(-1);
287 }
288 
289 chkloc(frame)
290 L_INT		frame;
291 {
292 	readsym();
293 	REP IF localsym(frame)==0 THEN error(BADLOC); FI
294 	    expv=localval;
295 	PER !eqsym(cursym->n_un.n_name,isymbol,'~') DONE
296 }
297 
298 eqsym(s1, s2, c)
299 	register char *s1, *s2;
300 {
301 
302 	if (!strcmp(s1,s2))
303 		return (1);
304 	if (*s1 == c && !strcmp(s1+1, s2))
305 		return (1);
306 	return (0);
307 }
308