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