diff options
author | Denys Vlasenko <dvlasenk@redhat.com> | 2010-09-10 10:17:53 +0200 |
---|---|---|
committer | Denys Vlasenko <dvlasenk@redhat.com> | 2010-09-10 10:17:53 +0200 |
commit | ebee410fe2500d6bd5980032d0b183494f509c9b (patch) | |
tree | 7d51a849f343d4b3437714aea40f7efaf6ef4050 | |
parent | 14e289b3246b4266499ffc5747dcc5c98bdaf5b9 (diff) | |
download | busybox-w32-ebee410fe2500d6bd5980032d0b183494f509c9b.tar.gz busybox-w32-ebee410fe2500d6bd5980032d0b183494f509c9b.tar.bz2 busybox-w32-ebee410fe2500d6bd5980032d0b183494f509c9b.zip |
hush: fix var_bash5.tests failure
function old new delta
expand_one_var 1513 1552 +39
expand_pseudo_dquoted 118 135 +17
expand_string_to_string 110 126 +16
setup_heredoc 298 308 +10
expand_and_evaluate_arith 69 79 +10
parse_stream_dquoted 233 241 +8
setup_redirects 220 225 +5
run_list 956 961 +5
expand_assignments 76 81 +5
run_pipe 1587 1590 +3
parse_stream 2371 2374 +3
builtin_umask 132 133 +1
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 12/0 up/down: 122/0) Total: 122 bytes
Signed-off-by: Denys Vlasenko <dvlasenk@redhat.com>
-rw-r--r-- | shell/hush.c | 43 | ||||
-rw-r--r-- | shell/hush_test/hush-vars/var_bash5.right | 13 | ||||
-rwxr-xr-x | shell/hush_test/hush-vars/var_bash5.tests | 24 |
3 files changed, 54 insertions, 26 deletions
diff --git a/shell/hush.c b/shell/hush.c index 942e72ad0..f49a39b0f 100644 --- a/shell/hush.c +++ b/shell/hush.c | |||
@@ -4335,7 +4335,7 @@ static struct pipe *parse_stream(char **pstring, | |||
4335 | /*** Execution routines ***/ | 4335 | /*** Execution routines ***/ |
4336 | 4336 | ||
4337 | /* Expansion can recurse, need forward decls: */ | 4337 | /* Expansion can recurse, need forward decls: */ |
4338 | static char *expand_string_to_string(const char *str); | 4338 | static char *expand_string_to_string(const char *str, int do_unbackslash); |
4339 | static int process_command_subs(o_string *dest, const char *s); | 4339 | static int process_command_subs(o_string *dest, const char *s); |
4340 | 4340 | ||
4341 | /* expand_strvec_to_strvec() takes a list of strings, expands | 4341 | /* expand_strvec_to_strvec() takes a list of strings, expands |
@@ -4387,7 +4387,7 @@ static int expand_on_ifs(o_string *output, int n, const char *str) | |||
4387 | * Returns malloced string. | 4387 | * Returns malloced string. |
4388 | * As an optimization, we return NULL if expansion is not needed. | 4388 | * As an optimization, we return NULL if expansion is not needed. |
4389 | */ | 4389 | */ |
4390 | static char *expand_pseudo_dquoted(const char *str, int dquoted) | 4390 | static char *expand_pseudo_dquoted(const char *str, int dquoted, int do_unbackslash) |
4391 | { | 4391 | { |
4392 | char *exp_str; | 4392 | char *exp_str; |
4393 | struct in_str input; | 4393 | struct in_str input; |
@@ -4408,7 +4408,7 @@ static char *expand_pseudo_dquoted(const char *str, int dquoted) | |||
4408 | setup_string_in_str(&input, str); | 4408 | setup_string_in_str(&input, str); |
4409 | parse_stream_dquoted(NULL, &dest, &input, EOF, dquoted); | 4409 | parse_stream_dquoted(NULL, &dest, &input, EOF, dquoted); |
4410 | //bb_error_msg("'%s' -> '%s'", str, dest.data); | 4410 | //bb_error_msg("'%s' -> '%s'", str, dest.data); |
4411 | exp_str = expand_string_to_string(dest.data); | 4411 | exp_str = expand_string_to_string(dest.data, /*unbackslash:*/ do_unbackslash); |
4412 | //bb_error_msg("'%s' -> '%s'", dest.data, exp_str); | 4412 | //bb_error_msg("'%s' -> '%s'", dest.data, exp_str); |
4413 | o_free_unsafe(&dest); | 4413 | o_free_unsafe(&dest); |
4414 | return exp_str; | 4414 | return exp_str; |
@@ -4424,7 +4424,7 @@ static arith_t expand_and_evaluate_arith(const char *arg, int *errcode_p) | |||
4424 | hooks.lookupvar = get_local_var_value; | 4424 | hooks.lookupvar = get_local_var_value; |
4425 | hooks.setvar = set_local_var_from_halves; | 4425 | hooks.setvar = set_local_var_from_halves; |
4426 | //hooks.endofname = endofname; | 4426 | //hooks.endofname = endofname; |
4427 | exp_str = expand_pseudo_dquoted(arg, /*dquoted:*/ 1); | 4427 | exp_str = expand_pseudo_dquoted(arg, /*dquoted:*/ 1, /*unbackslash:*/ 1); |
4428 | res = arith(exp_str ? exp_str : arg, errcode_p, &hooks); | 4428 | res = arith(exp_str ? exp_str : arg, errcode_p, &hooks); |
4429 | free(exp_str); | 4429 | free(exp_str); |
4430 | return res; | 4430 | return res; |
@@ -4594,8 +4594,7 @@ static NOINLINE const char *expand_one_var(char **to_be_freed_pp, char *arg, cha | |||
4594 | //TODO: avoid xstrdup unless needed | 4594 | //TODO: avoid xstrdup unless needed |
4595 | // (see HACK ALERT below for an example) | 4595 | // (see HACK ALERT below for an example) |
4596 | val = to_be_freed = xstrdup(val); | 4596 | val = to_be_freed = xstrdup(val); |
4597 | //TODO: fix expansion rules: | 4597 | exp_exp_word = expand_pseudo_dquoted(exp_word, /*dquoted:*/ 1, /*unbackslash:*/ 1); |
4598 | exp_exp_word = expand_pseudo_dquoted(exp_word, /*dquoted:*/ 1); | ||
4599 | if (exp_exp_word) | 4598 | if (exp_exp_word) |
4600 | exp_word = exp_exp_word; | 4599 | exp_word = exp_exp_word; |
4601 | loc = scan_and_match(to_be_freed, exp_word, scan_flags); | 4600 | loc = scan_and_match(to_be_freed, exp_word, scan_flags); |
@@ -4631,9 +4630,8 @@ static NOINLINE const char *expand_one_var(char **to_be_freed_pp, char *arg, cha | |||
4631 | * v='a bz'; echo ${v/a*z/\z} prints "z" | 4630 | * v='a bz'; echo ${v/a*z/\z} prints "z" |
4632 | * (note that a*z _pattern_ is never globbed!) | 4631 | * (note that a*z _pattern_ is never globbed!) |
4633 | */ | 4632 | */ |
4634 | //TODO: fix expansion rules: | ||
4635 | char *pattern, *repl, *t; | 4633 | char *pattern, *repl, *t; |
4636 | pattern = expand_pseudo_dquoted(exp_word, /*dquoted:*/ 1); | 4634 | pattern = expand_pseudo_dquoted(exp_word, /*dquoted:*/ 0, /*unbackslash:*/ 0); |
4637 | if (!pattern) | 4635 | if (!pattern) |
4638 | pattern = xstrdup(exp_word); | 4636 | pattern = xstrdup(exp_word); |
4639 | debug_printf_varexp("pattern:'%s'->'%s'\n", exp_word, pattern); | 4637 | debug_printf_varexp("pattern:'%s'->'%s'\n", exp_word, pattern); |
@@ -4641,7 +4639,7 @@ static NOINLINE const char *expand_one_var(char **to_be_freed_pp, char *arg, cha | |||
4641 | exp_word = p; | 4639 | exp_word = p; |
4642 | p = strchr(p, SPECIAL_VAR_SYMBOL); | 4640 | p = strchr(p, SPECIAL_VAR_SYMBOL); |
4643 | *p = '\0'; | 4641 | *p = '\0'; |
4644 | repl = expand_pseudo_dquoted(exp_word, /*dquoted:*/ arg0 & 0x80); | 4642 | repl = expand_pseudo_dquoted(exp_word, /*dquoted:*/ arg0 & 0x80, /*unbackslash:*/ 1); |
4645 | debug_printf_varexp("repl:'%s'->'%s'\n", exp_word, repl); | 4643 | debug_printf_varexp("repl:'%s'->'%s'\n", exp_word, repl); |
4646 | /* HACK ALERT. We depend here on the fact that | 4644 | /* HACK ALERT. We depend here on the fact that |
4647 | * G.global_argv and results of utoa and get_local_var_value | 4645 | * G.global_argv and results of utoa and get_local_var_value |
@@ -4726,7 +4724,7 @@ static NOINLINE const char *expand_one_var(char **to_be_freed_pp, char *arg, cha | |||
4726 | debug_printf_expand("expand: op:%c (null:%s) test:%i\n", exp_op, | 4724 | debug_printf_expand("expand: op:%c (null:%s) test:%i\n", exp_op, |
4727 | (exp_save == ':') ? "true" : "false", use_word); | 4725 | (exp_save == ':') ? "true" : "false", use_word); |
4728 | if (use_word) { | 4726 | if (use_word) { |
4729 | to_be_freed = expand_pseudo_dquoted(exp_word, /*dquoted:*/ 1); | 4727 | to_be_freed = expand_pseudo_dquoted(exp_word, /*dquoted:*/ 1, /*unbackslash:*/ 1); |
4730 | if (to_be_freed) | 4728 | if (to_be_freed) |
4731 | exp_word = to_be_freed; | 4729 | exp_word = to_be_freed; |
4732 | if (exp_op == '?') { | 4730 | if (exp_op == '?') { |
@@ -4998,30 +4996,35 @@ static char **expand_strvec_to_strvec_singleword_noglob(char **argv) | |||
4998 | * NB: should NOT do globbing! | 4996 | * NB: should NOT do globbing! |
4999 | * "export v=/bin/c*; env | grep ^v=" outputs "v=/bin/c*" | 4997 | * "export v=/bin/c*; env | grep ^v=" outputs "v=/bin/c*" |
5000 | */ | 4998 | */ |
5001 | static char *expand_string_to_string(const char *str) | 4999 | static char *expand_string_to_string(const char *str, int do_unbackslash) |
5002 | { | 5000 | { |
5003 | char *argv[2], **list; | 5001 | char *argv[2], **list; |
5004 | 5002 | ||
5003 | debug_printf_expand("string_to_string<='%s'\n", str); | ||
5005 | /* This is generally an optimization, but it also | 5004 | /* This is generally an optimization, but it also |
5006 | * handles "", which otherwise trips over !list[0] check below. | 5005 | * handles "", which otherwise trips over !list[0] check below. |
5007 | * (is this ever happens that we actually get str="" here?) | 5006 | * (is this ever happens that we actually get str="" here?) |
5008 | */ | 5007 | */ |
5009 | if (!strchr(str, SPECIAL_VAR_SYMBOL) && !strchr(str, '\\')) { | 5008 | if (!strchr(str, SPECIAL_VAR_SYMBOL) && !strchr(str, '\\')) { |
5010 | //TODO: Can use on strings with \ too, just unbackslash() them? | 5009 | //TODO: Can use on strings with \ too, just unbackslash() them? |
5011 | debug_printf_expand("string_to_string(fast)='%s'\n", str); | 5010 | debug_printf_expand("string_to_string(fast)=>'%s'\n", str); |
5012 | return xstrdup(str); | 5011 | return xstrdup(str); |
5013 | } | 5012 | } |
5014 | 5013 | ||
5015 | argv[0] = (char*)str; | 5014 | argv[0] = (char*)str; |
5016 | argv[1] = NULL; | 5015 | argv[1] = NULL; |
5017 | list = expand_variables(argv, EXP_FLAG_ESC_GLOB_CHARS | EXP_FLAG_SINGLEWORD); | 5016 | list = expand_variables(argv, do_unbackslash |
5017 | ? EXP_FLAG_ESC_GLOB_CHARS | EXP_FLAG_SINGLEWORD | ||
5018 | : EXP_FLAG_SINGLEWORD | ||
5019 | ); | ||
5018 | if (HUSH_DEBUG) | 5020 | if (HUSH_DEBUG) |
5019 | if (!list[0] || list[1]) | 5021 | if (!list[0] || list[1]) |
5020 | bb_error_msg_and_die("BUG in varexp2"); | 5022 | bb_error_msg_and_die("BUG in varexp2"); |
5021 | /* actually, just move string 2*sizeof(char*) bytes back */ | 5023 | /* actually, just move string 2*sizeof(char*) bytes back */ |
5022 | overlapping_strcpy((char*)list, list[0]); | 5024 | overlapping_strcpy((char*)list, list[0]); |
5023 | unbackslash((char*)list); | 5025 | if (do_unbackslash) |
5024 | debug_printf_expand("string_to_string='%s'\n", (char*)list); | 5026 | unbackslash((char*)list); |
5027 | debug_printf_expand("string_to_string=>'%s'\n", (char*)list); | ||
5025 | return (char*)list; | 5028 | return (char*)list; |
5026 | } | 5029 | } |
5027 | 5030 | ||
@@ -5056,7 +5059,7 @@ static char **expand_assignments(char **argv, int count) | |||
5056 | G.expanded_assignments = p = NULL; | 5059 | G.expanded_assignments = p = NULL; |
5057 | /* Expand assignments into one string each */ | 5060 | /* Expand assignments into one string each */ |
5058 | for (i = 0; i < count; i++) { | 5061 | for (i = 0; i < count; i++) { |
5059 | G.expanded_assignments = p = add_string_to_strings(p, expand_string_to_string(argv[i])); | 5062 | G.expanded_assignments = p = add_string_to_strings(p, expand_string_to_string(argv[i], /*unbackslash:*/ 1)); |
5060 | } | 5063 | } |
5061 | G.expanded_assignments = NULL; | 5064 | G.expanded_assignments = NULL; |
5062 | return p; | 5065 | return p; |
@@ -5465,7 +5468,7 @@ static void setup_heredoc(struct redir_struct *redir) | |||
5465 | 5468 | ||
5466 | expanded = NULL; | 5469 | expanded = NULL; |
5467 | if (!(redir->rd_dup & HEREDOC_QUOTED)) { | 5470 | if (!(redir->rd_dup & HEREDOC_QUOTED)) { |
5468 | expanded = expand_pseudo_dquoted(heredoc, /*dquoted:*/ 1); | 5471 | expanded = expand_pseudo_dquoted(heredoc, /*dquoted:*/ 1, /*unbackslash:*/ 1); |
5469 | if (expanded) | 5472 | if (expanded) |
5470 | heredoc = expanded; | 5473 | heredoc = expanded; |
5471 | } | 5474 | } |
@@ -5565,7 +5568,7 @@ static int setup_redirects(struct command *prog, int squirrel[]) | |||
5565 | continue; | 5568 | continue; |
5566 | } | 5569 | } |
5567 | mode = redir_table[redir->rd_type].mode; | 5570 | mode = redir_table[redir->rd_type].mode; |
5568 | p = expand_string_to_string(redir->rd_filename); | 5571 | p = expand_string_to_string(redir->rd_filename, /*unbackslash:*/ 1); |
5569 | openfd = open_or_warn(p, mode); | 5572 | openfd = open_or_warn(p, mode); |
5570 | free(p); | 5573 | free(p); |
5571 | if (openfd < 0) { | 5574 | if (openfd < 0) { |
@@ -6516,7 +6519,7 @@ static NOINLINE int run_pipe(struct pipe *pi) | |||
6516 | if (G_x_mode) | 6519 | if (G_x_mode) |
6517 | bb_putchar_stderr('+'); | 6520 | bb_putchar_stderr('+'); |
6518 | while (*argv) { | 6521 | while (*argv) { |
6519 | char *p = expand_string_to_string(*argv); | 6522 | char *p = expand_string_to_string(*argv, /*unbackslash:*/ 1); |
6520 | if (G_x_mode) | 6523 | if (G_x_mode) |
6521 | fprintf(stderr, " %s", p); | 6524 | fprintf(stderr, " %s", p); |
6522 | debug_printf_exec("set shell var:'%s'->'%s'\n", | 6525 | debug_printf_exec("set shell var:'%s'->'%s'\n", |
@@ -7020,7 +7023,7 @@ static int run_list(struct pipe *pi) | |||
7020 | /* all prev words didn't match, does this one match? */ | 7023 | /* all prev words didn't match, does this one match? */ |
7021 | argv = pi->cmds->argv; | 7024 | argv = pi->cmds->argv; |
7022 | while (*argv) { | 7025 | while (*argv) { |
7023 | char *pattern = expand_string_to_string(*argv); | 7026 | char *pattern = expand_string_to_string(*argv, /*unbackslash:*/ 1); |
7024 | /* TODO: which FNM_xxx flags to use? */ | 7027 | /* TODO: which FNM_xxx flags to use? */ |
7025 | cond_code = (fnmatch(pattern, case_word, /*flags:*/ 0) != 0); | 7028 | cond_code = (fnmatch(pattern, case_word, /*flags:*/ 0) != 0); |
7026 | free(pattern); | 7029 | free(pattern); |
diff --git a/shell/hush_test/hush-vars/var_bash5.right b/shell/hush_test/hush-vars/var_bash5.right index 278ed3228..1990902b2 100644 --- a/shell/hush_test/hush-vars/var_bash5.right +++ b/shell/hush_test/hush-vars/var_bash5.right | |||
@@ -1,4 +1,11 @@ | |||
1 | a/ | 1 | 1 a/ |
2 | a/d | 2 | 2 a/d |
3 | a/e/f | 3 | 3 a/e/f |
4 | 4 a\ | ||
5 | 5 a\d | ||
6 | 6 a\e\f | ||
7 | 7 a\\ | ||
8 | 8 a\\d | ||
9 | 9 a\\e\\f | ||
10 | a ab | ||
4 | Done: 0 | 11 | Done: 0 |
diff --git a/shell/hush_test/hush-vars/var_bash5.tests b/shell/hush_test/hush-vars/var_bash5.tests index 7f482a554..5748b4ac7 100755 --- a/shell/hush_test/hush-vars/var_bash5.tests +++ b/shell/hush_test/hush-vars/var_bash5.tests | |||
@@ -4,8 +4,26 @@ | |||
4 | v='a/b/c' | 4 | v='a/b/c' |
5 | s='b/c' | 5 | s='b/c' |
6 | r='e/f' | 6 | r='e/f' |
7 | echo "${v/$s}" | 7 | echo "1 ${v/$s}" |
8 | echo "${v/$s/d}" | 8 | echo "2 ${v/$s/d}" |
9 | echo "${v/$s/$r}" | 9 | echo "3 ${v/$s/$r}" |
10 | |||
11 | v='a\b\c' | ||
12 | s='b\\c' | ||
13 | r='e\f' | ||
14 | echo "4 ${v/$s}" | ||
15 | echo "5 ${v/$s/d}" | ||
16 | echo "6 ${v/$s/$r}" | ||
17 | |||
18 | v='a\\b\\c' | ||
19 | s='b\\\\c' | ||
20 | r='e\\f' | ||
21 | echo "7 ${v/$s}" | ||
22 | echo "8 ${v/$s/d}" | ||
23 | echo "9 ${v/$s/$r}" | ||
24 | |||
25 | v='a-$a-\t-\\-\"-\`-\--\z-\*-\?-b' | ||
26 | s='-$a-\\t-\\\\-\\"-\\`-\\--\\z-\\\*-\\\?-' | ||
27 | echo "a ${v/$s}" | ||
10 | 28 | ||
11 | echo Done: $? | 29 | echo Done: $? |