diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2021-10-09 03:32:20 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2021-10-09 03:33:22 +0200 |
commit | 5aaeb550b76f063ffddef8587d9d91f7fddc4406 (patch) | |
tree | c643b6ceba297c4951c582bc30e7e5aa5aecbf4c /shell | |
parent | 21e8dbfd9d11a461ed7f91b495fa39d8a9131b28 (diff) | |
download | busybox-w32-5aaeb550b76f063ffddef8587d9d91f7fddc4406.tar.gz busybox-w32-5aaeb550b76f063ffddef8587d9d91f7fddc4406.tar.bz2 busybox-w32-5aaeb550b76f063ffddef8587d9d91f7fddc4406.zip |
ash: speed up ${x//\*/|} too, make it independent of ASH_OPTIMIZE_FOR_SIZE
function old new delta
subevalvar 1503 1545 +42
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'shell')
-rw-r--r-- | shell/ash.c | 18 |
1 files changed, 12 insertions, 6 deletions
diff --git a/shell/ash.c b/shell/ash.c index e8ec0b1a6..199975191 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
@@ -7251,7 +7251,7 @@ subevalvar(char *start, char *str, int strloc, | |||
7251 | #if BASH_PATTERN_SUBST | 7251 | #if BASH_PATTERN_SUBST |
7252 | workloc = expdest - (char *)stackblock(); | 7252 | workloc = expdest - (char *)stackblock(); |
7253 | if (subtype == VSREPLACE || subtype == VSREPLACEALL) { | 7253 | if (subtype == VSREPLACE || subtype == VSREPLACEALL) { |
7254 | size_t no_meta_len; | 7254 | size_t no_meta_len, first_escaped; |
7255 | int len; | 7255 | int len; |
7256 | char *idx, *end; | 7256 | char *idx, *end; |
7257 | 7257 | ||
@@ -7269,28 +7269,34 @@ subevalvar(char *start, char *str, int strloc, | |||
7269 | if (str[0] == '\0') | 7269 | if (str[0] == '\0') |
7270 | goto out1; | 7270 | goto out1; |
7271 | 7271 | ||
7272 | no_meta_len = (ENABLE_ASH_OPTIMIZE_FOR_SIZE || strpbrk(str, "*?[\\")) ? 0 : strlen(str); | 7272 | first_escaped = (str[0] == '\\' && str[1]); |
7273 | /* "first_escaped" trick allows to treat e.g. "\*no_glob_chars" | ||
7274 | * as literal too (as it is semi-common, and easy to accomodate | ||
7275 | * by just using str + 1). | ||
7276 | */ | ||
7277 | no_meta_len = strpbrk(str + first_escaped * 2, "*?[\\") ? 0 : strlen(str); | ||
7273 | len = 0; | 7278 | len = 0; |
7274 | idx = startp; | 7279 | idx = startp; |
7275 | end = str - 1; | 7280 | end = str - 1; |
7276 | while (idx <= end) { | 7281 | while (idx <= end) { |
7277 | try_to_match: | 7282 | try_to_match: |
7278 | if (no_meta_len == 0) { | 7283 | if (no_meta_len == 0) { |
7279 | /* pattern has meta chars, have to glob; or ENABLE_ASH_OPTIMIZE_FOR_SIZE */ | 7284 | /* pattern has meta chars, have to glob */ |
7280 | loc = scanright(idx, rmesc, rmescend, str, quotes, /*match_at_start:*/ 1); | 7285 | loc = scanright(idx, rmesc, rmescend, str, quotes, /*match_at_start:*/ 1); |
7281 | } else { | 7286 | } else { |
7282 | /* Testcase for very slow replace (performs about 22k replaces): | 7287 | /* Testcase for very slow replace (performs about 22k replaces): |
7283 | * x=:::::::::::::::::::::: | 7288 | * x=:::::::::::::::::::::: |
7284 | * x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;echo ${#x} | 7289 | * x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;echo ${#x} |
7285 | * echo "${x//:/|}" | 7290 | * echo "${x//:/|}" |
7291 | * To test "first_escaped" logic, replace : with *. | ||
7286 | */ | 7292 | */ |
7287 | if (strncmp(rmesc, str, no_meta_len) != 0) | 7293 | if (strncmp(rmesc, str + first_escaped, no_meta_len - first_escaped) != 0) |
7288 | goto no_match; | 7294 | goto no_match; |
7289 | loc = idx; | 7295 | loc = idx; |
7290 | if (!quotes) { | 7296 | if (!quotes) { |
7291 | loc += no_meta_len; | 7297 | loc += no_meta_len - first_escaped; |
7292 | } else { | 7298 | } else { |
7293 | size_t n = no_meta_len; | 7299 | size_t n = no_meta_len - first_escaped; |
7294 | do { | 7300 | do { |
7295 | if ((unsigned char)*loc == CTLESC) | 7301 | if ((unsigned char)*loc == CTLESC) |
7296 | loc++; | 7302 | loc++; |