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