summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <dvlasenk@redhat.com>2010-09-10 11:06:01 +0200
committerDenys Vlasenko <dvlasenk@redhat.com>2010-09-10 11:06:01 +0200
commit4f870496e7d934fcbe092478f1da8ec7a3ea4466 (patch)
tree931344dd0d6d1d8cfaf358b1cd6f6e8982101b74
parentd98e5c65c3c69373dab56a7f9af8780c1a8123b2 (diff)
downloadbusybox-w32-4f870496e7d934fcbe092478f1da8ec7a3ea4466.tar.gz
busybox-w32-4f870496e7d934fcbe092478f1da8ec7a3ea4466.tar.bz2
busybox-w32-4f870496e7d934fcbe092478f1da8ec7a3ea4466.zip
hush: do fewer strdups in % and hash expansions
function old new delta builtin_umask 133 132 -1 expand_one_var 1552 1543 -9 Signed-off-by: Denys Vlasenko <dvlasenk@redhat.com>
-rw-r--r--shell/hush.c29
-rw-r--r--shell/hush_test/hush-vars/var_bash6.right5
-rwxr-xr-xshell/hush_test/hush-vars/var_bash6.tests9
3 files changed, 30 insertions, 13 deletions
diff --git a/shell/hush.c b/shell/hush.c
index 920d9638c..3faf2b326 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -3800,8 +3800,8 @@ static int encode_string(o_string *as_string,
3800 ch = i_getch(input); /* eat next */ 3800 ch = i_getch(input); /* eat next */
3801 if (ch == '\n') 3801 if (ch == '\n')
3802 goto again; /* skip \<newline> */ 3802 goto again; /* skip \<newline> */
3803 } /* else: ch remains == '\\', and we double it */ 3803 } /* else: ch remains == '\\', and we double it below: */
3804 o_addqchr(dest, ch); /* \c if c is s glob char, else just c */ 3804 o_addqchr(dest, ch); /* \c if c is a glob char, else just c */
3805 nommu_addchr(as_string, ch); 3805 nommu_addchr(as_string, ch);
3806 goto again; 3806 goto again;
3807 } 3807 }
@@ -4618,26 +4618,29 @@ static NOINLINE const char *expand_one_var(char **to_be_freed_pp, char *arg, cha
4618 * Then var's value is matched to it and matching part removed. 4618 * Then var's value is matched to it and matching part removed.
4619 */ 4619 */
4620 if (val && val[0]) { 4620 if (val && val[0]) {
4621 char *t;
4621 char *exp_exp_word; 4622 char *exp_exp_word;
4622 char *loc; 4623 char *loc;
4623 unsigned scan_flags = pick_scan(exp_op, *exp_word); 4624 unsigned scan_flags = pick_scan(exp_op, *exp_word);
4624 if (exp_op == *exp_word) /* ## or %% */ 4625 if (exp_op == *exp_word) /* ## or %% */
4625 exp_word++; 4626 exp_word++;
4626//TODO: avoid xstrdup unless needed
4627// (see HACK ALERT below for an example)
4628 val = to_be_freed = xstrdup(val);
4629 exp_exp_word = encode_then_expand_string(exp_word, /*process_bkslash:*/ 1, /*unbackslash:*/ 1); 4627 exp_exp_word = encode_then_expand_string(exp_word, /*process_bkslash:*/ 1, /*unbackslash:*/ 1);
4630 if (exp_exp_word) 4628 if (exp_exp_word)
4631 exp_word = exp_exp_word; 4629 exp_word = exp_exp_word;
4632 loc = scan_and_match(to_be_freed, exp_word, scan_flags); 4630 /* HACK ALERT. We depend here on the fact that
4631 * G.global_argv and results of utoa and get_local_var_value
4632 * are actually in writable memory:
4633 * scan_and_match momentarily stores NULs there. */
4634 t = (char*)val;
4635 loc = scan_and_match(t, exp_word, scan_flags);
4633 //bb_error_msg("op:%c str:'%s' pat:'%s' res:'%s'", 4636 //bb_error_msg("op:%c str:'%s' pat:'%s' res:'%s'",
4634 // exp_op, to_be_freed, exp_word, loc); 4637 // exp_op, t, exp_word, loc);
4635 free(exp_exp_word); 4638 free(exp_exp_word);
4636 if (loc) { /* match was found */ 4639 if (loc) { /* match was found */
4637 if (scan_flags & SCAN_MATCH_LEFT_HALF) /* #[#] */ 4640 if (scan_flags & SCAN_MATCH_LEFT_HALF) /* #[#] */
4638 val = loc; 4641 val = loc; /* take right part */
4639 else /* %[%] */ 4642 else /* %[%] */
4640 *loc = '\0'; 4643 val = to_be_freed = xstrndup(val, loc - val); /* left */
4641 } 4644 }
4642 } 4645 }
4643 } 4646 }
@@ -4646,13 +4649,13 @@ static NOINLINE const char *expand_one_var(char **to_be_freed_pp, char *arg, cha
4646 /* It's ${var/[/]pattern[/repl]} thing. 4649 /* It's ${var/[/]pattern[/repl]} thing.
4647 * Note that in encoded form it has TWO parts: 4650 * Note that in encoded form it has TWO parts:
4648 * var/pattern<SPECIAL_VAR_SYMBOL>repl<SPECIAL_VAR_SYMBOL> 4651 * var/pattern<SPECIAL_VAR_SYMBOL>repl<SPECIAL_VAR_SYMBOL>
4652 * and if // is used, it is encoded as \:
4653 * var\pattern<SPECIAL_VAR_SYMBOL>repl<SPECIAL_VAR_SYMBOL>
4649 */ 4654 */
4650 /* Empty variable always gives nothing: */ 4655 /* Empty variable always gives nothing: */
4651 // "v=''; echo ${v/*/w}" prints "", not "w" 4656 // "v=''; echo ${v/*/w}" prints "", not "w"
4652 if (val && val[0]) { 4657 if (val && val[0]) {
4653 /* It's ${var/[/]pattern[/repl]} thing */ 4658 /* pattern uses non-standard expansion.
4654 /*
4655 * Pattern is taken literally, while
4656 * repl should be unbackslashed and globbed 4659 * repl should be unbackslashed and globbed
4657 * by the usual expansion rules: 4660 * by the usual expansion rules:
4658 * >az; >bz; 4661 * >az; >bz;
@@ -7339,7 +7342,7 @@ int hush_main(int argc, char **argv)
7339 /* Deal with HUSH_VERSION */ 7342 /* Deal with HUSH_VERSION */
7340 G.shell_ver.flg_export = 1; 7343 G.shell_ver.flg_export = 1;
7341 G.shell_ver.flg_read_only = 1; 7344 G.shell_ver.flg_read_only = 1;
7342 /* Code which handles ${var/P/R} needs writable values for all variables, 7345 /* Code which handles ${var<op>...} needs writable values for all variables,
7343 * therefore we xstrdup: */ 7346 * therefore we xstrdup: */
7344 G.shell_ver.varstr = xstrdup(hush_version_str), 7347 G.shell_ver.varstr = xstrdup(hush_version_str),
7345 G.top_var = &G.shell_ver; 7348 G.top_var = &G.shell_ver;
diff --git a/shell/hush_test/hush-vars/var_bash6.right b/shell/hush_test/hush-vars/var_bash6.right
new file mode 100644
index 000000000..63fc23df8
--- /dev/null
+++ b/shell/hush_test/hush-vars/var_bash6.right
@@ -0,0 +1,5 @@
1Expected Actual
2a*z : a*z
3\z : \z
4a1z a2z: a1z a2z
5z : z
diff --git a/shell/hush_test/hush-vars/var_bash6.tests b/shell/hush_test/hush-vars/var_bash6.tests
new file mode 100755
index 000000000..cf2e4f020
--- /dev/null
+++ b/shell/hush_test/hush-vars/var_bash6.tests
@@ -0,0 +1,9 @@
1# This testcase checks globbing correctness in ${v/a/b}
2
3>a1z; >a2z;
4 echo 'Expected' 'Actual'
5v='a bz'; echo 'a*z :' "${v/a*z/a*z}"
6v='a bz'; echo '\z :' "${v/a*z/\z}"
7v='a bz'; echo 'a1z a2z:' ${v/a*z/a*z}
8v='a bz'; echo 'z :' ${v/a*z/\z}
9rm a1z a2z