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