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