[git commit] hush: store "ended_in_ifs" flag in o_string

Denys Vlasenko vda.linux at googlemail.com
Fri Jul 20 14:27:26 UTC 2018


commit: https://git.busybox.net/busybox/commit/?id=168579a34c6fc6c2f2cd20256367ceb61f50bf68
branch: https://git.busybox.net/busybox/commit/?id=refs/heads/master

This simplifies function parameter passing.

function                                             old     new   delta
expand_one_var                                      1643    1639      -4
append_str_maybe_ifs_split                            64      52     -12
expand_vars_to_list                                 1125    1112     -13
expand_on_ifs                                        361     345     -16
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 0/4 up/down: 0/-45)             Total: -45 bytes

Signed-off-by: Denys Vlasenko <vda.linux at googlemail.com>
---
 shell/hush.c | 37 +++++++++++++++++++------------------
 1 file changed, 19 insertions(+), 18 deletions(-)

diff --git a/shell/hush.c b/shell/hush.c
index ea259f53c..2d4e3fa66 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -534,6 +534,7 @@ typedef struct o_string {
 	 * possibly empty one: word"", wo''rd etc. */
 	smallint has_quoted_part;
 	smallint has_empty_slot;
+	smallint ended_in_ifs;
 } o_string;
 enum {
 	EXP_FLAG_SINGLEWORD     = 0x80, /* must be 0x80 */
@@ -5643,10 +5644,10 @@ static void o_addblock_duplicate_backslash(o_string *o, const char *str, int len
 /* Store given string, finalizing the word and starting new one whenever
  * we encounter IFS char(s). This is used for expanding variable values.
  * End-of-string does NOT finalize word: think about 'echo -$VAR-'.
- * Return in *ended_with_ifs:
+ * Return in output->ended_in_ifs:
  * 1 - ended with IFS char, else 0 (this includes case of empty str).
  */
-static int expand_on_ifs(int *ended_with_ifs, o_string *output, int n, const char *str)
+static int expand_on_ifs(o_string *output, int n, const char *str)
 {
 	int last_is_ifs = 0;
 
@@ -5709,8 +5710,7 @@ static int expand_on_ifs(int *ended_with_ifs, o_string *output, int n, const cha
 		}
 	}
 
-	if (ended_with_ifs)
-		*ended_with_ifs = last_is_ifs;
+	output->ended_in_ifs = last_is_ifs;
 	debug_print_list("expand_on_ifs[1]", output, n);
 	return n;
 }
@@ -5955,14 +5955,14 @@ 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,
+static int append_str_maybe_ifs_split(o_string *output, 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);
+			n = expand_on_ifs(output, n, val);
 	} else { /* quoted "$VAR" */
 		output->has_quoted_part = 1;
 		debug_printf_expand("quoted '%s', output->o_escape:%d\n", val,
@@ -5977,7 +5977,7 @@ static int append_str_maybe_ifs_split(o_string *output, int *ended_in_ifs, int n
  * Handles <SPECIAL_VAR_SYMBOL>varname...<SPECIAL_VAR_SYMBOL> construct.
  */
 static NOINLINE int expand_one_var(o_string *output,
-	int *ended_in_ifs, int n, int first_ch, char *arg, char **pp)
+	int n, int first_ch, char *arg, char **pp)
 {
 	const char *val;
 	char *to_be_freed;
@@ -6242,9 +6242,9 @@ static NOINLINE int expand_one_var(o_string *output,
  * $ f() { for i; do echo "|$i|"; done; };
  *
  * $ x=; f ${x:?'x y' z}
- * bash: x: x y z
+ * bash: x: x y z              #BUG: does not abort, ${} results in empty expansion
  * $ x=; f "${x:?'x y' z}"
- * bash: x: x y z       # dash prints: dash: x: 'x y' z
+ * bash: x: x y z       # dash prints: dash: x: 'x y' z   #BUG: does not abort, ${} results in ""
  *
  * $ x=; f ${x:='x y' z}
  * |x|
@@ -6290,7 +6290,7 @@ static NOINLINE int expand_one_var(o_string *output,
 						/*: (exp_save == ':' ? "parameter null or not set" : "parameter not set")*/
 					);
 //TODO: how interactive bash aborts expansion mid-command?
-//It aborts the entire line:
+//It aborts the entire line, returns to prompt:
 // $ f() { for i; do echo "|$i|"; done; }; x=; f "${x:?'x y' z}"; echo YO
 // bash: x: x y z
 // $
@@ -6319,7 +6319,7 @@ static NOINLINE int expand_one_var(o_string *output,
 	arg[0] = arg0;
 	*pp = p;
 
-	n = append_str_maybe_ifs_split(output, ended_in_ifs, n, first_ch, val);
+	n = append_str_maybe_ifs_split(output, n, first_ch, val);
 
 	free(to_be_freed);
 	return n;
@@ -6336,9 +6336,10 @@ static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg)
 	 * expansion of right-hand side of assignment == 1-element expand.
 	 */
 	char cant_be_null = 0; /* only bit 0x80 matters */
-	int ended_in_ifs = 0;  /* did last unquoted expansion end with IFS chars? */
 	char *p;
 
+	output->ended_in_ifs = 0;  /* did last unquoted expansion end with IFS chars? */
+
 	debug_printf_expand("expand_vars_to_list: arg:'%s' singleword:%x\n", arg,
 			!!(output->o_expflags & EXP_FLAG_SINGLEWORD));
 	debug_print_list("expand_vars_to_list", output, n);
@@ -6352,10 +6353,10 @@ static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg)
 		char arith_buf[sizeof(arith_t)*3 + 2];
 #endif
 
-		if (ended_in_ifs) {
+		if (output->ended_in_ifs) {
 			o_addchr(output, '\0');
 			n = o_save_ptr(output, n);
-			ended_in_ifs = 0;
+			output->ended_in_ifs = 0;
 		}
 
 		o_addblock(output, arg, p - arg);
@@ -6386,7 +6387,7 @@ static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg)
 			cant_be_null |= first_ch; /* do it for "$@" _now_, when we know it's not empty */
 			if (!(first_ch & 0x80)) { /* unquoted $* or $@ */
 				while (G.global_argv[i]) {
-					n = expand_on_ifs(NULL, output, n, G.global_argv[i]);
+					n = expand_on_ifs(output, n, G.global_argv[i]);
 					debug_printf_expand("expand_vars_to_list: argv %d (last %d)\n", i, G.global_argc - 1);
 					if (G.global_argv[i++][0] && G.global_argv[i]) {
 						/* this argv[] is not empty and not last:
@@ -6447,7 +6448,7 @@ 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);
-			n = append_str_maybe_ifs_split(output, &ended_in_ifs, n, first_ch, subst_result.data);
+			n = append_str_maybe_ifs_split(output, n, first_ch, subst_result.data);
 			o_free_unsafe(&subst_result);
 			goto restore;
 		}
@@ -6467,7 +6468,7 @@ static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg)
 		}
 #endif
 		default:
-			n = expand_one_var(output, &ended_in_ifs, n, first_ch, arg, &p);
+			n = expand_one_var(output, n, first_ch, arg, &p);
 			goto restore;
 		} /* switch (char after <SPECIAL_VAR_SYMBOL>) */
 
@@ -6483,7 +6484,7 @@ static NOINLINE int expand_vars_to_list(o_string *output, int n, char *arg)
 	} /* end of "while (SPECIAL_VAR_SYMBOL is found) ..." */
 
 	if (arg[0]) {
-		if (ended_in_ifs) {
+		if (output->ended_in_ifs) {
 			o_addchr(output, '\0');
 			n = o_save_ptr(output, n);
 		}


More information about the busybox-cvs mailing list