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 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 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 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 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 */ 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 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 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 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 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 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