mirror of https://github.com/mirror/busybox.git
shell/math: fix order of expansion of variables to numbers
This fixes arith-assign-in-varexp1.tests function old new delta evaluate_string 1132 1258 +126 arith_lookup_val 143 - -143 arith_apply 1132 977 -155 ------------------------------------------------------------------------------ (add/remove: 0/1 grow/shrink: 1/1 up/down: 126/-298) Total: -172 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>master
parent
22cb0d573a
commit
ea6dcbe283
|
@ -0,0 +1,2 @@
|
|||
7:7
|
||||
x=3
|
|
@ -0,0 +1,9 @@
|
|||
exec 2>&1
|
||||
a='x=1'
|
||||
b='x=2'
|
||||
c='x=3'
|
||||
# The variables should evaluate immediately when they encountered,
|
||||
# not when they go into an operation. Here, order of evaluation
|
||||
# of names to numbers should be a,b,c - not b,c,a:
|
||||
echo 7:$((a+b*c))
|
||||
echo "x=$x"
|
49
shell/math.c
49
shell/math.c
|
@ -310,7 +310,6 @@ arith_apply(arith_state_t *math_state, operator op, var_or_num_t *numstack, var_
|
|||
|
||||
var_or_num_t *top_of_stack;
|
||||
arith_t rez;
|
||||
const char *err;
|
||||
|
||||
/* There is no operator that can work without arguments */
|
||||
if (NUMPTR == numstack)
|
||||
|
@ -324,14 +323,8 @@ arith_apply(arith_state_t *math_state, operator op, var_or_num_t *numstack, var_
|
|||
NUMPTR = expr1 + 1;
|
||||
if (expr1 < numstack) /* Example: $((2:3)) */
|
||||
return "malformed ?: operator";
|
||||
err = arith_lookup_val(math_state, expr1);
|
||||
if (err)
|
||||
return err;
|
||||
if (expr1->val != 0) /* select expr2 or expr3 */
|
||||
top_of_stack--;
|
||||
err = arith_lookup_val(math_state, top_of_stack);
|
||||
if (err)
|
||||
return err;
|
||||
expr1->val = top_of_stack->val;
|
||||
expr1->var_name = NULL;
|
||||
return NULL;
|
||||
|
@ -339,24 +332,6 @@ arith_apply(arith_state_t *math_state, operator op, var_or_num_t *numstack, var_
|
|||
if (op == TOK_CONDITIONAL) /* Example: $((a ? b)) */
|
||||
return "malformed ?: operator";
|
||||
|
||||
if (PREC(op) < UNARYPREC) {
|
||||
/* In binops a ~ b, variables are resolved left-to-right,
|
||||
* resolve top_of_stack[-1] _before_ resolving top_of_stack[0]
|
||||
*/
|
||||
if (top_of_stack == numstack) /* need two arguments */
|
||||
goto syntax_err;
|
||||
/* Unless it is =, resolve top_of_stack[-1] name to value */
|
||||
if (op != TOK_ASSIGN) {
|
||||
err = arith_lookup_val(math_state, top_of_stack - 1);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
}
|
||||
/* Resolve top_of_stack[0] name to value */
|
||||
err = arith_lookup_val(math_state, top_of_stack);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
rez = top_of_stack->val;
|
||||
if (op == TOK_UMINUS)
|
||||
rez = -rez;
|
||||
|
@ -372,6 +347,9 @@ arith_apply(arith_state_t *math_state, operator op, var_or_num_t *numstack, var_
|
|||
/* Binary operators */
|
||||
arith_t right_side_val;
|
||||
|
||||
if (top_of_stack == numstack) /* have two arguments? */
|
||||
goto syntax_err; /* no */
|
||||
|
||||
/* Pop numstack */
|
||||
NUMPTR = top_of_stack; /* this decrements NUMPTR */
|
||||
top_of_stack--; /* now points to left side */
|
||||
|
@ -677,7 +655,16 @@ evaluate_string(arith_state_t *math_state, const char *expr)
|
|||
numstackptr->var_name = alloca(var_name_size);
|
||||
safe_strncpy(numstackptr->var_name, expr, var_name_size);
|
||||
dbg("[%d] var:'%s'", (int)(numstackptr - numstack), numstackptr->var_name);
|
||||
expr = p;
|
||||
expr = skip_whitespace(p);
|
||||
/* If it is not followed by "=" operator... */
|
||||
if (expr[0] != '=' /* not "=..." */
|
||||
|| expr[1] == '=' /* or "==..." */
|
||||
) {
|
||||
/* Evaluate variable to value */
|
||||
errmsg = arith_lookup_val(math_state, numstackptr);
|
||||
if (errmsg)
|
||||
goto err_with_custom_msg;
|
||||
}
|
||||
push_num:
|
||||
numstackptr++;
|
||||
lasttok = TOK_NUM;
|
||||
|
@ -819,14 +806,8 @@ evaluate_string(arith_state_t *math_state, const char *expr)
|
|||
operator prev_op = *--opstackptr;
|
||||
if (op == TOK_RPAREN) {
|
||||
if (prev_op == TOK_LPAREN) {
|
||||
if (VALID_NAME(numstackptr[-1].var_name)) {
|
||||
/* Expression is (var), lookup now */
|
||||
errmsg = arith_lookup_val(math_state, &numstackptr[-1]);
|
||||
if (errmsg)
|
||||
goto err_with_custom_msg;
|
||||
/* Erase var name: (var) is just a number, for example, (var) = 1 is not valid */
|
||||
numstackptr[-1].var_name = NULL;
|
||||
}
|
||||
/* Erase var name: (var) is just a number, for example, (var) = 1 is not valid */
|
||||
numstackptr[-1].var_name = NULL;
|
||||
/* Any operator directly after a
|
||||
* close paren should consider itself binary */
|
||||
lasttok = TOK_NUM;
|
||||
|
|
Loading…
Reference in New Issue