|
|
1.1 ! root 1: /* ! 2: Hatari - calculate.c ! 3: ! 4: Copyright (C) 1994, 2009 by Eero Tamminen ! 5: ! 6: This file is distributed under the GNU Public License, version 2 or at ! 7: your option any later version. Read the file gpl.txt for details. ! 8: ! 9: calculate.c - parse numbers, number ranges and expressions. Supports ! 10: most unary and binary operations, parenthesis and order of precedence. ! 11: Originally based on code from my Clac calculator MiNT filter version. ! 12: */ ! 13: const char Eval_fileid[] = "Hatari calculate.c : " __DATE__ " " __TIME__; ! 14: ! 15: #include <ctype.h> ! 16: #include <limits.h> ! 17: #include <errno.h> ! 18: #include <stdio.h> ! 19: #include <stdlib.h> ! 20: #include <stdbool.h> ! 21: #include <SDL_types.h> ! 22: #include "configuration.h" ! 23: #include "debugcpu.h" ! 24: #include "evaluate.h" ! 25: #include "main.h" ! 26: #include "m68000.h" ! 27: #include "symbols.h" ! 28: ! 29: /* define which character indicates which type of number on expression */ ! 30: #define PREFIX_BIN '%' /* binary decimal */ ! 31: #define PREFIX_DEC '#' /* normal decimal */ ! 32: #define PREFIX_HEX '$' /* hexadecimal */ ! 33: ! 34: /* define error codes */ ! 35: #define CLAC_EXP_ERR "No expression given" ! 36: #define CLAC_GEN_ERR "Syntax error" ! 37: #define CLAC_PAR_ERR "Mismatched parenthesis" ! 38: #define CLAC_DEF_ERR "Undefined result (1/0)" ! 39: #define CLAC_STK_ERR "Operation/value stack full" ! 40: #define CLAC_OVF_ERR "Overflow" ! 41: #define CLAC_OVR_ERR "Mode overflow" ! 42: #define CLAC_PRG_ERR "Internal program error" ! 43: ! 44: /* define internal allocation sizes (should be enough ;-) */ ! 45: #define PARDEPTH_MAX 64 /* max. parenth. nesting depth */ ! 46: #define OSTACK_MAX 128 /* size of the operator stack */ ! 47: #define VSTACK_MAX 128 /* size of the value stack */ ! 48: ! 49: /* operation with lowest precedence, used to finish calculations */ ! 50: #define LOWEST_PREDECENCE '|' ! 51: ! 52: /* globals + function identifier stack(s) */ ! 53: static struct { ! 54: const char *error; /* global error code */ ! 55: bool valid; /* value validation */ ! 56: } id = {0, 0}; ! 57: ! 58: /* parenthesis and function stacks */ ! 59: static struct { ! 60: int idx; /* parenthesis level */ ! 61: int max; /* maximum idx */ ! 62: int opx[PARDEPTH_MAX + 1]; /* current op index for par */ ! 63: int vax[PARDEPTH_MAX + 1]; /* current val index for par */ ! 64: } par = {0, PARDEPTH_MAX, {0}, {0}}; ! 65: ! 66: static struct { /* operator stack */ ! 67: int idx; ! 68: int max; ! 69: char buf[OSTACK_MAX + 1]; ! 70: } op = {0, OSTACK_MAX, ""}; ! 71: ! 72: static struct value_stk { /* value stack */ ! 73: int idx; ! 74: int max; ! 75: long long buf[VSTACK_MAX + 1]; ! 76: } val = {0, VSTACK_MAX, {0}}; ! 77: ! 78: /* -------------------------------------------------------------------- */ ! 79: /* macros */ ! 80: ! 81: /* increment stack index and put value on stack (ie. PUSH) */ ! 82: #define PUSH(stk,val) \ ! 83: if((stk).idx < (stk).max) { \ ! 84: (stk).idx += 1; \ ! 85: (stk).buf[(stk).idx] = (val); \ ! 86: } else { \ ! 87: id.error = CLAC_STK_ERR; \ ! 88: } ! 89: ! 90: /* -------------------------------------------------------------------- */ ! 91: /* declare subfunctions */ ! 92: ! 93: /* parse in-between operations */ ! 94: static void operation(long long value, char op); ! 95: /* parse unary operators */ ! 96: static void unary (char op); ! 97: /* apply a prefix to a value */ ! 98: static void apply_prefix(void); ! 99: /* juggle stacks, if possible */ ! 100: static void eval_stack(void); ! 101: /* operator -> operator level */ ! 102: static int get_level(int stk_offset); ! 103: /* evaluate operation */ ! 104: static long long apply_op(char op, long long x, long long y); ! 105: ! 106: /* increase parenthesis level */ ! 107: static void open_bracket(void); ! 108: /* decrease parenthesis level */ ! 109: static long long close_bracket(long long x); ! 110: ! 111: ! 112: /** ! 113: * Parse & set an (unsigned) number, assuming it's in the configured ! 114: * default number base unless it has a prefix: ! 115: * - '$' / '0x' / '0h' => hexadecimal ! 116: * - '#' / '0d' => normal decimal ! 117: * - '%' / '0b' => binary decimal ! 118: * - '0o' => octal decimal ! 119: * Return how many characters were parsed or zero for error. ! 120: */ ! 121: static int getNumber(const char *str, Uint32 *number, int *nbase) ! 122: { ! 123: char *end; ! 124: const char const *start = str; ! 125: int base = ConfigureParams.Debugger.nNumberBase; ! 126: unsigned long int value; ! 127: ! 128: if (!str[0]) { ! 129: fprintf(stderr, "Value missing!\n"); ! 130: return 0; ! 131: } ! 132: ! 133: /* determine correct number base */ ! 134: if (str[0] == '0') { ! 135: ! 136: /* 0x & 0h = hex, 0d = dec, 0o = oct, 0b = bin ? */ ! 137: switch(str[1]) { ! 138: case 'b': ! 139: base = 2; ! 140: break; ! 141: case 'o': ! 142: base = 8; ! 143: break; ! 144: case 'd': ! 145: base = 10; ! 146: break; ! 147: case 'h': ! 148: case 'x': ! 149: base = 16; ! 150: break; ! 151: default: ! 152: str -= 2; ! 153: } ! 154: str += 2; ! 155: } ! 156: else if (!isxdigit(str[0])) { ! 157: ! 158: /* doesn't start with (hex) number -> is it prefix? */ ! 159: switch (*str++) { ! 160: case PREFIX_BIN: ! 161: base = 2; ! 162: break; ! 163: case PREFIX_DEC: ! 164: base = 10; ! 165: break; ! 166: case PREFIX_HEX: ! 167: base = 16; ! 168: break; ! 169: default: ! 170: fprintf(stderr, "Unrecognized number prefix in '%s'!\n", start); ! 171: return 0; ! 172: } ! 173: } ! 174: *nbase = base; ! 175: ! 176: /* parse number */ ! 177: errno = 0; ! 178: value = strtoul(str, &end, base); ! 179: if (errno == ERANGE && value == LONG_MAX) { ! 180: fprintf(stderr, "Overflow with value '%s'!\n", start); ! 181: return 0; ! 182: } ! 183: if ((errno != 0 && value == 0) || end == str) { ! 184: fprintf(stderr, "Invalid value '%s'!\n", start); ! 185: return 0; ! 186: } ! 187: *number = value; ! 188: return end - start; ! 189: } ! 190: ! 191: ! 192: /** ! 193: * Parse unsigned register/symbol/number value and set it to "number". ! 194: * Return how many characters were parsed or zero for error. ! 195: */ ! 196: static int getValue(const char *str, Uint32 *number, bool bForDsp) ! 197: { ! 198: char name[64]; ! 199: const char *end; ! 200: Uint32 mask, *addr; ! 201: int len, dummy; ! 202: ! 203: for (end = str; *end == '_' || isalnum(*end); end++); ! 204: ! 205: len = end-str; ! 206: if (len >= (int)sizeof(name)) { ! 207: fprintf(stderr, "ERROR: symbol name at '%s' too long (%d chars)\n", str, len); ! 208: return 0; ! 209: } ! 210: memcpy(name, str, len); ! 211: name[len] = '\0'; ! 212: ! 213: if (bForDsp) { ! 214: if (Symbols_GetDspAddress(SYMTYPE_ALL, name, number)) { ! 215: return len; ! 216: } ! 217: } else { ! 218: /* a special case CPU register? */ ! 219: if (strcasecmp(name, "PC") == 0) { ! 220: *number = M68000_GetPC(); ! 221: return len; ! 222: } ! 223: if (strcasecmp(name, "SR") == 0) { ! 224: *number = M68000_GetSR(); ! 225: return len; ! 226: } ! 227: /* a normal CPU register or symbol? */ ! 228: if (DebugCpu_GetRegisterAddress(name, &addr)) { ! 229: *number = *addr; ! 230: return len; ! 231: } ! 232: if (Symbols_GetCpuAddress(SYMTYPE_ALL, name, number)) { ! 233: return len; ! 234: } ! 235: } ! 236: ! 237: /* none of above, assume it's a number */ ! 238: return getNumber(str, number, &dummy); ! 239: } ! 240: ! 241: ! 242: /** ! 243: * Parse & set an (unsigned) number, assume it's in the configured ! 244: * default number base unless it has a suitable prefix. ! 245: * Return true for success and false for failure. ! 246: */ ! 247: bool Eval_Number(const char *str, Uint32 *number) ! 248: { ! 249: int offset, base = 0; ! 250: ! 251: offset = getNumber(str, number, &base); ! 252: if (!offset) { ! 253: return false; ! 254: } ! 255: if (str[offset]) { ! 256: const char *basestr; ! 257: ! 258: switch (base) { ! 259: case 2: ! 260: basestr = "binary"; ! 261: break; ! 262: case 8: ! 263: basestr = "octal"; ! 264: break; ! 265: case 10: ! 266: basestr = "decimal"; ! 267: break; ! 268: case 16: ! 269: basestr = "hexadecimal"; ! 270: break; ! 271: default: ! 272: basestr = "unknown"; ! 273: } ! 274: fprintf(stderr, "Extra characters in %s based number '%s'!\n", ! 275: basestr, str); ! 276: return false; ! 277: } ! 278: return true; ! 279: } ! 280: ! 281: ! 282: /** ! 283: * Get a an adress range, eg. "$fa0000-$fa0100" ! 284: * returns: ! 285: * 0 if OK, ! 286: * -1 if not syntaxically a range, ! 287: * -2 if values are invalid, ! 288: * -3 if syntaxically range, but not value-wise. ! 289: */ ! 290: static int getRange(char *str1, Uint32 *lower, Uint32 *upper) ! 291: { ! 292: bool fDash = false; ! 293: char *str2 = str1; ! 294: int ret = 0; ! 295: ! 296: while (*str2) { ! 297: if (*str2 == '-') { ! 298: *str2++ = '\0'; ! 299: fDash = true; ! 300: break; ! 301: } ! 302: str2++; ! 303: } ! 304: if (!fDash) ! 305: return -1; ! 306: ! 307: if (!Eval_Number(str1, lower)) ! 308: ret = -2; ! 309: else if (!Eval_Number(str2, upper)) ! 310: ret = -2; ! 311: else if (*lower > *upper) ! 312: ret = -3; ! 313: *--str2 = '-'; ! 314: return ret; ! 315: } ! 316: ! 317: ! 318: /** ! 319: * Parse an adress range, eg. "$fa0000[-$fa0100]" + show appropriate warnings ! 320: * returns: ! 321: * -1 if invalid address or range, ! 322: * 0 if single address, ! 323: * +1 if a range. ! 324: */ ! 325: int Eval_Range(char *str, Uint32 *lower, Uint32 *upper) ! 326: { ! 327: switch (getRange(str, lower, upper)) { ! 328: case 0: ! 329: return 1; ! 330: case -1: ! 331: /* single address, not a range */ ! 332: if (!Eval_Number(str, lower)) ! 333: return -1; ! 334: return 0; ! 335: case -2: ! 336: fprintf(stderr,"Invalid address values in '%s'!\n", str); ! 337: return -1; ! 338: case -3: ! 339: fprintf(stderr,"Invalid range ($%x > $%x)!\n", *lower, *upper); ! 340: return -1; ! 341: } ! 342: fprintf(stderr, "INTERNAL ERROR: Unknown getRange() return value.\n"); ! 343: return -1; ! 344: } ! 345: ! 346: ! 347: /** ! 348: * Evaluate expression. bForDsp determines which registers and symbols ! 349: * are interpreted. Sets given value and parsing offset. ! 350: * Return error string or NULL for success. ! 351: */ ! 352: const char* Eval_Expression(const char *in, Uint32 *out, int *erroff, bool bForDsp) ! 353: { ! 354: /* in : expression to evaluate */ ! 355: /* out : final parsed value */ ! 356: /* value : current parsed value */ ! 357: /* mark : current character in expression */ ! 358: /* valid : expression validation flag, set when number parsed */ ! 359: /* end : 'expression end' flag */ ! 360: /* offset: character offset in expression */ ! 361: ! 362: long long value; ! 363: int offset = 0; ! 364: char mark; ! 365: ! 366: /* Uses global variables: */ ! 367: ! 368: par.idx = 0; /* parenthesis stack pointer */ ! 369: par.opx[0] = par.vax[0] = 0; /* additional stack pointers */ ! 370: op.idx = val.idx = -1; ! 371: ! 372: id.error = NULL; ! 373: id.valid = false; /* value validation */ ! 374: value = 0; ! 375: ! 376: /* parsing loop, repeated until expression ends */ ! 377: do { ! 378: mark = in[offset]; ! 379: switch(mark) { ! 380: case '\0': ! 381: break; ! 382: case ' ': ! 383: case '\t': ! 384: offset ++; /* jump over white space */ ! 385: break; ! 386: case '~': /* prefixes */ ! 387: unary(mark); ! 388: offset ++; ! 389: break; ! 390: case '>': /* operators */ ! 391: case '<': ! 392: offset ++; ! 393: /* check that it's '>>' or '<<' */ ! 394: if (in[offset] != mark) ! 395: { ! 396: id.error = CLAC_GEN_ERR; ! 397: break; ! 398: } ! 399: operation (value, mark); ! 400: offset ++; ! 401: break; ! 402: case '|': ! 403: case '&': ! 404: case '^': ! 405: case '+': ! 406: case '-': ! 407: case '*': ! 408: case '/': ! 409: operation (value, mark); ! 410: offset ++; ! 411: break; ! 412: case '(': ! 413: open_bracket (); ! 414: offset ++; ! 415: break; ! 416: case ')': ! 417: value = close_bracket (value); ! 418: offset ++; ! 419: break; ! 420: default: ! 421: /* register/symbol/number value needed? */ ! 422: if (id.valid == false) { ! 423: Uint32 tmp; ! 424: int consumed; ! 425: consumed = getValue(&(in[offset]), &tmp, bForDsp); ! 426: /* number parsed? */ ! 427: if (consumed) { ! 428: offset += consumed; ! 429: id.valid = true; ! 430: value = tmp; ! 431: break; ! 432: } ! 433: } ! 434: id.error = CLAC_GEN_ERR; ! 435: } ! 436: ! 437: /* until exit or error message */ ! 438: } while(mark && !id.error); ! 439: ! 440: /* result of evaluation */ ! 441: if (val.idx >= 0) ! 442: *out = val.buf[val.idx]; ! 443: ! 444: /* something to return? */ ! 445: if (!id.error) { ! 446: if (id.valid) { ! 447: ! 448: /* evaluate rest of the expression */ ! 449: operation (value, LOWEST_PREDECENCE); ! 450: if (par.idx) /* mismatched */ ! 451: id.error = CLAC_PAR_ERR; ! 452: else /* result out */ ! 453: *out = val.buf[val.idx]; ! 454: ! 455: } else { ! 456: if ((val.idx < 0) && (op.idx < 0)) { ! 457: id.error = CLAC_EXP_ERR; ! 458: } else /* trailing operators */ ! 459: id.error = CLAC_GEN_ERR; ! 460: } ! 461: } ! 462: ! 463: *erroff = offset; ! 464: if (id.error) { ! 465: *out = 0; ! 466: return id.error; ! 467: } ! 468: return NULL; ! 469: } ! 470: ! 471: ! 472: /* ==================================================================== */ ! 473: /* expression evaluation */ ! 474: /* ==================================================================== */ ! 475: ! 476: static void operation (long long value, char oper) ! 477: { ! 478: /* uses globals par[], id.error[], op[], val[] ! 479: * operation executed if the next one is on same or lower level ! 480: */ ! 481: /* something to calc? */ ! 482: if(id.valid == true) { ! 483: ! 484: /* add new items to stack */ ! 485: PUSH(op, oper); ! 486: PUSH(val, value); ! 487: ! 488: /* more than 1 operator */ ! 489: if(op.idx > par.opx[par.idx]) { ! 490: ! 491: /* but only one value */ ! 492: if(val.idx == par.vax[par.idx]) { ! 493: apply_prefix(); ! 494: } else { ! 495: /* evaluate all possible operations */ ! 496: eval_stack(); ! 497: } ! 498: } ! 499: /* next a number needed */ ! 500: id.valid = false; ! 501: } else { ! 502: /* pre- or post-operators instead of in-betweens? */ ! 503: unary(oper); ! 504: } ! 505: } ! 506: ! 507: /** ! 508: * handle unary operators ! 509: */ ! 510: static void unary (char oper) ! 511: { ! 512: /* check pre-value operators ! 513: * have to be parenthesised ! 514: */ ! 515: if(id.valid == false && op.idx < par.opx[par.idx]) ! 516: { ! 517: switch(oper) { ! 518: case '+': /* not needed */ ! 519: break; ! 520: case '-': ! 521: case '~': ! 522: PUSH(op, oper); ! 523: break; ! 524: default: ! 525: id.error = CLAC_GEN_ERR; ! 526: } ! 527: } ! 528: else ! 529: id.error = CLAC_GEN_ERR; ! 530: } ! 531: ! 532: /** ! 533: * apply a prefix to the current value ! 534: */ ! 535: static void apply_prefix(void) ! 536: { ! 537: long long value = val.buf[val.idx]; ! 538: ! 539: op.idx--; ! 540: switch(op.buf[op.idx]) { ! 541: case '-': ! 542: value = (-value); ! 543: break; ! 544: case '~': ! 545: value = (~value); ! 546: break; ! 547: default: ! 548: id.error = CLAC_PRG_ERR; ! 549: } ! 550: val.buf[val.idx] = value; ! 551: op.buf[op.idx] = op.buf[op.idx + 1]; ! 552: } ! 553: ! 554: /* -------------------------------------------------------------------- */ ! 555: /** ! 556: * evaluate operators if precedence allows it ! 557: */ ! 558: /* evaluate all possible (according to order of precedence) operators */ ! 559: static void eval_stack (void) ! 560: { ! 561: /* uses globals par[], op[], val[] */ ! 562: ! 563: /* # of operators >= 2 and prev. op-level >= current op-level ? */ ! 564: while ((op.idx > par.opx[par.idx]) && get_level (-1) >= get_level (0)) { ! 565: ! 566: /* shorten value stacks by one */ ! 567: /* + calculate resulting value */ ! 568: op.idx -= 1; ! 569: val.idx -= 1; ! 570: val.buf[val.idx] = apply_op(op.buf[op.idx], ! 571: val.buf[val.idx], val.buf[val.idx + 1]); ! 572: ! 573: /* pull the just used operator out of the stack */ ! 574: op.buf[op.idx] = op.buf[op.idx + 1]; ! 575: } ! 576: } ! 577: ! 578: /* -------------------------------------------------------------------- */ ! 579: /** ! 580: * return the precedence level of a given operator ! 581: */ ! 582: static int get_level (int offset) ! 583: { ! 584: /* used globals par[], op[] ! 585: * returns operator level of: operator[stack idx + offset] ! 586: */ ! 587: switch(op.buf[op.idx + offset]) { ! 588: case '|': /* binary operations */ ! 589: case '&': ! 590: case '^': ! 591: return 0; ! 592: ! 593: case '>': /* bit shifting */ ! 594: case '<': ! 595: return 1; ! 596: ! 597: case '+': ! 598: case '-': ! 599: return 2; ! 600: ! 601: case '*': ! 602: case '/': ! 603: return 3; ! 604: ! 605: default: ! 606: id.error = CLAC_PRG_ERR; ! 607: } ! 608: return 6; ! 609: } ! 610: ! 611: /* -------------------------------------------------------------------- */ ! 612: /** ! 613: * apply operator to given values, return the result ! 614: */ ! 615: static long long apply_op (char opcode, long long value1, long long value2) ! 616: { ! 617: /* uses global id.error[] */ ! 618: /* returns the result of operation */ ! 619: ! 620: switch (opcode) { ! 621: case '|': ! 622: value1 |= value2; ! 623: break; ! 624: case '&': ! 625: value1 &= value2; ! 626: break; ! 627: case '^': ! 628: value1 ^= value2; ! 629: break; ! 630: case '>': ! 631: value1 >>= value2; ! 632: case '<': ! 633: value1 <<= value2; ! 634: break; ! 635: case '+': ! 636: value1 += value2; ! 637: break; ! 638: case '-': ! 639: value1 -= value2; ! 640: break; ! 641: case '*': ! 642: value1 *= value2; ! 643: break; ! 644: case '/': ! 645: /* don't divide by zero */ ! 646: if (value2) ! 647: value1 /= value2; ! 648: else ! 649: id.error = CLAC_DEF_ERR; ! 650: break; ! 651: default: ! 652: id.error = CLAC_PRG_ERR; ! 653: } ! 654: return value1; /* return result */ ! 655: } ! 656: ! 657: ! 658: /* ==================================================================== */ ! 659: /* parenthesis and help */ ! 660: /* ==================================================================== */ ! 661: ! 662: /** ! 663: * open prenthesis, push values & operators to stack ! 664: */ ! 665: static void open_bracket (void) ! 666: { ! 667: if (id.valid == false) { /* preceded by operator */ ! 668: if (par.idx < PARDEPTH_MAX) { /* not nested too deep */ ! 669: par.idx ++; ! 670: par.opx[par.idx] = op.idx + 1; ! 671: par.vax[par.idx] = val.idx + 1; ! 672: } else ! 673: id.error = CLAC_STK_ERR; ! 674: } else ! 675: id.error = CLAC_GEN_ERR; ! 676: } ! 677: ! 678: /* -------------------------------------------------------------------- */ ! 679: /** ! 680: * close prenthesis, and evaluate / pop stacks ! 681: */ ! 682: /* last parsed value, last param. flag, trigonometric mode */ ! 683: static long long close_bracket (long long value) ! 684: { ! 685: /* returns the value of the parenthesised expression */ ! 686: ! 687: if (id.valid) { /* preceded by an operator */ ! 688: if (par.idx > 0) { /* prenthesis has a pair */ ! 689: /* calculate the value of parenthesised exp. */ ! 690: operation (value, LOWEST_PREDECENCE); ! 691: value = val.buf[val.idx]; ! 692: op.idx = par.opx[par.idx] - 1; /* restore prev */ ! 693: val.idx = par.vax[par.idx] - 1; ! 694: par.idx --; ! 695: ! 696: /* next operator */ ! 697: id.valid = true; ! 698: } else ! 699: id.error = CLAC_PAR_ERR; ! 700: } else ! 701: id.error = CLAC_GEN_ERR; ! 702: ! 703: return value; ! 704: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.