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