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>
This commit is contained in:
parent
6221832bc1
commit
19a74a54de
2 changed files with 21 additions and 14 deletions
33
shell/math.c
33
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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue