From 116b50a5c1ea9d80d60641f2df2b61473b57fe47 Mon Sep 17 00:00:00 2001
From: Denys Vlasenko <vda.linux@googlemail.com>
Date: Thu, 19 Jul 2018 11:16:53 +0200
Subject: hush: make expand_vars_to_list() a bit more sane

function                                             old     new   delta
append_str_maybe_ifs_split                             -      64     +64
expand_vars_to_list                                 1167    1139     -28
------------------------------------------------------------------------------
(add/remove: 1/0 grow/shrink: 0/1 up/down: 64/-28)             Total: 36 bytes

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
---
 shell/hush.c | 60 ++++++++++++++++++++++++++++++++----------------------------
 1 file changed, 32 insertions(+), 28 deletions(-)

diff --git a/shell/hush.c b/shell/hush.c
index 92c79b8b6..b738d2fd8 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -5955,6 +5955,24 @@ static char *replace_pattern(char *val, const char *pattern, const char *repl, c
 }
 #endif /* BASH_PATTERN_SUBST */
 
+static int append_str_maybe_ifs_split(o_string *output, int *ended_in_ifs, int n,
+	int first_ch, const char *val)
+{
+	if (!(first_ch & 0x80)) { /* unquoted $VAR */
+		debug_printf_expand("unquoted '%s', output->o_escape:%d\n", val,
+				!!(output->o_expflags & EXP_FLAG_ESC_GLOB_CHARS));
+		if (val && val[0])
+			n = expand_on_ifs(ended_in_ifs, output, n, val);
+	} else { /* quoted "$VAR" */
+		output->has_quoted_part = 1;
+		debug_printf_expand("quoted '%s', output->o_escape:%d\n", val,
+				!!(output->o_expflags & EXP_FLAG_ESC_GLOB_CHARS));
+		if (val && val[0])
+			o_addQstr(output, val);
+	}
+	return n;
+}
+
 /* Helper:
  * Handles <SPECIAL_VAR_SYMBOL>varname...<SPECIAL_VAR_SYMBOL> construct.
  */
@@ -6290,11 +6308,7 @@ static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg)
 
 	while ((p = strchr(arg, SPECIAL_VAR_SYMBOL)) != NULL) {
 		char first_ch;
-		char *to_be_freed = NULL;
 		const char *val = NULL;
-#if ENABLE_HUSH_TICK
-		o_string subst_result = NULL_O_STRING;
-#endif
 #if ENABLE_FEATURE_SH_MATH
 		char arith_buf[sizeof(arith_t)*3 + 2];
 #endif
@@ -6382,7 +6396,9 @@ static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg)
 			val = SPECIAL_VAR_SYMBOL_STR;
 			break;
 #if ENABLE_HUSH_TICK
-		case '`': /* <SPECIAL_VAR_SYMBOL>`cmd<SPECIAL_VAR_SYMBOL> */
+		case '`': { /* <SPECIAL_VAR_SYMBOL>`cmd<SPECIAL_VAR_SYMBOL> */
+			o_string subst_result = NULL_O_STRING;
+
 			*p = '\0'; /* replace trailing <SPECIAL_VAR_SYMBOL> */
 			arg++;
 			/* Can't just stuff it into output o_string,
@@ -6392,8 +6408,10 @@ static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg)
 			G.last_exitcode = process_command_subs(&subst_result, arg);
 			G.expand_exitcode = G.last_exitcode;
 			debug_printf_subst("SUBST RES:%d '%s'\n", G.last_exitcode, subst_result.data);
-			val = subst_result.data;
-			goto store_val;
+			n = append_str_maybe_ifs_split(output, &ended_in_ifs, n, first_ch, subst_result.data);
+			o_free_unsafe(&subst_result);
+			goto restore;
+		}
 #endif
 #if ENABLE_FEATURE_SH_MATH
 		case '+': { /* <SPECIAL_VAR_SYMBOL>+cmd<SPECIAL_VAR_SYMBOL> */
@@ -6409,37 +6427,23 @@ static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg)
 			break;
 		}
 #endif
-		default:
+		default: {
+			char *to_be_freed;
 			val = expand_one_var(&to_be_freed, arg, &p);
- IF_HUSH_TICK(store_val:)
-			if (!(first_ch & 0x80)) { /* unquoted $VAR */
-				debug_printf_expand("unquoted '%s', output->o_escape:%d\n", val,
-						!!(output->o_expflags & EXP_FLAG_ESC_GLOB_CHARS));
-				if (val && val[0]) {
-					n = expand_on_ifs(&ended_in_ifs, output, n, val);
-					val = NULL;
-				}
-			} else { /* quoted $VAR, val will be appended below */
-				output->has_quoted_part = 1;
-				debug_printf_expand("quoted '%s', output->o_escape:%d\n", val,
-						!!(output->o_expflags & EXP_FLAG_ESC_GLOB_CHARS));
-			}
-			break;
+			n = append_str_maybe_ifs_split(output, &ended_in_ifs, n, first_ch, val);
+			free(to_be_freed);
+			goto restore;
+		} /* default: */
 		} /* switch (char after <SPECIAL_VAR_SYMBOL>) */
 
 		if (val && val[0]) {
 			o_addQstr(output, val);
 		}
-		free(to_be_freed);
-
+ restore:
 		/* Restore NULL'ed SPECIAL_VAR_SYMBOL.
 		 * Do the check to avoid writing to a const string. */
 		if (*p != SPECIAL_VAR_SYMBOL)
 			*p = SPECIAL_VAR_SYMBOL;
-
-#if ENABLE_HUSH_TICK
-		o_free(&subst_result);
-#endif
 		arg = ++p;
 	} /* end of "while (SPECIAL_VAR_SYMBOL is found) ..." */
 
-- 
cgit v1.2.3-55-g6feb