hush: speed up ${var:+ARG} for literal ARGs
authorDenys Vlasenko <vda.linux@googlemail.com>
Tue, 31 Jul 2018 08:36:29 +0000 (10:36 +0200)
committerDenys Vlasenko <vda.linux@googlemail.com>
Tue, 31 Jul 2018 08:36:29 +0000 (10:36 +0200)
function                                             old     new   delta
first_special_char_in_vararg                           -      52     +52
expand_one_var                                      2248    2296     +48
encode_then_expand_vararg                            357     336     -21
------------------------------------------------------------------------------
(add/remove: 1/0 grow/shrink: 1/1 up/down: 100/-21)            Total: 79 bytes

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

index d17f7f29e966f25e5360bba5d5ba097ccc4f86e5..6852b5f79ce1bb24fd3c14d45a0797e2a9b02832 100644 (file)
@@ -5913,6 +5913,26 @@ static char *encode_then_expand_string(const char *str)
        return exp_str;
 }
 
+static const char *first_special_char_in_vararg(const char *cp)
+{
+       for (;;) {
+               if (!*cp) return NULL; /* string has no special chars */
+               if (*cp == '$') return cp;
+               if (*cp == '\\') return cp;
+               if (*cp == '\'') return cp;
+               if (*cp == '"') return cp;
+#if ENABLE_HUSH_TICK
+               if (*cp == '`') return cp;
+#endif
+               /* dquoted "${x:+ARG}" should not glob, therefore
+                * '*' et al require some non-literal processing: */
+               if (*cp == '*') return cp;
+               if (*cp == '?') return cp;
+               if (*cp == '[') return cp;
+               cp++;
+       }
+}
+
 /* Expanding ARG in ${var#ARG}, ${var%ARG}, or ${var/ARG/ARG}.
  * These can contain single- and double-quoted strings,
  * and treated as if the ARG string is initially unquoted. IOW:
@@ -5932,19 +5952,10 @@ static char *encode_then_expand_vararg(const char *str, int handle_squotes, int
        char *exp_str;
        struct in_str input;
        o_string dest = NULL_O_STRING;
-       const char *cp;
 
-       cp = str;
-       for (;;) {
-               if (!*cp) return NULL; /* string has no special chars */
-               if (*cp == '$') break;
-               if (*cp == '\\') break;
-               if (*cp == '\'') break;
-               if (*cp == '"') break;
-#if ENABLE_HUSH_TICK
-               if (*cp == '`') break;
-#endif
-               cp++;
+       if (!first_special_char_in_vararg(str)) {
+               /* string has no special chars */
+               return NULL;
        }
 
        setup_string_in_str(&input, str);
@@ -6025,26 +6036,19 @@ static char *encode_then_expand_vararg(const char *str, int handle_squotes, int
 /* Expanding ARG in ${var+ARG}, ${var-ARG}
  */
 static int encode_then_append_var_plusminus(o_string *output, int n,
-               const char *str, int dquoted)
+               char *str, int dquoted)
 {
        struct in_str input;
        o_string dest = NULL_O_STRING;
 
-#if 0 //todo?
-       const char *cp;
-       cp = str;
-       for (;;) {
-               if (!*cp) return NULL; /* string has no special chars */
-               if (*cp == '$') break;
-               if (*cp == '\\') break;
-               if (*cp == '\'') break;
-               if (*cp == '"') break;
-#if ENABLE_HUSH_TICK
-               if (*cp == '`') break;
-#endif
-               cp++;
+       if (!first_special_char_in_vararg(str)
+        && '\0' == str[strcspn(str, G.ifs)]
+       ) {
+               /* string has no special chars
+                * && string has no $IFS chars
+                */
+               return expand_vars_to_list(output, n, str);
        }
-#endif
 
        setup_string_in_str(&input, str);