summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <dvlasenk@redhat.com>2010-09-10 10:17:53 +0200
committerDenys Vlasenko <dvlasenk@redhat.com>2010-09-10 10:17:53 +0200
commitebee410fe2500d6bd5980032d0b183494f509c9b (patch)
tree7d51a849f343d4b3437714aea40f7efaf6ef4050
parent14e289b3246b4266499ffc5747dcc5c98bdaf5b9 (diff)
downloadbusybox-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.c43
-rw-r--r--shell/hush_test/hush-vars/var_bash5.right13
-rwxr-xr-xshell/hush_test/hush-vars/var_bash5.tests24
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: */
4338static char *expand_string_to_string(const char *str); 4338static char *expand_string_to_string(const char *str, int do_unbackslash);
4339static int process_command_subs(o_string *dest, const char *s); 4339static 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 */
4390static char *expand_pseudo_dquoted(const char *str, int dquoted) 4390static 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 */
5001static char *expand_string_to_string(const char *str) 4999static 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 @@
1a/ 11 a/
2a/d 22 a/d
3a/e/f 33 a/e/f
44 a\
55 a\d
66 a\e\f
77 a\\
88 a\\d
99 a\\e\\f
10a ab
4Done: 0 11Done: 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 @@
4v='a/b/c' 4v='a/b/c'
5s='b/c' 5s='b/c'
6r='e/f' 6r='e/f'
7echo "${v/$s}" 7echo "1 ${v/$s}"
8echo "${v/$s/d}" 8echo "2 ${v/$s/d}"
9echo "${v/$s/$r}" 9echo "3 ${v/$s/$r}"
10
11v='a\b\c'
12s='b\\c'
13r='e\f'
14echo "4 ${v/$s}"
15echo "5 ${v/$s/d}"
16echo "6 ${v/$s/$r}"
17
18v='a\\b\\c'
19s='b\\\\c'
20r='e\\f'
21echo "7 ${v/$s}"
22echo "8 ${v/$s/d}"
23echo "9 ${v/$s/$r}"
24
25v='a-$a-\t-\\-\"-\`-\--\z-\*-\?-b'
26s='-$a-\\t-\\\\-\\"-\\`-\\--\\z-\\\*-\\\?-'
27echo "a ${v/$s}"
10 28
11echo Done: $? 29echo Done: $?