Fix implied operators under NEW_MATH

This fixes several issues with the implied operators when NEW_MATH is enabled:

* None of the implied operators were returning the correct value, which should be the value
assigned to the LHS.

* The &&=, ||= ad ^^= operators were also operating on uninitialized variables and so behaving
unpredictably.

* The /= and %= operators would crash the client when the RHS was zero, because after outputting
the "Divide by zero" error they would go on to perform the operation anyway.
This commit is contained in:
Kevin Easton
2016-09-29 01:11:29 +10:00
parent a625650c4a
commit 7e3c39a464
2 changed files with 33 additions and 19 deletions

View File

@@ -773,7 +773,6 @@ __inline static void pop2s_a (expr_info *c, char **s, char **t, TOKEN *v)
*v = t1;
}
#if notused
__inline static void pop2b_a (expr_info *c, BooL *a, BooL *b, TOKEN *v)
{
TOKEN t1, t2;
@@ -788,7 +787,6 @@ __inline static void pop2b_a (expr_info *c, BooL *a, BooL *b, TOKEN *v)
new_free(&x);
new_free(&y);
}
#endif
__inline static void pop3 (expr_info *c, NUMBER *a, TOKEN *v, TOKEN *w)
{
@@ -866,27 +864,41 @@ void op (expr_info *cx, int what)
}
#define IMPLIED(x) \
{ \
long r; \
pop2n_a(cx, &a, &b, &v); \
r = (x); \
if (x_debug & DEBUG_NEW_MATH_DEBUG) \
debugyell("O: %s = %s (%ld %ld) -> %ld", \
get_token(cx, v), #x, a, b, x); \
pushn(cx, setnvar(cx, v, (x))); \
get_token(cx, v), #x, a, b, r); \
setnvar(cx, v, r); \
pushn(cx, r); \
break; \
}
#define IMPLIED_BOOLEAN(x) \
{ \
long r; \
pop2b_a(cx, &c, &d, &v); \
r = (x); \
if (x_debug & DEBUG_NEW_MATH_DEBUG) \
debugyell("O: %s = %s (%ld %ld) -> %ld", \
get_token(cx, v), #x, c, d, r); \
setnvar(cx, v, r); \
pushn(cx, r); \
break; \
}
#define IMPLIED_NOZERO(x) \
{ \
long r = 0; \
pop2n_a(cx, &a, &b, &v); \
if (b == 0) { \
if (x_debug & DEBUG_NEW_MATH_DEBUG) \
debugyell("O: %s = %s (%ld %ld) -> 0", \
get_token(cx, v), #x, a, b); \
error("Division by zero"); \
pushn(cx, setnvar(cx, v, 0)); \
} \
if (b != 0) \
r = (x); \
if (x_debug & DEBUG_NEW_MATH_DEBUG) \
debugyell("O: %s = %s (%ld %ld) -> %ld", \
get_token(cx, v), #x, a, b, x); \
pushn(cx, setnvar(cx, v, (x))); \
get_token(cx, v), #x, a, b, r); \
if (b == 0) \
error("Division by zero"); \
setnvar(cx, v, r); \
pushn(cx, r); \
break; \
}
#define AUTO_UNARY(x, y) \
@@ -1040,9 +1052,9 @@ void op (expr_info *cx, int what)
case OREQ: IMPLIED(a | b)
case SHLEFTEQ: IMPLIED(a << b)
case SHRIGHTEQ: IMPLIED(a >> b)
case DANDEQ: IMPLIED((long)(c && d))
case DOREQ: IMPLIED((long)(c || d))
case DXOREQ: IMPLIED((long)((c && !d) || (!c && d)))
case DANDEQ: IMPLIED_BOOLEAN(c && d)
case DOREQ: IMPLIED_BOOLEAN(c || d)
case DXOREQ: IMPLIED_BOOLEAN((c && !d) || (!c && d))
case STRCATEQ:
pop2s_a(cx, &s, &t, &v);
if (x_debug & DEBUG_NEW_MATH_DEBUG)
@@ -1192,7 +1204,7 @@ int lexerr (expr_info *c, char *format, ...)
* case 'operand' is set to 1. When an operand is lexed, then the next token
* is expected to be a binary operator, so 'operand' is set to 0.
*/
__inline int check_implied_arg (expr_info *c)
static __inline int check_implied_arg (expr_info *c)
{
if (c->operand == 2)
{
@@ -1205,7 +1217,7 @@ __inline int check_implied_arg (expr_info *c)
return c->operand;
}
__inline TOKEN operator (expr_info *c, char *x, int y, TOKEN z)
static __inline TOKEN operator (expr_info *c, char *x, int y, TOKEN z)
{
check_implied_arg(c);
if (c->operand)
@@ -1216,7 +1228,7 @@ __inline TOKEN operator (expr_info *c, char *x, int y, TOKEN z)
return z;
}
__inline TOKEN unary (expr_info *c, char *x, int y, TOKEN z)
static __inline TOKEN unary (expr_info *c, char *x, int y, TOKEN z)
{
if (!c->operand)
return lexerr(c, "An operator (%s) was found where "