1 /*
2 * Copyright (c) 1986 Regents of the University of California.
3 * All rights reserved. The Berkeley software License Agreement
4 * specifies the terms and conditions for redistribution.
5 *
6 * @(#)kdb_expr.c 7.6 (Berkeley) 05/03/90
7 */
8
9 #include "../kdb/defs.h"
10
11 char *kdbBADSYM;
12 char *kdbBADVAR;
13 char *kdbBADKET;
14 char *kdbBADSYN;
15 char *kdbNOCFN;
16 char *kdbNOADR;
17 char *kdbBADLOC;
18
19 ADDR kdblastframe;
20 ADDR kdbsavlastf;
21 ADDR kdbsavframe;
22 ADDR kdbsavpc;
23 ADDR kdbcallpc;
24
25 char *kdblp;
26 int kdbradix;
27 char kdbisymbol[1024];
28
29 char kdblastc, kdbpeekc;
30
31 long kdbditto;
32 long kdbexpv;
33
34 static long
kdbround(a,b)35 kdbround(a,b)
36 register long a, b;
37 {
38 register long w;
39
40 w = (a/b)*b;
41 if (a!=w)
42 w += b;
43 return (w);
44 }
45
46 /* term | term dyadic expr | */
kdbexpr(a)47 kdbexpr(a)
48 {
49 register rc;
50 register long lhs;
51
52 (void) kdbrdc(); kdblp--; rc=kdbterm(a);
53
54 while (rc) {
55 lhs = kdbexpv;
56 switch ((int)kdbreadchar()) {
57 case '+':
58 (void) kdbterm(a|1); kdbexpv += lhs; break;
59 case '-':
60 (void) kdbterm(a|1); kdbexpv = lhs - kdbexpv; break;
61 case '#':
62 (void) kdbterm(a|1); kdbexpv = kdbround(lhs,kdbexpv); break;
63 case '*':
64 (void) kdbterm(a|1); kdbexpv *= lhs; break;
65 case '%':
66 (void) kdbterm(a|1); kdbexpv = lhs/kdbexpv; break;
67 case '&':
68 (void) kdbterm(a|1); kdbexpv &= lhs; break;
69 case '|':
70 (void) kdbterm(a|1); kdbexpv |= lhs; break;
71 case ')':
72 if ((a&2)==0)
73 kdberror(kdbBADKET);
74 default:
75 kdblp--;
76 return (rc);
77 }
78 }
79 return (rc);
80 }
81
82 /* item | monadic item | (expr) | */
83 static
kdbterm(a)84 kdbterm(a)
85 {
86
87 switch ((int)kdbreadchar()) {
88 case '*':
89 (void) kdbterm(a|1); kdbexpv=kdbchkget(kdbexpv,DSP);
90 return(1);
91 case '@':
92 (void) kdbterm(a|1); kdbexpv=kdbchkget(kdbexpv,ISP);
93 return(1);
94 case '-':
95 (void) kdbterm(a|1); kdbexpv = -kdbexpv;
96 return(1);
97 case '~':
98 (void) kdbterm(a|1); kdbexpv = ~kdbexpv;
99 return(1);
100 case '#':
101 (void) kdbterm(a|1); kdbexpv = !kdbexpv;
102 return(1);
103 case '(':
104 (void) kdbexpr(2);
105 if (*kdblp!=')')
106 kdberror(kdbBADSYN);
107 kdblp++;
108 return(1);
109 }
110 kdblp--;
111 return (kdbitem(a));
112 }
113
114 /* name [ . local ] | number | . | ^ | <var | <register | 'x | | */
115 static
kdbitem(a)116 kdbitem(a)
117 {
118 register base, d, regptr;
119 char savc;
120 register long frame;
121 register struct nlist *symp;
122
123 (void) kdbreadchar();
124 if (kdbsymchar(0)) {
125 kdbreadsym();
126 if (kdblastc=='.') {
127 frame = kdbpcb.pcb_fp; kdblastframe = 0;
128 kdbcallpc = kdbpcb.pcb_pc;
129 while (!kdberrflg) {
130 kdbsavpc = kdbcallpc;
131 (void) kdbfindsym((long)kdbcallpc,ISYM);
132 if (kdbeqsym(kdbcursym->n_un.n_name,kdbisymbol,'~'))
133 break;
134 kdbcallpc = getprevpc(frame);
135 kdblastframe = frame;
136 frame = getprevframe(frame);
137 if (frame == NOFRAME)
138 kdberror(kdbNOCFN);
139 }
140 kdbsavlastf = kdblastframe; kdbsavframe = frame;
141 (void) kdbreadchar();
142 if (kdbsymchar(0))
143 kdbchkloc(kdbexpv=frame);
144 } else if ((symp=kdblookup(kdbisymbol))==0)
145 kdberror(kdbBADSYM);
146 else
147 kdbexpv = symp->n_value;
148 kdblp--;
149 return (1);
150 }
151 if (kdbgetnum())
152 return (1);
153 switch (kdblastc) {
154 case '.':
155 (void) kdbreadchar();
156 if (kdbsymchar(0)) {
157 kdblastframe=kdbsavlastf; kdbcallpc=kdbsavpc;
158 kdbchkloc((long)kdbsavframe);
159 } else
160 kdbexpv=kdbdot;
161 kdblp--;
162 break;
163 case '"':
164 kdbexpv=kdbditto;
165 break;
166 case '+':
167 kdbexpv=kdbinkdot(kdbdotinc);
168 break;
169 case '^':
170 kdbexpv=kdbinkdot(-kdbdotinc);
171 break;
172 case '<':
173 savc=kdbrdc();
174 if ((regptr=kdbgetreg(savc)) != -1)
175 kdbexpv = *(int *)regptr;
176 else if ((base=kdbvarchk(savc)) != -1)
177 kdbexpv=kdbvar[base];
178 else
179 kdberror(kdbBADVAR);
180 break;
181 case '\'':
182 d=4; kdbexpv=0;
183 while (kdbquotchar()) {
184 if (d--) {
185 kdbexpv <<= 8;
186 kdbexpv |= kdblastc;
187 } else
188 kdberror(kdbBADSYN);
189 }
190 break;
191 default:
192 if (a)
193 kdberror(kdbNOADR);
194 kdblp--;
195 return(0);
196 }
197 return (1);
198 }
199
200 /* service routines for expression reading */
201 static
kdbgetnum()202 kdbgetnum()
203 {
204 register base,d,frpt;
205
206 if (!isdigit(kdblastc))
207 return (0);
208 if ((base = kdbradix) < 0)
209 base = -base;
210 kdbexpv = 0;
211 while (base>10 ? isxdigit(kdblastc) : isdigit(kdblastc)) {
212 register m = MAXINT/base;
213
214 if (kdbexpv>m) /* avoid overflow */
215 kdbexpv = (kdbexpv-m)*base+m*base;
216 else
217 kdbexpv *= base;
218 if ((d=kdbconvdig(kdblastc))>=base || d<0)
219 kdberror(kdbBADSYN);
220 kdbexpv += d; (void) kdbreadchar();
221 if (kdbexpv==0) {
222 if (kdblastc=='x' || kdblastc=='X') {
223 base=16; (void) kdbreadchar();
224 } else if (kdblastc=='t' || kdblastc=='T') {
225 base=10; (void) kdbreadchar();
226 } else if (kdblastc=='o' || kdblastc=='O') {
227 base=8; (void) kdbreadchar();
228 }
229 }
230 }
231 if (kdblastc=='.' && (base==10 || kdbexpv==0)) {
232 frpt=0; base=10;
233 while (isdigit(kdbreadchar())) {
234 if (frpt)
235 continue;
236 frpt++;
237 if (kdblastc - '0' >= 5)
238 kdbexpv++;
239 }
240 }
241 kdbpeekc=kdblastc;
242 return (1);
243 }
244
245 static
kdbreadsym()246 kdbreadsym()
247 {
248 register char *p;
249
250 p = kdbisymbol;
251 do {
252 if (p < &kdbisymbol[sizeof(kdbisymbol)-1])
253 *p++ = kdblastc;
254 (void) kdbreadchar();
255 } while (kdbsymchar(1));
256 *p++ = 0;
257 }
258
259 static
kdbconvdig(c)260 kdbconvdig(c)
261 char c;
262 {
263 if (isdigit(c))
264 return (c-'0');
265 if (isxdigit(c))
266 return (c-'a'+10);
267 return (-1);
268 }
269
270 static
kdbsymchar(dig)271 kdbsymchar(dig)
272 {
273
274 if (kdblastc=='\\') {
275 (void) kdbreadchar();
276 return (1);
277 }
278 return (isalpha(kdblastc) || kdblastc=='_' || dig && isdigit(kdblastc));
279 }
280
kdbvarchk(name)281 kdbvarchk(name)
282 register name;
283 {
284 if (isdigit(name))
285 return (name-'0');
286 if (isalpha(name))
287 return ((name&037)-1+10);
288 return (-1);
289 }
290
291 static
kdbchkloc(frame)292 kdbchkloc(frame)
293 long frame;
294 {
295
296 kdbreadsym();
297 do {
298 if (kdblocalsym(frame)==0)
299 kdberror(kdbBADLOC);
300 kdbexpv=kdblocalval;
301 } while (!kdbeqsym(kdbcursym->n_un.n_name,kdbisymbol,'~'));
302 }
303
kdbeqsym(s1,s2,c)304 kdbeqsym(s1, s2, c)
305 register char *s1, *s2;
306 {
307
308 if (kdbstreq(s1,s2))
309 return (1);
310 if (*s1 == c && kdbstreq(s1+1, s2))
311 return (1);
312 return (0);
313 }
314
315 static
kdbstreq(s1,s2)316 kdbstreq(s1, s2)
317 char *s1, *s2;
318 {
319
320 while (*s1 == *s2++)
321 if (*s1++ == '\0')
322 return (1);
323 return (0);
324 }
325