aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2023-06-17 11:03:02 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2023-06-17 11:03:02 +0200
commit19a74a54ded98b28c672d38b79ea9f313f2d89db (patch)
tree41898bf80b1518438979d5e7c64787c73f766ba9
parent6221832bc15d9037360e3bdc9405df08ed801cc1 (diff)
downloadbusybox-w32-19a74a54ded98b28c672d38b79ea9f313f2d89db.tar.gz
busybox-w32-19a74a54ded98b28c672d38b79ea9f313f2d89db.tar.bz2
busybox-w32-19a74a54ded98b28c672d38b79ea9f313f2d89db.zip
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.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 6196a6ad9..3e339a5ec 100644
--- a/shell/math.c
+++ b/shell/math.c
@@ -599,8 +599,6 @@ static arith_t strto_arith_t(const char *nptr, char **endptr)
599static arith_t 599static arith_t
600evaluate_string(arith_state_t *math_state, const char *expr) 600evaluate_string(arith_state_t *math_state, const char *expr)
601{ 601{
602#define EVAL_DISABLED ((unsigned long long)math_state->evaluation_disabled)
603#define TOP_BIT_ULL ((unsigned long long)LLONG_MAX + 1)
604 operator lasttok; 602 operator lasttok;
605 const char *errmsg = NULL; 603 const char *errmsg = NULL;
606 const char *start_expr = expr = skip_whitespace(expr); 604 const char *start_expr = expr = skip_whitespace(expr);
@@ -617,6 +615,7 @@ evaluate_string(arith_state_t *math_state, const char *expr)
617 operator *const opstack = alloca(expr_len * sizeof(opstack[0])); 615 operator *const opstack = alloca(expr_len * sizeof(opstack[0]));
618 operator *opstackptr = opstack; 616 operator *opstackptr = opstack;
619 operator insert_op = 0xff; 617 operator insert_op = 0xff;
618 unsigned ternary_level = 0;
620 619
621 /* Start with a left paren */ 620 /* Start with a left paren */
622 dbg("(%d) op:TOK_LPAREN", (int)(opstackptr - opstack)); 621 dbg("(%d) op:TOK_LPAREN", (int)(opstackptr - opstack));
@@ -875,8 +874,11 @@ dbg(" numstack:%d val:%lld '%s'", (int)(numstackptr - numstack), numstackptr[
875 /* Example: a=1?2:3,a. We just executed ":". 874 /* Example: a=1?2:3,a. We just executed ":".
876 * Prevent assignment from being still disabled. 875 * Prevent assignment from being still disabled.
877 */ 876 */
878 math_state->evaluation_disabled >>= 1; 877 if (ternary_level == math_state->evaluation_disabled) {
879 dbg("':' executed: evaluation_disabled=%llx (restored)", EVAL_DISABLED); 878 math_state->evaluation_disabled = 0;
879 dbg("':' executed: evaluation_disabled=CLEAR");
880 }
881 ternary_level--;
880 } 882 }
881 } /* while (opstack not empty) */ 883 } /* while (opstack not empty) */
882 884
@@ -887,12 +889,11 @@ dbg(" numstack:%d val:%lld '%s'", (int)(numstackptr - numstack), numstackptr[
887 /* We just now evaluated EXPR before "?". 889 /* We just now evaluated EXPR before "?".
888 * Should we disable evaluation now? 890 * Should we disable evaluation now?
889 */ 891 */
890 if (math_state->evaluation_disabled & TOP_BIT_ULL) 892 ternary_level++;
891 goto err; /* >63 levels of ?: nesting not supported */ 893 if (numstackptr[-1].val == 0 && !math_state->evaluation_disabled) {
892 math_state->evaluation_disabled = 894 math_state->evaluation_disabled = ternary_level;
893 (math_state->evaluation_disabled << 1) 895 dbg("'?' entered: evaluation_disabled=%u", math_state->evaluation_disabled);
894 | (numstackptr[-1].val == 0); 896 }
895 dbg("'?' entered: evaluation_disabled=%llx", EVAL_DISABLED);
896 } 897 }
897 } /* if */ 898 } /* if */
898 /* else: LPAREN or UNARY: push it on opstack */ 899 /* else: LPAREN or UNARY: push it on opstack */
@@ -906,9 +907,15 @@ dbg(" numstack:%d val:%lld '%s'", (int)(numstackptr - numstack), numstackptr[
906 insert_op = 0xff; 907 insert_op = 0xff;
907 dbg("inserting %02x", op); 908 dbg("inserting %02x", op);
908 if (op == TOK_CONDITIONAL_SEP) { 909 if (op == TOK_CONDITIONAL_SEP) {
909 /* The next token is ":". Toggle "do not evaluate" bit */ 910 /* The next token is ":". Toggle "do not evaluate" state */
910 math_state->evaluation_disabled ^= 1; 911 if (!math_state->evaluation_disabled) {
911 dbg("':' entered: evaluation_disabled=%llx (negated)", EVAL_DISABLED); 912 math_state->evaluation_disabled = ternary_level;
913 dbg("':' entered: evaluation_disabled=%u", math_state->evaluation_disabled);
914 } else if (ternary_level == math_state->evaluation_disabled) {
915 math_state->evaluation_disabled = 0;
916 dbg("':' entered: evaluation_disabled=CLEAR");
917 } /* else: ternary_level > nonzero evaluation_disabled: we are in nested ?:, in its disabled branch */
918 /* do nothing */
912 } 919 }
913 goto tok_found1; 920 goto tok_found1;
914 } 921 }
diff --git a/shell/math.h b/shell/math.h
index 9812184f1..439031828 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);
57typedef void FAST_FUNC (*arith_var_set_t)(const char *name, const char *val); 57typedef void FAST_FUNC (*arith_var_set_t)(const char *name, const char *val);
58 58
59typedef struct arith_state_t { 59typedef struct arith_state_t {
60 uint64_t evaluation_disabled; 60 unsigned evaluation_disabled;
61 const char *errmsg; 61 const char *errmsg;
62 void *list_of_recursed_names; 62 void *list_of_recursed_names;
63 arith_var_lookup_t lookupvar; 63 arith_var_lookup_t lookupvar;