hush: shrink variable expansion code
authorDenys Vlasenko <vda.linux@googlemail.com>
Thu, 20 May 2010 14:27:42 +0000 (16:27 +0200)
committerDenys Vlasenko <vda.linux@googlemail.com>
Thu, 20 May 2010 14:27:42 +0000 (16:27 +0200)
function                                             old     new   delta
expand_vars_to_list                                 2164    2012    -152

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
shell/hush.c

index 8da9439c1d92768e948d321439322bb60b9aad93..824a5b52ed7396950021552d6162d1a8c6a674a1 100644 (file)
@@ -2568,35 +2568,33 @@ static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg, char
 #endif
                default: /* <SPECIAL_VAR_SYMBOL>varname<SPECIAL_VAR_SYMBOL> */
                case_default: {
-                       bool exp_len = false;
-                       bool exp_null = false;
                        char *var = arg;
+                       bool exp_len;
+                       char exp_op;
                        char exp_save = exp_save; /* for compiler */
-                       char exp_op = exp_op; /* for compiler */
+                       char *exp_saveptr = exp_saveptr; /* points to expansion operator */
                        char *exp_word = exp_word; /* for compiler */
-                       size_t exp_off = 0;
 
                        *p = '\0';
                        arg[0] = first_ch & 0x7f;
 
                        /* prepare for expansions */
+                       exp_len = false;
+                       exp_op = 0;
                        if (var[0] == '#') {
                                /* handle length expansion ${#var} */
                                exp_len = true;
                                ++var;
                        } else {
                                /* maybe handle parameter expansion */
-                               exp_off = strcspn(var, ":-=+?%#");
-                               if (!var[exp_off])
-                                       exp_off = 0;
-                               if (exp_off) {
-                                       exp_save = var[exp_off];
-                                       exp_null = exp_save == ':';
-                                       exp_word = var + exp_off;
-                                       if (exp_null)
-                                               ++exp_word;
+                               exp_saveptr = var + strcspn(var, ":-=+?%#");
+                               exp_save = *exp_saveptr;
+                               if (exp_save) {
+                                       exp_word = exp_saveptr;
+                                       if (exp_save == ':')
+                                               exp_word++;
                                        exp_op = *exp_word++;
-                                       var[exp_off] = '\0';
+                                       *exp_saveptr = '\0';
                                }
                        }
 
@@ -2615,7 +2613,7 @@ static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg, char
                                debug_printf_expand("expand: length of '%s' = ", val);
                                val = utoa(val ? strlen(val) : 0);
                                debug_printf_expand("%s\n", val);
-                       } else if (exp_off) {
+                       } else if (exp_op) {
                                if (exp_op == '%' || exp_op == '#') {
                                        if (val) {
                                                /* we need to do a pattern match */
@@ -2623,7 +2621,7 @@ static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg, char
                                                char *loc;
                                                scan_t scan = pick_scan(exp_op, *exp_word, &match_at_left);
                                                if (exp_op == *exp_word)        /* ## or %% */
-                                                       ++exp_word;
+                                                       exp_word++;
                                                val = dyn_val = xstrdup(val);
                                                loc = scan(dyn_val, exp_word, match_at_left);
                                                if (match_at_left) /* # or ## */
@@ -2631,13 +2629,14 @@ static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg, char
                                                else if (loc) /* % or %% and match was found */
                                                        *loc = '\0';
                                        }
-                               } else {
+                               } else { /* one of :-=+? */
+//TODO: handle ${VAR:N[:M]} here. N, M can be expressions similar to $((EXPR)): 2+2, 2+var etc
                                        /* we need to do an expansion */
-                                       int exp_test = (!val || (exp_null && !val[0]));
+                                       int exp_test = (!val || ((exp_save == ':') && !val[0]));
                                        if (exp_op == '+')
                                                exp_test = !exp_test;
                                        debug_printf_expand("expand: op:%c (null:%s) test:%i\n", exp_op,
-                                               exp_null ? "true" : "false", exp_test);
+                                               (exp_save == ':') ? "true" : "false", exp_test);
                                        if (exp_test) {
                                                if (exp_op == '?') {
 //TODO: how interactive bash aborts expansion mid-command?
@@ -2666,7 +2665,7 @@ static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg, char
                                        }
                                }
 
-                               var[exp_off] = exp_save;
+                               *exp_saveptr = exp_save;
                        }
 
                        arg[0] = first_ch;