From: Toni Wilen Date: Mon, 8 May 2023 17:19:03 +0000 (+0300) Subject: debugger/custom event calculator updates. X-Git-Tag: 5.0.0~52 X-Git-Url: https://git.unchartedbackwaters.co.uk/w/?a=commitdiff_plain;h=693bc427fe1352e0acef71725970ee3f04f8523d;p=francis%2Fwinuae.git debugger/custom event calculator updates. --- diff --git a/calc.cpp b/calc.cpp index 2f1224d9..eaa10fd9 100644 --- a/calc.cpp +++ b/calc.cpp @@ -32,7 +32,8 @@ #define MAX_VALUES 32 #define IOBUFFERS 256 -static double parsedvalues[MAX_VALUES]; +static double parsedvaluesd[MAX_VALUES]; +static TCHAR *parsedvaluess[MAX_VALUES]; // operators // precedence operators associativity @@ -50,8 +51,12 @@ static int op_preced(const TCHAR c) return 3; case '+': case '-': return 2; - case '=': case '@': case '>': case '<': + case '=': case '@': case '@' | 0x80: case '>': case '<': case '>' | 0x80: case '<' | 0x80: return 1; + case ':': + return -1; + case '?': + return -2; } return 0; } @@ -64,7 +69,7 @@ static bool op_left_assoc(const TCHAR c) case '|': case '&': case '^': return true; // right to left - case '=': case '!': case '@': case '>': case '<': + case '=': case '!': case '@': case '@' | 0x80: case '>': case '<': case '>' | 0x80: case '<' | 0x80: return false; } return false; @@ -73,10 +78,13 @@ static bool op_left_assoc(const TCHAR c) static unsigned int op_arg_count(const TCHAR c) { switch(c) { - case '*': case '/': case '%': case '+': case '-': case '=': case '@': case '<': case '>': - case '|': case '&': case '^': + case '?': + return 3; + case '*': case '/': case '%': case '+': case '-': case '=': case '@': case '@' | 0x80: case '<': case '>': + case '|': case '&': case '^': case '<' | 0x80: case '>' | 0x80: return 2; case '!': + case ':': return 1; default: return c - 'A'; @@ -84,7 +92,9 @@ static unsigned int op_arg_count(const TCHAR c) return 0; } -#define is_operator(c) (c == '+' || c == '-' || c == '/' || c == '*' || c == '!' || c == '%' || c == '=' || c == '|' || c == '&' || c == '^' || c == '@' || c == '>' || c == '<') +#define is_operator(c) (c == '+' || c == '-' || c == '/' || c == '*' || c == '!' || c == '%' || c == '=' || \ + c == '|' || c == '&' || c == '^' || c == '@' || c == ('@' | 0x80) || c == '>' || c == '<' || c == ('>' | 0x80) || c == ('<' | 0x80) || \ + c == '?' || c == ':') #define is_function(c) (c >= 'A' && c <= 'Z') #define is_ident(c) ((c >= '0' && c <= '9') || (c >= 'a' && c <= 'z')) @@ -227,63 +237,205 @@ struct calcstack { TCHAR *s; double val; + TCHAR *vals; }; -static double docalcx(TCHAR op, double v1, double v2) +static double stacktoval(struct calcstack *st) +{ + if (st->s) { + if (_tcslen(st->s) == 1 && st->s[0] >= 'a' && st->s[0] <= 'z') + return parsedvaluesd[st->s[0] - 'a']; + return _tstof(st->s); + } else { + return st->val; + } +} + +static bool isstackstring(struct calcstack *st) +{ + if (st->vals && st->vals[0]) { + return true; + } + if (st->s) { + if (_tcslen(st->s) == 1 && st->s[0] >= 'a' && st->s[0] <= 'z') { + TCHAR *s = parsedvaluess[st->s[0] - 'a']; + if (s) { + return true; + } + } + } + return false; +} + +static TCHAR *stacktostring(struct calcstack *st) +{ + if (st->s) { + if (_tcslen(st->s) == 1 && st->s[0] >= 'a' && st->s[0] <= 'z') { + TCHAR *s = parsedvaluess[st->s[0] - 'a']; + if (s) { + st->vals = my_strdup(s); + xfree(st->s); + st->s = NULL; + return st->vals; + } + double v = parsedvaluesd[st->s[0] - 'a']; + TCHAR tmp[256]; + _stprintf(tmp, _T("%d"), (int)v); + st->vals = my_strdup(tmp); + xfree(st->s); + st->s = NULL; + return st->vals; + } + } + if (!st->vals || !st->vals[0]) { + TCHAR tmp[256]; + _stprintf(tmp, _T("%d"), (int)st->val); + xfree(st->vals); + st->vals = my_strdup(tmp); + } + return st->vals; +} + + +static TCHAR *docalcxs(TCHAR op, TCHAR *v1, TCHAR *v2, double *voutp) { + TCHAR tmp[MAX_DPATH]; + tmp[0] = 0; + + switch(op) + { + case '+': + _tcscpy(tmp, v1); + _tcscat(tmp, v2); + break; + case '@': + if (!_tcsicmp(v1, v2)) { + *voutp = 1; + return my_strdup(_T("")); + } else { + *voutp = 0; + return my_strdup(_T("")); + } + break; + case '@' | 0x80: + if (!_tcsicmp(v1, v2)) { + *voutp = 0; + return my_strdup(_T("")); + } else { + *voutp = 1; + return my_strdup(_T("")); + } + break; + case ':': + _tcscpy(tmp, v1); + break; + default: + return NULL; + } + return my_strdup(tmp); +} + +static bool docalcx(TCHAR op, double v1, double v2, double *valp) +{ + double v = 0; switch (op) { case '-': - return v1 - v2; + v = v1 - v2; + break; case '+': - return v1 + v2; - case '*': - return v1 * v2; - case '/': - return v1 / v2; - case '\\': - return (int)v1 % (int)v2; + v = v1 + v2; + break; + case '*': + v = v1 * v2; + break; + case '/': + v = v1 / v2; + break; + case '\\': + v = (int)v1 % (int)v2; + break; case '|': - return (int)v1 | (int)v2; + v = (int)v1 | (int)v2; + break; case '&': - return (int)v1 & (int)v2; + v = (int)v1 & (int)v2; + break; case '^': - return (int)v1 ^ (int)v2; + v = (int)v1 ^ (int)v2; + break; case '@': - return (int)v1 == (int)v2; + v = (int)v1 == (int)v2; + break; + case '@' | 0x80: + v = (int)v1 != (int)v2; + break; case '>': - return (int)v1 > (int)v2; + v = (int)v1 > (int)v2; + break; case '<': - return (int)v1 < (int)v2; - } - return 0; -} - -static double stacktoval(struct calcstack *st) -{ - if (st->s) { - if (_tcslen(st->s) == 1 && st->s[0] >= 'a' && st->s[0] <= 'z') - return parsedvalues[st->s[0] - 'a']; - return _tstof (st->s); - } else { - return st->val; - } + v = (int)v1 < (int)v2; + break; + case '<' | 0x80: + if ((uae_u32)v2 < 32) { + v = (uae_u32)v1 << (uae_u32)v2; + } + break; + case '>' | 0x80: + if ((uae_u32)v2 < 32) { + v = (uae_u32)v1 >> (uae_u32)v2; + } + break; + case ':': + v = v1; + break; + default: + return false; + } + *valp = v; + return true; } -static double docalc2(TCHAR op, struct calcstack *sv1, struct calcstack *sv2) +static bool docalc2(TCHAR op, struct calcstack *sv1, struct calcstack *sv2, double *valp, TCHAR *sp) { - double v1, v2; - - v1 = stacktoval(sv1); - v2 = stacktoval(sv2); - return docalcx (op, v1, v2); + *sp = NULL; + *valp = 0; + if (isstackstring(sv1) || isstackstring(sv2)) { + TCHAR *v1 = stacktostring(sv1); + TCHAR *v2 = stacktostring(sv2); + double vout = 0; + TCHAR *s = docalcxs(op, v1, v2, &vout); + if (!s) { + return false; + } + _tcscpy(sp, s); + xfree(s); + if (vout) { + *valp = vout; + } + return true; + } else { + double v1 = stacktoval(sv1); + double v2 = stacktoval(sv2); + return docalcx(op, v1, v2, valp); + } } -static double docalc1(TCHAR op, struct calcstack *sv1, double v2) +static bool docalc1(TCHAR op, struct calcstack *sv1, double v2, double *valp, TCHAR *sp) { - double v1; - - v1 = stacktoval(sv1); - return docalcx (op, v1, v2); + if (isstackstring(sv1)) { + TCHAR *v1 = stacktostring(sv1); + double vout; + TCHAR *s = docalcxs(op, v1, _T(""), &vout); + if (!s) { + return false; + } + _tcscpy(sp, s); + xfree(s); + return true; + } else { + double v1 = stacktoval(sv1); + return docalcx(op, v1, v2, valp); + } } #if CALC_DEBUG @@ -305,16 +457,20 @@ static TCHAR *chartostack(TCHAR c) return s; } -static bool execution_order(const TCHAR *input, double *outval) +static struct calcstack stack[STACK_SIZE] = { 0 }; + +static bool execution_order(const TCHAR *input, double *outval, TCHAR *outstring, int maxlen) { const TCHAR *strpos = input, *strend = input + _tcslen(input); TCHAR c, res[4]; unsigned int sl = 0, rn = 0; - struct calcstack stack[STACK_SIZE] = { { 0 } }, *sc, *sc2; + struct calcstack *sc, *sc2; double val = 0; - int i; + TCHAR vals[MAX_DPATH]; + int i; bool ok = false; + vals[0] = 0; // While there are input tokens left while(strpos < strend) { @@ -361,20 +517,37 @@ static bool execution_order(const TCHAR *input, double *outval) if(nargs == 1) { sc = &stack[sl - 1]; sl--; - val = docalc1 (c, sc, val); + docalc1 (c, sc, val, &val, vals); calc_log ((_T("%c %s = %f;\n"), c, stacktostr(sc), val)); } - else { + else if (nargs == 2) { sc = &stack[sl - 2]; calc_log ((_T("%s %c "), stacktostr(sc), c)); sc2 = &stack[sl - 1]; - val = docalc2 (c, sc, sc2); - sl--;sl--; + docalc2 (c, sc, sc2, &val, vals); + sl--;sl--; calc_log ((_T("%s = %f;\n"), stacktostr(sc2), val)); + } else if (nargs == 3) { + // ternary + sc = &stack[sl - 3]; + if (sc->val != 0) { + sc2 = &stack[sl - 2]; + } else { + sc2 = &stack[sl - 1]; + } + sl--;sl--;sl--; + if (isstackstring(sc2)) { + TCHAR *c = stacktostring(sc2); + _tcscpy(vals, c); + xfree(c); + } + val = stacktoval(sc2); } } // Push the returned results, if any, back onto the stack. stack[sl].val = val; + xfree(stack[sl].vals); + stack[sl].vals = my_strdup(vals); stack[sl].s = NULL; ++sl; } @@ -388,6 +561,12 @@ static bool execution_order(const TCHAR *input, double *outval) calc_log ((_T("result = %f\n"), val)); if (outval) *outval = val; + if (outstring) { + if (vals && _tcslen(vals) >= maxlen) { + vals[maxlen] = 0; + } + _tcscpy(outstring, vals ? vals : _T("")); + } ok = true; } for (i = 0; i < STACK_SIZE; i++) @@ -433,12 +612,41 @@ static bool parse_values(const TCHAR *ins, TCHAR *out) in[2] = ' '; in[3] = ' '; in[4] = ' '; - } + } else if (in[0] == '>' && in[1] == '>') { + in[0] = '>' | 0x80; + in[1] = ' '; + } else if (in[0] == '<' && in[1] == '<') { + in[0] = '<' | 0x80; + in[1] = ' '; + } else if (in[0] == '"' || in[0] == '\'') { + TCHAR *quoted = in; + TCHAR quotec = *in; + *in++ = 0; + if (ident >= MAX_VALUES) + return false; + *p++ = ident + 'a'; + while (*in != 0 && *in != quotec) { + in++; + } + if (*in != quotec) { + return false; + } + *in = 0; + parsedvaluess[ident++] = my_strdup(quoted + 1); + while (quoted <= in) { + *quoted++ = ' '; + } + continue; + } if (*in == '=' && *(in + 1) == '=') { *in = '@'; *(in + 1) = ' '; } - if (_istdigit (*in)) { + if (*in == '!' && *(in + 1) == '=') { + *in = '@' | 0x80; + *(in + 1) = ' '; + } + if (_istdigit (*in)) { if (ident >= MAX_VALUES) return false; if (op > 1 && (in[-1] == '-' || in[-1] == '+')) { @@ -450,7 +658,7 @@ static bool parse_values(const TCHAR *ins, TCHAR *out) in++; tmp = *in; *in = 0; - parsedvalues[ident++] = _tstof (instart); + parsedvaluesd[ident++] = _tstof (instart); *in = tmp; op = 0; } else { @@ -463,21 +671,43 @@ static bool parse_values(const TCHAR *ins, TCHAR *out) return true; } -bool calc(const TCHAR *input, double *outval) +int calc(const TCHAR *input, double *outval, TCHAR *outstring, int maxlen) { TCHAR output[IOBUFFERS], output2[IOBUFFERS]; + int ret = -1; calc_log ((_T("IN: '%s'\n"), input)); + if (outval) { + *outval = 0; + } + if (outstring) { + outstring[0] = 0; + } if (parse_values(input, output2)) { if(shunting_yard(output2, output)) { calc_log ((_T("RPN OUT: %s\n"), output)); - if(!execution_order(output, outval)) { + if(!execution_order(output, outval, outstring, maxlen)) { calc_log ((_T("PARSE ERROR!\n"))); } else { - return true; + if (outstring && outstring[0]) { + ret = -1; + } else { + ret = 1; + } } } } - return false; + for (int i = 0; i < MAX_VALUES; i++) { + xfree(parsedvaluess[i]); + parsedvaluesd[i] = 0; + parsedvaluess[i] = NULL; + } + for (int i = 0; i < STACK_SIZE; i++) { + struct calcstack *s = &stack[i]; + xfree(s->vals); + xfree(s->s); + memset(s, 0, sizeof(struct calcstack)); + } + return ret; } bool iscalcformula (const TCHAR *formula) diff --git a/cfgfile.cpp b/cfgfile.cpp index 1a8e2b16..11ebde0c 100644 --- a/cfgfile.cpp +++ b/cfgfile.cpp @@ -6649,11 +6649,12 @@ static int getconfigstoreline (const TCHAR *option, TCHAR *value); static void calcformula (struct uae_prefs *prefs, TCHAR *in) { - TCHAR out[MAX_DPATH], configvalue[CONFIG_BLEN]; + TCHAR out[MAX_DPATH], configvalue[CONFIG_BLEN], tmp[MAX_DPATH]; TCHAR *p = out; double val; int cnt1, cnt2; static bool updatestore; + int escaped, quoted; if (_tcslen (in) < 2 || in[0] != '[' || in[_tcslen (in) - 1] != ']') return; @@ -6663,9 +6664,18 @@ static void calcformula (struct uae_prefs *prefs, TCHAR *in) if (!configstore) return; cnt1 = cnt2 = 0; + escaped = 0; + quoted = 0; for (int i = 1; i < _tcslen (in) - 1; i++) { TCHAR c = _totupper (in[i]); - if (c >= 'A' && c <='Z') { + if (c == '\\') { + escaped = 1; + } else if (c == '\'') { + quoted = escaped + 1; + escaped = 0; + cnt2++; + *p++ = c; + } else if (c >= 'A' && c <='Z') { TCHAR *start = &in[i]; while (_istalnum (c) || c == '_' || c == '.') { i++; @@ -6674,16 +6684,22 @@ static void calcformula (struct uae_prefs *prefs, TCHAR *in) TCHAR store = in[i]; in[i] = 0; //write_log (_T("'%s'\n"), start); - if (!getconfigstoreline (start, configvalue)) - return; - _tcscpy (p, configvalue); + if ((quoted == 0 || quoted == 2) && getconfigstoreline (start, configvalue)) { + _tcscpy(p, configvalue); + } else { + _tcscpy(p, start); + } p += _tcslen (p); in[i] = store; i--; cnt1++; + escaped = 0; + quoted = 0; } else { cnt2++; - *p ++= c; + *p++= c; + escaped = 0; + quoted = 0; } } *p = 0; @@ -6695,13 +6711,16 @@ static void calcformula (struct uae_prefs *prefs, TCHAR *in) updatestore = true; return; } - if (calc (out, &val)) { + int v = calc(out, &val, tmp, sizeof(tmp) / sizeof(TCHAR)); + if (v > 0) { if (val - (int)val != 0.0f) _stprintf (in, _T("%f"), val); else _stprintf (in, _T("%d"), (int)val); updatestore = true; - return; + } else if (v < 0) { + _tcscpy(in, tmp); + updatestore = true; } } diff --git a/debug.cpp b/debug.cpp index afe157d8..e1f07a06 100644 --- a/debug.cpp +++ b/debug.cpp @@ -750,12 +750,26 @@ static int readregx(TCHAR **c, uae_u32 *valp) return 1; } +static bool checkisneg(TCHAR **c) +{ + TCHAR nc = peekchar(c); + if (nc == '-') { + (*c)++; + return true; + } else if (nc == '+') { + (*c)++; + } + return false; +} + static bool readbinx (TCHAR **c, uae_u32 *valp) { uae_u32 val = 0; bool first = true; + bool negative = false; ignore_ws (c); + negative = checkisneg(c); for (;;) { TCHAR nc = **c; if (nc != '1' && nc != '0') { @@ -769,7 +783,7 @@ static bool readbinx (TCHAR **c, uae_u32 *valp) if (nc == '1') val |= 1; } - *valp = val; + *valp = val * (negative ? -1 : 1); return true; } @@ -777,9 +791,11 @@ static bool readhexx (TCHAR **c, uae_u32 *valp) { uae_u32 val = 0; TCHAR nc; + bool negative = false; - ignore_ws (c); - if (!isxdigit (peekchar (c))) + ignore_ws(c); + negative = checkisneg(c); + if (!isxdigit(peekchar(c))) return false; while (isxdigit (nc = **c)) { (*c)++; @@ -791,7 +807,7 @@ static bool readhexx (TCHAR **c, uae_u32 *valp) val += nc - 'A' + 10; } } - *valp = val; + *valp = val * (negative ? -1 : 1); return true; } @@ -802,8 +818,7 @@ static bool readintx (TCHAR **c, uae_u32 *valp) int negative = 0; ignore_ws (c); - if (**c == '-') - negative = 1, (*c)++; + negative = checkisneg(c); if (!isdigit (peekchar (c))) return false; while (isdigit (nc = **c)) { @@ -896,14 +911,8 @@ static int checkvaltype (TCHAR **cp, uae_u32 *val, int *size, TCHAR def) for (;;) { uae_u32 v; if (!checkvaltype2 (cp, &v, def)) { - if (isoperator(cp) || gotop) { - for (;;) { - *p = readchar(cp); - if (*p == 0) { - goto docalc; - } - p++; - } + if (isoperator(cp) || gotop || **cp == '\"' || **cp == '\'') { + goto docalc; } return 0; } @@ -911,11 +920,13 @@ static int checkvaltype (TCHAR **cp, uae_u32 *val, int *size, TCHAR def) // stupid but works! _stprintf(p, _T("%u"), v); p += _tcslen (p); + *p = 0; if (peekchar (cp) == '.') { readchar (cp); if (size) *size = readsize (v, cp); } + ignore_ws(cp); if (!isoperator (cp)) break; gotop = true; @@ -936,7 +947,13 @@ static int checkvaltype (TCHAR **cp, uae_u32 *val, int *size, TCHAR def) return 1; } docalc: - if (calc (form, &out)) { + while (more_params2(cp)) { + *p++ = readchar(cp); + } + *p = 0; + TCHAR tmp[MAX_DPATH]; + int v = calc(form, &out, tmp, sizeof(tmp) / sizeof(TCHAR)); + if (v > 0) { *val = (uae_u32)out; if (size && *size == 0) { uae_s32 v = (uae_s32)(*val); @@ -949,6 +966,8 @@ docalc: } } return 1; + } else if (v < 0) { + console_out_f(_T("String returned: '%s'\n"), tmp); } return 0; } diff --git a/include/calc.h b/include/calc.h index 33ae11a2..80bb1988 100644 --- a/include/calc.h +++ b/include/calc.h @@ -3,7 +3,7 @@ #include "uae/types.h" -extern bool calc(const TCHAR *input, double *outval); -extern bool iscalcformula (const TCHAR *formula); +extern int calc(const TCHAR *input, double *outval, TCHAR *outstring, int maxlen); +extern bool iscalcformula(const TCHAR *formula); #endif /* UAE_CALC_H */ diff --git a/inputdevice.cpp b/inputdevice.cpp index 63f050e8..d3b6d79f 100644 --- a/inputdevice.cpp +++ b/inputdevice.cpp @@ -1535,8 +1535,20 @@ static const struct inputevent *readevent (const TCHAR *name, TCHAR **customp) if (_tcslen (name) > 2 && name[0] == '\'') { name++; const TCHAR *end = name; - while (*end && *end != '\'') + bool equote = false; + while (*end) { + if (*end == '\"') { + if (!equote) { + equote = 1; + } else { + equote = 0; + } + } + if (!equote && *end == '\'') { + break; + } end++; + } if (!customp || *end == 0) return NULL; TCHAR *custom = my_strdup (name);