shell/math: change ?: nesting code to not have 63 level nesting limitation
No binary (build failed)
—
(log yok)
| @@ -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; | |
| } | |
| @@ -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; | |