1 /*
2 *
3 * debugger
4 *
5 */
6
7 #include "defs.h"
8 #include "fns.h"
9
10 static long round(long, long);
11
12 extern ADDR ditto;
13 uvlong expv;
14
15 static WORD
ascval(void)16 ascval(void)
17 {
18 Rune r;
19
20 if (readchar() == 0)
21 return (0);
22 r = lastc;
23 while(quotchar()) /*discard chars to ending quote */
24 ;
25 return((WORD) r);
26 }
27
28 /*
29 * read a floating point number
30 * the result must fit in a WORD
31 */
32
33 static WORD
fpin(char * buf)34 fpin(char *buf)
35 {
36 union {
37 WORD w;
38 float f;
39 } x;
40
41 x.f = atof(buf);
42 return (x.w);
43 }
44
45 WORD
defval(WORD w)46 defval(WORD w)
47 {
48 if (expr(0))
49 return (expv);
50 else
51 return (w);
52 }
53
expr(int a)54 expr(int a)
55 { /* term | term dyadic expr | */
56 int rc;
57 WORD lhs;
58
59 rdc();
60 reread();
61 rc=term(a);
62 while (rc) {
63 lhs = expv;
64 switch ((int)readchar()) {
65
66 case '+':
67 term(a|1);
68 expv += lhs;
69 break;
70
71 case '-':
72 term(a|1);
73 expv = lhs - expv;
74 break;
75
76 case '#':
77 term(a|1);
78 expv = round(lhs,expv);
79 break;
80
81 case '*':
82 term(a|1);
83 expv *= lhs;
84 break;
85
86 case '%':
87 term(a|1);
88 if(expv != 0)
89 expv = lhs/expv;
90 else{
91 if(lhs)
92 expv = 1;
93 else
94 expv = 0;
95 }
96 break;
97
98 case '&':
99 term(a|1);
100 expv &= lhs;
101 break;
102
103 case '|':
104 term(a|1);
105 expv |= lhs;
106 break;
107
108 case ')':
109 if ((a&2)==0)
110 error("unexpected `)'");
111
112 default:
113 reread();
114 return(rc);
115 }
116 }
117 return(rc);
118 }
119
term(int a)120 term(int a)
121 { /* item | monadic item | (expr) | */
122 ADDR e;
123
124 switch ((int)readchar()) {
125
126 case '*':
127 term(a|1);
128 if (geta(cormap, expv, &e) < 0)
129 error("%r");
130 expv = e;
131 return(1);
132
133 case '@':
134 term(a|1);
135 if (geta(symmap, expv, &e) < 0)
136 error("%r");
137 expv = e;
138 return(1);
139
140 case '-':
141 term(a|1);
142 expv = -expv;
143 return(1);
144
145 case '~':
146 term(a|1);
147 expv = ~expv;
148 return(1);
149
150 case '(':
151 expr(2);
152 if (readchar()!=')')
153 error("syntax error: `)' expected");
154 return(1);
155
156 default:
157 reread();
158 return(item(a));
159 }
160 }
161
item(int a)162 item(int a)
163 { /* name [ . local ] | number | . | ^ | <register | 'x | | */
164 char *base;
165 char savc;
166 uvlong e;
167 Symbol s;
168 char gsym[MAXSYM], lsym[MAXSYM];
169
170 readchar();
171 if (isfileref()) {
172 readfname(gsym);
173 rdc(); /* skip white space */
174 if (lastc == ':') { /* it better be */
175 rdc(); /* skip white space */
176 if (!getnum(readchar))
177 error("bad number");
178 if (expv == 0)
179 expv = 1; /* file begins at line 1 */
180 expv = file2pc(gsym, expv);
181 if (expv == -1)
182 error("%r");
183 return 1;
184 }
185 error("bad file location");
186 } else if (symchar(0)) {
187 readsym(gsym);
188 if (lastc=='.') {
189 readchar(); /* ugh */
190 if (lastc == '.') {
191 lsym[0] = '.';
192 readchar();
193 readsym(lsym+1);
194 } else if (symchar(0)) {
195 readsym(lsym);
196 } else
197 lsym[0] = 0;
198 if (localaddr(cormap, gsym, lsym, &e, rget) < 0)
199 error("%r");
200 expv = e;
201 }
202 else {
203 if (lookup(0, gsym, &s) == 0)
204 error("symbol not found");
205 expv = s.value;
206 }
207 reread();
208 } else if (getnum(readchar)) {
209 ;
210 } else if (lastc=='.') {
211 readchar();
212 if (!symchar(0) && lastc != '.') {
213 expv = dot;
214 } else {
215 if (findsym(rget(cormap, mach->pc), CTEXT, &s) == 0)
216 error("no current function");
217 if (lastc == '.') {
218 lsym[0] = '.';
219 readchar();
220 readsym(lsym+1);
221 } else
222 readsym(lsym);
223 if (localaddr(cormap, s.name, lsym, &e, rget) < 0)
224 error("%r");
225 expv = e;
226 }
227 reread();
228 } else if (lastc=='"') {
229 expv=ditto;
230 } else if (lastc=='+') {
231 expv=inkdot(dotinc);
232 } else if (lastc=='^') {
233 expv=inkdot(-dotinc);
234 } else if (lastc=='<') {
235 savc=rdc();
236 base = regname(savc);
237 expv = rget(cormap, base);
238 }
239 else if (lastc=='\'')
240 expv = ascval();
241 else if (a)
242 error("address expected");
243 else {
244 reread();
245 return(0);
246 }
247 return(1);
248 }
249
250 #define MAXBASE 16
251
252 /* service routines for expression reading */
getnum(int (* rdf)(void))253 getnum(int (*rdf)(void))
254 {
255 char *cp;
256 int base, d;
257 BOOL fpnum;
258 char num[MAXLIN];
259
260 base = 0;
261 fpnum = FALSE;
262 if (lastc == '#') {
263 base = 16;
264 (*rdf)();
265 }
266 if (convdig(lastc) >= MAXBASE)
267 return (0);
268 if (lastc == '0')
269 switch ((*rdf)()) {
270 case 'x':
271 case 'X':
272 base = 16;
273 (*rdf)();
274 break;
275
276 case 't':
277 case 'T':
278 base = 10;
279 (*rdf)();
280 break;
281
282 case 'o':
283 case 'O':
284 base = 8;
285 (*rdf)();
286 break;
287 default:
288 if (base == 0)
289 base = 8;
290 break;
291 }
292 if (base == 0)
293 base = 10;
294 expv = 0;
295 for (cp = num, *cp = lastc; ;(*rdf)()) {
296 if ((d = convdig(lastc)) < base) {
297 expv *= base;
298 expv += d;
299 *cp++ = lastc;
300 }
301 else if (lastc == '.') {
302 fpnum = TRUE;
303 *cp++ = lastc;
304 } else {
305 reread();
306 break;
307 }
308 }
309 if (fpnum)
310 expv = fpin(num);
311 return (1);
312 }
313
314 void
readsym(char * isymbol)315 readsym(char *isymbol)
316 {
317 char *p;
318 Rune r;
319
320 p = isymbol;
321 do {
322 if (p < &isymbol[MAXSYM-UTFmax-1]){
323 r = lastc;
324 p += runetochar(p, &r);
325 }
326 readchar();
327 } while (symchar(1));
328 *p = 0;
329 }
330
331 void
readfname(char * filename)332 readfname(char *filename)
333 {
334 char *p;
335 Rune c;
336
337 /* snarf chars until un-escaped char in terminal char set */
338 p = filename;
339 do {
340 if ((c = lastc) != '\\' && p < &filename[MAXSYM-UTFmax-1])
341 p += runetochar(p, &c);
342 readchar();
343 } while (c == '\\' || strchr(CMD_VERBS, lastc) == 0);
344 *p = 0;
345 reread();
346 }
347
convdig(int c)348 convdig(int c)
349 {
350 if (isdigit(c))
351 return(c-'0');
352 else if (!isxdigit(c))
353 return(MAXBASE);
354 else if (isupper(c))
355 return(c-'A'+10);
356 else
357 return(c-'a'+10);
358 }
359
symchar(int dig)360 symchar(int dig)
361 {
362 if (lastc=='\\') {
363 readchar();
364 return(TRUE);
365 }
366 return(isalpha(lastc) || lastc>0x80 || lastc=='_' || dig && isdigit(lastc));
367 }
368
369 static long
round(long a,long b)370 round(long a, long b)
371 {
372 long w;
373
374 w = (a/b)*b;
375 if (a!=w)
376 w += b;
377 return(w);
378 }
379