|
|
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.