|
|
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:
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.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;
1.1.1.3 ! root 129: const char *start = str;
1.1 root 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) {
1.1.1.3 ! root 227: int regsize = DSP_GetRegisterAddress(name, &addr, &mask);
1.1 root 228: /* DSP register or symbol? */
1.1.1.3 ! root 229: switch (regsize) {
! 230: case 16:
! 231: *number = (*((Uint16*)addr) & mask);
1.1 root 232: return len;
1.1.1.3 ! root 233: case 32:
! 234: *number = (*addr & mask);
1.1 root 235: return len;
1.1.1.3 ! root 236: default:
! 237: if (Symbols_GetDspAddress(SYMTYPE_ALL, name, number)) {
! 238: return len;
! 239: }
1.1 root 240: }
241: } else {
242: /* a special case CPU register? */
243: if (strcasecmp(name, "PC") == 0) {
244: *number = M68000_GetPC();
245: return len;
246: }
247: if (strcasecmp(name, "SR") == 0) {
248: *number = M68000_GetSR();
249: return len;
250: }
251: /* a normal CPU register or symbol? */
252: if (DebugCpu_GetRegisterAddress(name, &addr)) {
253: *number = *addr;
254: return len;
255: }
256: if (Symbols_GetCpuAddress(SYMTYPE_ALL, name, number)) {
257: return len;
258: }
259: }
260:
261: /* none of above, assume it's a number */
1.1.1.2 root 262: return getNumber(str, number, base);
1.1 root 263: }
264:
265:
1.1.1.2 root 266: /* Check that number string is OK and isn't followed by unrecognized
267: * character (last char char is zero). If not, complain about it.
1.1 root 268: * Return true for success and false for failure.
269: */
1.1.1.2 root 270: static bool isNumberOK(const char *str, int offset, int base)
1.1 root 271: {
1.1.1.2 root 272: const char *basestr;
273:
1.1 root 274: if (!offset) {
275: return false;
276: }
1.1.1.2 root 277: if (!str[offset]) {
278: /* no extra chars after the parsed part */
279: return true;
1.1 root 280: }
1.1.1.2 root 281: switch (base) {
282: case 0:
283: fprintf(stderr, "Name '%s' contains non-alphanumeric characters!\n", str);
1.1 root 284: return false;
1.1.1.2 root 285: case 2:
286: basestr = "binary";
287: break;
288: case 8:
289: basestr = "octal";
290: break;
291: case 10:
292: basestr = "decimal";
293: break;
294: case 16:
295: basestr = "hexadecimal";
296: break;
297: default:
298: basestr = "unknown";
1.1 root 299: }
1.1.1.2 root 300: fprintf(stderr, "Extra characters in %s based number '%s'!\n", basestr, str);
301: return false;
302: }
303:
304: /**
305: * Parse & set an (unsigned) number, assume it's in the configured
306: * default number base unless it has a suitable prefix.
307: * Return true for success and false for failure.
308: */
309: bool Eval_Number(const char *str, Uint32 *number)
310: {
311: int offset, base;
312: /* TODO: add CPU/DSP flag and use getValue() instead of getNumber()
313: * like getRange() does, so that user can use variable names in
314: * addition to numbers.
315: */
316: offset = getNumber(str, number, &base);
317: return isNumberOK(str, offset, base);
1.1 root 318: }
319:
320:
321: /**
1.1.1.2 root 322: * Parse an address range, eg. "$fa0000[-$fa0100]" or "pc[-a0]" and
323: * output appropriate warnings if range or values are invalid.
324: * Address can also be a register/variable/symbol name.
1.1 root 325: * returns:
1.1.1.2 root 326: * -1 if invalid address or range,
327: * 0 if single address,
328: * +1 if a range.
1.1 root 329: */
1.1.1.2 root 330: int Eval_Range(char *str1, Uint32 *lower, Uint32 *upper, bool fordsp)
1.1 root 331: {
1.1.1.2 root 332: int offset, base, ret;
1.1 root 333: bool fDash = false;
334: char *str2 = str1;
335:
336: while (*str2) {
337: if (*str2 == '-') {
338: *str2++ = '\0';
339: fDash = true;
340: break;
341: }
342: str2++;
343: }
344:
1.1.1.2 root 345: offset = getValue(str1, lower, &base, fordsp);
346: if (!isNumberOK(str1, offset, base)) {
347: /* first number not OK */
348: fprintf(stderr,"Invalid address value '%s'!\n", str1);
349: ret = -1;
350: } else {
351: /* first number OK */
352: ret = 0;
1.1 root 353: }
1.1.1.2 root 354: if (fDash) {
355: offset = getValue(str2, upper, &base, fordsp);
356: if (!isNumberOK(str2, offset, base)) {
357: /* second number not OK */
358: fprintf(stderr, "Invalid address value '%s'!\n", str2);
359: ret = -1;
360: } else {
361: if (*lower > *upper) {
362: fprintf(stderr,"Invalid range ($%x > $%x)!\n", *lower, *upper);
363: /* not a range */
364: ret = -1;
365: } else {
366: /* second number & range OK */
367: ret = 1;
368: }
369: }
370: *--str2 = '-';
371: }
372: return ret;
1.1 root 373: }
374:
375:
376: /**
377: * Evaluate expression. bForDsp determines which registers and symbols
378: * are interpreted. Sets given value and parsing offset.
379: * Return error string or NULL for success.
380: */
381: const char* Eval_Expression(const char *in, Uint32 *out, int *erroff, bool bForDsp)
382: {
383: /* in : expression to evaluate */
384: /* out : final parsed value */
385: /* value : current parsed value */
386: /* mark : current character in expression */
387: /* valid : expression validation flag, set when number parsed */
388: /* end : 'expression end' flag */
389: /* offset: character offset in expression */
390:
391: long long value;
1.1.1.2 root 392: int dummy, offset = 0;
1.1 root 393: char mark;
394:
395: /* Uses global variables: */
396:
397: par.idx = 0; /* parenthesis stack pointer */
398: par.opx[0] = par.vax[0] = 0; /* additional stack pointers */
399: op.idx = val.idx = -1;
400:
401: id.error = NULL;
402: id.valid = false; /* value validation */
403: value = 0;
404:
405: /* parsing loop, repeated until expression ends */
406: do {
407: mark = in[offset];
408: switch(mark) {
409: case '\0':
410: break;
411: case ' ':
412: case '\t':
413: offset ++; /* jump over white space */
414: break;
415: case '~': /* prefixes */
416: unary(mark);
417: offset ++;
418: break;
419: case '>': /* operators */
420: case '<':
421: offset ++;
422: /* check that it's '>>' or '<<' */
423: if (in[offset] != mark)
424: {
425: id.error = CLAC_GEN_ERR;
426: break;
427: }
428: operation (value, mark);
429: offset ++;
430: break;
431: case '|':
432: case '&':
433: case '^':
434: case '+':
435: case '-':
436: case '*':
437: case '/':
438: operation (value, mark);
439: offset ++;
440: break;
441: case '(':
442: open_bracket ();
443: offset ++;
444: break;
445: case ')':
446: value = close_bracket (value);
447: offset ++;
448: break;
449: default:
450: /* register/symbol/number value needed? */
451: if (id.valid == false) {
452: Uint32 tmp;
453: int consumed;
1.1.1.2 root 454: consumed = getValue(&(in[offset]), &tmp, &dummy, bForDsp);
1.1 root 455: /* number parsed? */
456: if (consumed) {
457: offset += consumed;
458: id.valid = true;
459: value = tmp;
460: break;
461: }
462: }
463: id.error = CLAC_GEN_ERR;
464: }
465:
466: /* until exit or error message */
467: } while(mark && !id.error);
468:
469: /* result of evaluation */
470: if (val.idx >= 0)
471: *out = val.buf[val.idx];
472:
473: /* something to return? */
474: if (!id.error) {
475: if (id.valid) {
476:
477: /* evaluate rest of the expression */
478: operation (value, LOWEST_PREDECENCE);
479: if (par.idx) /* mismatched */
480: id.error = CLAC_PAR_ERR;
481: else /* result out */
482: *out = val.buf[val.idx];
483:
484: } else {
485: if ((val.idx < 0) && (op.idx < 0)) {
486: id.error = CLAC_EXP_ERR;
487: } else /* trailing operators */
488: id.error = CLAC_GEN_ERR;
489: }
490: }
491:
492: *erroff = offset;
493: if (id.error) {
494: *out = 0;
495: return id.error;
496: }
497: return NULL;
498: }
499:
500:
501: /* ==================================================================== */
502: /* expression evaluation */
503: /* ==================================================================== */
504:
505: static void operation (long long value, char oper)
506: {
507: /* uses globals par[], id.error[], op[], val[]
508: * operation executed if the next one is on same or lower level
509: */
510: /* something to calc? */
511: if(id.valid == true) {
512:
513: /* add new items to stack */
514: PUSH(op, oper);
515: PUSH(val, value);
516:
517: /* more than 1 operator */
518: if(op.idx > par.opx[par.idx]) {
519:
520: /* but only one value */
521: if(val.idx == par.vax[par.idx]) {
522: apply_prefix();
523: } else {
524: /* evaluate all possible operations */
525: eval_stack();
526: }
527: }
528: /* next a number needed */
529: id.valid = false;
530: } else {
531: /* pre- or post-operators instead of in-betweens? */
532: unary(oper);
533: }
534: }
535:
536: /**
537: * handle unary operators
538: */
539: static void unary (char oper)
540: {
541: /* check pre-value operators
542: * have to be parenthesised
543: */
544: if(id.valid == false && op.idx < par.opx[par.idx])
545: {
546: switch(oper) {
547: case '+': /* not needed */
548: break;
549: case '-':
550: case '~':
551: PUSH(op, oper);
552: break;
553: default:
554: id.error = CLAC_GEN_ERR;
555: }
556: }
557: else
558: id.error = CLAC_GEN_ERR;
559: }
560:
561: /**
562: * apply a prefix to the current value
563: */
564: static void apply_prefix(void)
565: {
566: long long value = val.buf[val.idx];
567:
568: op.idx--;
569: switch(op.buf[op.idx]) {
570: case '-':
571: value = (-value);
572: break;
573: case '~':
574: value = (~value);
575: break;
576: default:
577: id.error = CLAC_PRG_ERR;
578: }
579: val.buf[val.idx] = value;
580: op.buf[op.idx] = op.buf[op.idx + 1];
581: }
582:
583: /* -------------------------------------------------------------------- */
584: /**
585: * evaluate operators if precedence allows it
586: */
587: /* evaluate all possible (according to order of precedence) operators */
588: static void eval_stack (void)
589: {
590: /* uses globals par[], op[], val[] */
591:
592: /* # of operators >= 2 and prev. op-level >= current op-level ? */
593: while ((op.idx > par.opx[par.idx]) && get_level (-1) >= get_level (0)) {
594:
595: /* shorten value stacks by one */
596: /* + calculate resulting value */
597: op.idx -= 1;
598: val.idx -= 1;
599: val.buf[val.idx] = apply_op(op.buf[op.idx],
600: val.buf[val.idx], val.buf[val.idx + 1]);
601:
602: /* pull the just used operator out of the stack */
603: op.buf[op.idx] = op.buf[op.idx + 1];
604: }
605: }
606:
607: /* -------------------------------------------------------------------- */
608: /**
609: * return the precedence level of a given operator
610: */
611: static int get_level (int offset)
612: {
613: /* used globals par[], op[]
614: * returns operator level of: operator[stack idx + offset]
615: */
616: switch(op.buf[op.idx + offset]) {
617: case '|': /* binary operations */
618: case '&':
619: case '^':
620: return 0;
621:
622: case '>': /* bit shifting */
623: case '<':
624: return 1;
625:
626: case '+':
627: case '-':
628: return 2;
629:
630: case '*':
631: case '/':
632: return 3;
633:
634: default:
635: id.error = CLAC_PRG_ERR;
636: }
637: return 6;
638: }
639:
640: /* -------------------------------------------------------------------- */
641: /**
642: * apply operator to given values, return the result
643: */
644: static long long apply_op (char opcode, long long value1, long long value2)
645: {
646: /* uses global id.error[] */
647: /* returns the result of operation */
648:
649: switch (opcode) {
650: case '|':
651: value1 |= value2;
652: break;
653: case '&':
654: value1 &= value2;
655: break;
656: case '^':
657: value1 ^= value2;
658: break;
659: case '>':
660: value1 >>= value2;
661: case '<':
662: value1 <<= value2;
663: break;
664: case '+':
665: value1 += value2;
666: break;
667: case '-':
668: value1 -= value2;
669: break;
670: case '*':
671: value1 *= value2;
672: break;
673: case '/':
674: /* don't divide by zero */
675: if (value2)
676: value1 /= value2;
677: else
678: id.error = CLAC_DEF_ERR;
679: break;
680: default:
681: id.error = CLAC_PRG_ERR;
682: }
683: return value1; /* return result */
684: }
685:
686:
687: /* ==================================================================== */
688: /* parenthesis and help */
689: /* ==================================================================== */
690:
691: /**
692: * open prenthesis, push values & operators to stack
693: */
694: static void open_bracket (void)
695: {
696: if (id.valid == false) { /* preceded by operator */
697: if (par.idx < PARDEPTH_MAX) { /* not nested too deep */
698: par.idx ++;
699: par.opx[par.idx] = op.idx + 1;
700: par.vax[par.idx] = val.idx + 1;
701: } else
702: id.error = CLAC_STK_ERR;
703: } else
704: id.error = CLAC_GEN_ERR;
705: }
706:
707: /* -------------------------------------------------------------------- */
708: /**
709: * close prenthesis, and evaluate / pop stacks
710: */
711: /* last parsed value, last param. flag, trigonometric mode */
712: static long long close_bracket (long long value)
713: {
714: /* returns the value of the parenthesised expression */
715:
716: if (id.valid) { /* preceded by an operator */
717: if (par.idx > 0) { /* prenthesis has a pair */
1.1.1.2 root 718: Uint32 addr;
719:
1.1 root 720: /* calculate the value of parenthesised exp. */
721: operation (value, LOWEST_PREDECENCE);
1.1.1.2 root 722: /* fetch the indirect ST RAM value */
723: addr = val.buf[val.idx];
724: value = STMemory_ReadLong(addr);
725: fprintf(stderr, " value in RAM at ($%x).l = $%llx\n", addr, value);
726: /* restore state before parenthesis */
727: op.idx = par.opx[par.idx] - 1;
1.1 root 728: val.idx = par.vax[par.idx] - 1;
729: par.idx --;
730:
731: /* next operator */
732: id.valid = true;
733: } else
734: id.error = CLAC_PAR_ERR;
735: } else
736: id.error = CLAC_GEN_ERR;
737:
738: return value;
739: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.