--- hatari/src/debug/evaluate.c 2019/04/09 08:48:37 1.1 +++ hatari/src/debug/evaluate.c 2019/04/09 08:49:26 1.1.1.2 @@ -1,13 +1,15 @@ /* Hatari - calculate.c - Copyright (C) 1994, 2009 by Eero Tamminen + Copyright (C) 1994, 2009-2010 by Eero Tamminen This file is distributed under the GNU Public License, version 2 or at your option any later version. Read the file gpl.txt for details. calculate.c - parse numbers, number ranges and expressions. Supports - most unary and binary operations, parenthesis and order of precedence. + most unary and binary operations. Parenthesis are used for indirect + ST RAM value addressing. + Originally based on code from my Clac calculator MiNT filter version. */ const char Eval_fileid[] = "Hatari calculate.c : " __DATE__ " " __TIME__; @@ -19,18 +21,20 @@ const char Eval_fileid[] = "Hatari calcu #include #include #include +#include "breakcond.h" #include "configuration.h" #include "dsp.h" #include "debugcpu.h" #include "evaluate.h" #include "main.h" #include "m68000.h" +#include "stMemory.h" #include "symbols.h" /* define which character indicates which type of number on expression */ -#define PREFIX_BIN '%' /* binary decimal */ -#define PREFIX_DEC '#' /* normal decimal */ -#define PREFIX_HEX '$' /* hexadecimal */ +#define PREFIX_BIN '%' /* binary decimal */ +#define PREFIX_DEC '#' /* normal decimal */ +#define PREFIX_HEX '$' /* hexadecimal */ /* define error codes */ #define CLAC_EXP_ERR "No expression given" @@ -43,9 +47,9 @@ const char Eval_fileid[] = "Hatari calcu #define CLAC_PRG_ERR "Internal program error" /* define internal allocation sizes (should be enough ;-) */ -#define PARDEPTH_MAX 64 /* max. parenth. nesting depth */ -#define OSTACK_MAX 128 /* size of the operator stack */ -#define VSTACK_MAX 128 /* size of the value stack */ +#define PARDEPTH_MAX 16 /* max. parenth. nesting depth */ +#define OSTACK_MAX 64 /* size of the operator stack */ +#define VSTACK_MAX 64 /* size of the value stack */ /* operation with lowest precedence, used to finish calculations */ #define LOWEST_PREDECENCE '|' @@ -191,15 +195,16 @@ static int getNumber(const char *str, Ui /** - * Parse unsigned register/symbol/number value and set it to "number". + * Parse unsigned register/symbol/number value and set it to "number" + * and the number base used for parsing to "base". * Return how many characters were parsed or zero for error. */ -static int getValue(const char *str, Uint32 *number, bool bForDsp) +static int getValue(const char *str, Uint32 *number, int *base, bool bForDsp) { char name[64]; const char *end; Uint32 mask, *addr; - int len, dummy; + int len; for (end = str; *end == '_' || isalnum(*end); end++); @@ -211,6 +216,13 @@ static int getValue(const char *str, Uin memcpy(name, str, len); name[len] = '\0'; + *base = 0; /* no base (e.g. variable) */ + + /* internal Hatari variable? */ + if (BreakCond_GetHatariVariable(name, number)) { + return len; + } + if (bForDsp) { /* DSP register or symbol? */ if (DSP_GetRegisterAddress(name, &addr, &mask)) { @@ -241,63 +253,79 @@ static int getValue(const char *str, Uin } /* none of above, assume it's a number */ - return getNumber(str, number, &dummy); + return getNumber(str, number, base); } -/** - * Parse & set an (unsigned) number, assume it's in the configured - * default number base unless it has a suitable prefix. +/* Check that number string is OK and isn't followed by unrecognized + * character (last char char is zero). If not, complain about it. * Return true for success and false for failure. */ -bool Eval_Number(const char *str, Uint32 *number) +static bool isNumberOK(const char *str, int offset, int base) { - int offset, base = 0; - - offset = getNumber(str, number, &base); + const char *basestr; + if (!offset) { return false; } - if (str[offset]) { - const char *basestr; - - switch (base) { - case 2: - basestr = "binary"; - break; - case 8: - basestr = "octal"; - break; - case 10: - basestr = "decimal"; - break; - case 16: - basestr = "hexadecimal"; - break; - default: - basestr = "unknown"; + if (!str[offset]) { + /* no extra chars after the parsed part */ + return true; } - fprintf(stderr, "Extra characters in %s based number '%s'!\n", - basestr, str); + switch (base) { + case 0: + fprintf(stderr, "Name '%s' contains non-alphanumeric characters!\n", str); return false; + case 2: + basestr = "binary"; + break; + case 8: + basestr = "octal"; + break; + case 10: + basestr = "decimal"; + break; + case 16: + basestr = "hexadecimal"; + break; + default: + basestr = "unknown"; } - return true; + fprintf(stderr, "Extra characters in %s based number '%s'!\n", basestr, str); + return false; +} + +/** + * Parse & set an (unsigned) number, assume it's in the configured + * default number base unless it has a suitable prefix. + * Return true for success and false for failure. + */ +bool Eval_Number(const char *str, Uint32 *number) +{ + int offset, base; + /* TODO: add CPU/DSP flag and use getValue() instead of getNumber() + * like getRange() does, so that user can use variable names in + * addition to numbers. + */ + offset = getNumber(str, number, &base); + return isNumberOK(str, offset, base); } /** - * Get a an adress range, eg. "$fa0000-$fa0100" + * Parse an address range, eg. "$fa0000[-$fa0100]" or "pc[-a0]" and + * output appropriate warnings if range or values are invalid. + * Address can also be a register/variable/symbol name. * returns: - * 0 if OK, - * -1 if not syntaxically a range, - * -2 if values are invalid, - * -3 if syntaxically range, but not value-wise. + * -1 if invalid address or range, + * 0 if single address, + * +1 if a range. */ -static int getRange(char *str1, Uint32 *lower, Uint32 *upper) +int Eval_Range(char *str1, Uint32 *lower, Uint32 *upper, bool fordsp) { + int offset, base, ret; bool fDash = false; char *str2 = str1; - int ret = 0; while (*str2) { if (*str2 == '-') { @@ -307,46 +335,35 @@ static int getRange(char *str1, Uint32 * } str2++; } - if (!fDash) - return -1; - if (!Eval_Number(str1, lower)) - ret = -2; - else if (!Eval_Number(str2, upper)) - ret = -2; - else if (*lower > *upper) - ret = -3; - *--str2 = '-'; - return ret; -} - - -/** - * Parse an adress range, eg. "$fa0000[-$fa0100]" + show appropriate warnings - * returns: - * -1 if invalid address or range, - * 0 if single address, - * +1 if a range. - */ -int Eval_Range(char *str, Uint32 *lower, Uint32 *upper) -{ - switch (getRange(str, lower, upper)) { - case 0: - return 1; - case -1: - /* single address, not a range */ - if (!Eval_Number(str, lower)) - return -1; - return 0; - case -2: - fprintf(stderr,"Invalid address values in '%s'!\n", str); - return -1; - case -3: - fprintf(stderr,"Invalid range ($%x > $%x)!\n", *lower, *upper); - return -1; + offset = getValue(str1, lower, &base, fordsp); + if (!isNumberOK(str1, offset, base)) { + /* first number not OK */ + fprintf(stderr,"Invalid address value '%s'!\n", str1); + ret = -1; + } else { + /* first number OK */ + ret = 0; } - fprintf(stderr, "INTERNAL ERROR: Unknown getRange() return value.\n"); - return -1; + if (fDash) { + offset = getValue(str2, upper, &base, fordsp); + if (!isNumberOK(str2, offset, base)) { + /* second number not OK */ + fprintf(stderr, "Invalid address value '%s'!\n", str2); + ret = -1; + } else { + if (*lower > *upper) { + fprintf(stderr,"Invalid range ($%x > $%x)!\n", *lower, *upper); + /* not a range */ + ret = -1; + } else { + /* second number & range OK */ + ret = 1; + } + } + *--str2 = '-'; + } + return ret; } @@ -366,7 +383,7 @@ const char* Eval_Expression(const char * /* offset: character offset in expression */ long long value; - int offset = 0; + int dummy, offset = 0; char mark; /* Uses global variables: */ @@ -428,7 +445,7 @@ const char* Eval_Expression(const char * if (id.valid == false) { Uint32 tmp; int consumed; - consumed = getValue(&(in[offset]), &tmp, bForDsp); + consumed = getValue(&(in[offset]), &tmp, &dummy, bForDsp); /* number parsed? */ if (consumed) { offset += consumed; @@ -692,10 +709,16 @@ static long long close_bracket (long lon if (id.valid) { /* preceded by an operator */ if (par.idx > 0) { /* prenthesis has a pair */ + Uint32 addr; + /* calculate the value of parenthesised exp. */ operation (value, LOWEST_PREDECENCE); - value = val.buf[val.idx]; - op.idx = par.opx[par.idx] - 1; /* restore prev */ + /* fetch the indirect ST RAM value */ + addr = val.buf[val.idx]; + value = STMemory_ReadLong(addr); + fprintf(stderr, " value in RAM at ($%x).l = $%llx\n", addr, value); + /* restore state before parenthesis */ + op.idx = par.opx[par.idx] - 1; val.idx = par.vax[par.idx] - 1; par.idx --;