summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--shell/math.c54
-rw-r--r--shell/math.h5
2 files changed, 37 insertions, 22 deletions
diff --git a/shell/math.c b/shell/math.c
index 555559a26..839715776 100644
--- a/shell/math.c
+++ b/shell/math.c
@@ -232,6 +232,7 @@ is_right_associative(operator prec)
|| prec == PREC(TOK_CONDITIONAL));
}
+
typedef struct {
arith_t val;
arith_t contidional_second_val;
@@ -240,43 +241,49 @@ typedef struct {
else is variable name */
} v_n_t;
-typedef struct chk_var_recursive_looped_t {
+typedef struct remembered_name {
+ struct remembered_name *next;
const char *var;
- struct chk_var_recursive_looped_t *next;
-} chk_var_recursive_looped_t;
+} remembered_name;
+
-static chk_var_recursive_looped_t *prev_chk_var_recursive;
+static arith_t FAST_FUNC
+evaluate_string(arith_state_t *math_state, const char *expr);
static int
arith_lookup_val(arith_state_t *math_state, v_n_t *t)
{
if (t->var) {
const char *p = lookupvar(t->var);
-
if (p) {
- chk_var_recursive_looped_t *cur;
- chk_var_recursive_looped_t cur_save;
+ remembered_name *cur;
+ remembered_name cur_save;
- /* recursively try p as expression */
-
- for (cur = prev_chk_var_recursive; cur; cur = cur->next) {
+ /* did we already see this name?
+ * testcase: a=b; b=a; echo $((a))
+ */
+ for (cur = math_state->list_of_recursed_names; cur; cur = cur->next) {
if (strcmp(cur->var, t->var) == 0) {
- /* expression recursion loop detected */
+ /* Yes. Expression recursion loop detected */
return -5;
}
}
- /* save current var name */
- cur = prev_chk_var_recursive;
+
+ /* push current var name */
+ cur = math_state->list_of_recursed_names;
cur_save.var = t->var;
cur_save.next = cur;
- prev_chk_var_recursive = &cur_save;
+ math_state->list_of_recursed_names = &cur_save;
+
+ /* recursively evaluate p as expression */
+ t->val = evaluate_string(math_state, p);
+
+ /* pop current var name */
+ math_state->list_of_recursed_names = cur;
- t->val = arith(math_state, p);
- /* restore previous ptr after recursion */
- prev_chk_var_recursive = cur;
return math_state->errcode;
}
- /* allow undefined var as 0 */
+ /* treat undefined var as 0 */
t->val = 0;
}
return 0;
@@ -487,8 +494,8 @@ endofname(const char *name)
return name;
}
-arith_t
-arith(arith_state_t *math_state, const char *expr)
+static arith_t FAST_FUNC
+evaluate_string(arith_state_t *math_state, const char *expr)
{
operator lasttok;
int errcode;
@@ -677,6 +684,13 @@ arith(arith_state_t *math_state, const char *expr)
return numstack->val;
}
+arith_t FAST_FUNC
+arith(arith_state_t *math_state, const char *expr)
+{
+ math_state->list_of_recursed_names = NULL;
+ return evaluate_string(math_state, expr);
+}
+
/*
* Copyright (c) 1989, 1991, 1993, 1994
* The Regents of the University of California. All rights reserved.
diff --git a/shell/math.h b/shell/math.h
index 9f3da7f59..e34b65d5d 100644
--- a/shell/math.h
+++ b/shell/math.h
@@ -95,13 +95,14 @@ typedef void FAST_FUNC (*arith_var_set_t)(const char *name, const char *v
//typedef const char* FAST_FUNC (*arith_var_endofname_t)(const char *name);
typedef struct arith_state_t {
+ int errcode;
arith_var_lookup_t lookupvar;
arith_var_set_t setvar;
// arith_var_endofname_t endofname;
- int errcode;
+ void *list_of_recursed_names;
} arith_state_t;
-arith_t arith(arith_state_t *state, const char *expr);
+arith_t FAST_FUNC arith(arith_state_t *state, const char *expr);
POP_SAVED_FUNCTION_VISIBILITY