summaryrefslogtreecommitdiff
path: root/shell
diff options
context:
space:
mode:
authorDenys Vlasenko2023-06-17 11:03:02 +0200
committerDenys Vlasenko2023-06-17 11:03:02 +0200
commit19a74a54ded98b28c672d38b79ea9f313f2d89db (patch)
tree41898bf80b1518438979d5e7c64787c73f766ba9 /shell
parent6221832bc15d9037360e3bdc9405df08ed801cc1 (diff)
downloadbusybox-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>
Diffstat (limited to 'shell')
-rw-r--r--shell/math.c33
-rw-r--r--shell/math.h2
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;