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