diff options
Diffstat (limited to 'shell')
-rw-r--r-- | shell/hush.c | 37 |
1 files changed, 19 insertions, 18 deletions
diff --git a/shell/hush.c b/shell/hush.c index ea259f5..2d4e3fa 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); } |