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