shell/math.c: stop using bss variable

function                                             old     new   delta
evaluate_string                                        -     678    +678
expand_one_var                                      1543    1563     +20
builtin_type                                         114     116      +2
expand_and_evaluate_arith                             89      87      -2
prev_chk_var_recursive                                 4       -      -4
ash_arith                                            122     118      -4
arith_lookup_val                                     142     132     -10
arith                                                674      12    -662
------------------------------------------------------------------------------
(add/remove: 1/1 grow/shrink: 2/4 up/down: 700/-682)           Total: 18 bytes

Signed-off-by: Denys Vlasenko <dvlasenk@redhat.com>
diff --git a/shell/math.c b/shell/math.c
index 555559a..8397157 100644
--- a/shell/math.c
+++ b/shell/math.c
@@ -232,6 +232,7 @@
 	        || prec == PREC(TOK_CONDITIONAL));
 }
 
+
 typedef struct {
 	arith_t val;
 	arith_t contidional_second_val;
@@ -240,43 +241,49 @@
 			   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;
 
-			t->val = arith(math_state, p);
-			/* restore previous ptr after recursion */
-			prev_chk_var_recursive = cur;
+			/* recursively evaluate p as expression */
+			t->val = evaluate_string(math_state, p);
+
+			/* pop current var name */
+			math_state->list_of_recursed_names = cur;
+
 			return math_state->errcode;
 		}
-		/* allow undefined var as 0 */
+		/* treat undefined var as 0 */
 		t->val = 0;
 	}
 	return 0;
@@ -487,8 +494,8 @@
 	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 @@
 	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 9f3da7f..e34b65d 100644
--- a/shell/math.h
+++ b/shell/math.h
@@ -95,13 +95,14 @@
 //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