debugger/custom event calculator updates.

This commit is contained in:
Toni Wilen 2023-05-08 20:19:03 +03:00
parent 1cae292eee
commit 693bc427fe
5 changed files with 374 additions and 94 deletions

366
calc.cpp
View File

@ -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)
{
switch (op)
{
case '-':
return v1 - v2;
case '+':
return v1 + v2;
case '*':
return v1 * v2;
case '/':
return v1 / v2;
case '\\':
return (int)v1 % (int)v2;
case '|':
return (int)v1 | (int)v2;
case '&':
return (int)v1 & (int)v2;
case '^':
return (int)v1 ^ (int)v2;
case '@':
return (int)v1 == (int)v2;
case '>':
return (int)v1 > (int)v2;
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;
}
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 double docalc2(TCHAR op, struct calcstack *sv1, struct calcstack *sv2)
static bool isstackstring(struct calcstack *st)
{
double v1, v2;
v1 = stacktoval(sv1);
v2 = stacktoval(sv2);
return docalcx (op, v1, v2);
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 double docalc1(TCHAR op, struct calcstack *sv1, double v2)
{
double v1;
v1 = stacktoval(sv1);
return docalcx (op, v1, v2);
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 '-':
v = v1 - v2;
break;
case '+':
v = v1 + v2;
break;
case '*':
v = v1 * v2;
break;
case '/':
v = v1 / v2;
break;
case '\\':
v = (int)v1 % (int)v2;
break;
case '|':
v = (int)v1 | (int)v2;
break;
case '&':
v = (int)v1 & (int)v2;
break;
case '^':
v = (int)v1 ^ (int)v2;
break;
case '@':
v = (int)v1 == (int)v2;
break;
case '@' | 0x80:
v = (int)v1 != (int)v2;
break;
case '>':
v = (int)v1 > (int)v2;
break;
case '<':
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 bool docalc2(TCHAR op, struct calcstack *sv1, struct calcstack *sv2, double *valp, TCHAR *sp)
{
*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 bool docalc1(TCHAR op, struct calcstack *sv1, double v2, double *valp, TCHAR *sp)
{
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)

View File

@ -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;
}
}

View File

@ -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;
}

View File

@ -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 */

View File

@ -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);