shell/math.c: stop using bss variable
authorDenys Vlasenko <dvlasenk@redhat.com>
Mon, 13 Sep 2010 10:49:52 +0000 (12:49 +0200)
committerDenys Vlasenko <dvlasenk@redhat.com>
Mon, 13 Sep 2010 10:49:52 +0000 (12:49 +0200)
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>
shell/math.c
shell/math.h

index 555559a26ced9a20b34ed481ca495e302198eb9f..839715776ad69dd0566aa7bc299b8f2b32a01cf3 100644 (file)
@@ -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.
index 9f3da7f59e86b1a4ebedea471aff4154f5151c3d..e34b65d5d70cd6b0b5393919506cd0f0abfa863f 100644 (file)
@@ -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