diff options
author | Denys Vlasenko | 2023-06-17 11:03:02 +0200 |
---|---|---|
committer | Denys Vlasenko | 2023-06-17 11:03:02 +0200 |
commit | 19a74a54ded98b28c672d38b79ea9f313f2d89db (patch) | |
tree | 41898bf80b1518438979d5e7c64787c73f766ba9 | |
parent | 6221832bc15d9037360e3bdc9405df08ed801cc1 (diff) | |
download | busybox-19a74a54ded98b28c672d38b79ea9f313f2d89db.zip busybox-19a74a54ded98b28c672d38b79ea9f313f2d89db.tar.gz |
shell/math: change ?: nesting code to not have 63 level nesting limitation
function old new delta
evaluate_string 1406 1432 +26
arith 36 29 -7
arith_apply 998 990 -8
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 1/2 up/down: 26/-15) Total: 11 bytes
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | shell/math.c | 33 | ||||
-rw-r--r-- | shell/math.h | 2 |
2 files changed, 21 insertions, 14 deletions
diff --git a/shell/math.c b/shell/math.c index 6196a6a..3e339a5 100644 --- a/shell/math.c +++ b/shell/math.c @@ -599,8 +599,6 @@ static arith_t strto_arith_t(const char *nptr, char **endptr) static arith_t evaluate_string(arith_state_t *math_state, const char *expr) { -#define EVAL_DISABLED ((unsigned long long)math_state->evaluation_disabled) -#define TOP_BIT_ULL ((unsigned long long)LLONG_MAX + 1) operator lasttok; const char *errmsg = NULL; const char *start_expr = expr = skip_whitespace(expr); @@ -617,6 +615,7 @@ evaluate_string(arith_state_t *math_state, const char *expr) operator *const opstack = alloca(expr_len * sizeof(opstack[0])); operator *opstackptr = opstack; operator insert_op = 0xff; + unsigned ternary_level = 0; /* Start with a left paren */ dbg("(%d) op:TOK_LPAREN", (int)(opstackptr - opstack)); @@ -875,8 +874,11 @@ dbg(" numstack:%d val:%lld '%s'", (int)(numstackptr - numstack), numstackptr[ /* Example: a=1?2:3,a. We just executed ":". * Prevent assignment from being still disabled. */ - math_state->evaluation_disabled >>= 1; - dbg("':' executed: evaluation_disabled=%llx (restored)", EVAL_DISABLED); + if (ternary_level == math_state->evaluation_disabled) { + math_state->evaluation_disabled = 0; + dbg("':' executed: evaluation_disabled=CLEAR"); + } + ternary_level--; } } /* while (opstack not empty) */ @@ -887,12 +889,11 @@ dbg(" numstack:%d val:%lld '%s'", (int)(numstackptr - numstack), numstackptr[ /* We just now evaluated EXPR before "?". * Should we disable evaluation now? */ - if (math_state->evaluation_disabled & TOP_BIT_ULL) - goto err; /* >63 levels of ?: nesting not supported */ - math_state->evaluation_disabled = - (math_state->evaluation_disabled << 1) - | (numstackptr[-1].val == 0); - dbg("'?' entered: evaluation_disabled=%llx", EVAL_DISABLED); + ternary_level++; + if (numstackptr[-1].val == 0 && !math_state->evaluation_disabled) { + math_state->evaluation_disabled = ternary_level; + dbg("'?' entered: evaluation_disabled=%u", math_state->evaluation_disabled); + } } } /* if */ /* else: LPAREN or UNARY: push it on opstack */ @@ -906,9 +907,15 @@ dbg(" numstack:%d val:%lld '%s'", (int)(numstackptr - numstack), numstackptr[ insert_op = 0xff; dbg("inserting %02x", op); if (op == TOK_CONDITIONAL_SEP) { - /* The next token is ":". Toggle "do not evaluate" bit */ - math_state->evaluation_disabled ^= 1; - dbg("':' entered: evaluation_disabled=%llx (negated)", EVAL_DISABLED); + /* The next token is ":". Toggle "do not evaluate" state */ + if (!math_state->evaluation_disabled) { + math_state->evaluation_disabled = ternary_level; + dbg("':' entered: evaluation_disabled=%u", math_state->evaluation_disabled); + } else if (ternary_level == math_state->evaluation_disabled) { + math_state->evaluation_disabled = 0; + dbg("':' entered: evaluation_disabled=CLEAR"); + } /* else: ternary_level > nonzero evaluation_disabled: we are in nested ?:, in its disabled branch */ + /* do nothing */ } goto tok_found1; } diff --git a/shell/math.h b/shell/math.h index 9812184..4390318 100644 --- a/shell/math.h +++ b/shell/math.h @@ -57,7 +57,7 @@ typedef const char* FAST_FUNC (*arith_var_lookup_t)(const char *name); typedef void FAST_FUNC (*arith_var_set_t)(const char *name, const char *val); typedef struct arith_state_t { - uint64_t evaluation_disabled; + unsigned evaluation_disabled; const char *errmsg; void *list_of_recursed_names; arith_var_lookup_t lookupvar; |