summaryrefslogtreecommitdiff
path: root/shell
diff options
context:
space:
mode:
authorDenys Vlasenko2023-06-15 13:56:12 +0200
committerDenys Vlasenko2023-06-15 13:56:12 +0200
commitea6dcbe2839fb21049baadd0d5da903ae11661ec (patch)
tree66408551d3fdb6957e1ced4951c23b5f24226965 /shell
parent22cb0d573a5cabd24fa648f1a13c22acf661a4a3 (diff)
downloadbusybox-ea6dcbe2839fb21049baadd0d5da903ae11661ec.zip
busybox-ea6dcbe2839fb21049baadd0d5da903ae11661ec.tar.gz
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>
Diffstat (limited to 'shell')
-rw-r--r--shell/hush_test/hush-arith/arith-assign-in-varexp1.right2
-rwxr-xr-xshell/hush_test/hush-arith/arith-assign-in-varexp1.tests9
-rw-r--r--shell/math.c49
3 files changed, 26 insertions, 34 deletions
diff --git a/shell/hush_test/hush-arith/arith-assign-in-varexp1.right b/shell/hush_test/hush-arith/arith-assign-in-varexp1.right
new file mode 100644
index 0000000..1feb307
--- /dev/null
+++ b/shell/hush_test/hush-arith/arith-assign-in-varexp1.right
@@ -0,0 +1,2 @@
+7:7
+x=3
diff --git a/shell/hush_test/hush-arith/arith-assign-in-varexp1.tests b/shell/hush_test/hush-arith/arith-assign-in-varexp1.tests
new file mode 100755
index 0000000..fc8ac9d
--- /dev/null
+++ b/shell/hush_test/hush-arith/arith-assign-in-varexp1.tests
@@ -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"
diff --git a/shell/math.c b/shell/math.c
index 8d0c9de..7e2bf5e 100644
--- a/shell/math.c
+++ b/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;