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>
This commit is contained in:
parent
21e8dbfd9d
commit
5aaeb550b7
18
shell/ash.c
18
shell/ash.c
@ -7251,7 +7251,7 @@ subevalvar(char *start, char *str, int strloc,
|
|||||||
#if BASH_PATTERN_SUBST
|
#if BASH_PATTERN_SUBST
|
||||||
workloc = expdest - (char *)stackblock();
|
workloc = expdest - (char *)stackblock();
|
||||||
if (subtype == VSREPLACE || subtype == VSREPLACEALL) {
|
if (subtype == VSREPLACE || subtype == VSREPLACEALL) {
|
||||||
size_t no_meta_len;
|
size_t no_meta_len, first_escaped;
|
||||||
int len;
|
int len;
|
||||||
char *idx, *end;
|
char *idx, *end;
|
||||||
|
|
||||||
@ -7269,28 +7269,34 @@ subevalvar(char *start, char *str, int strloc,
|
|||||||
if (str[0] == '\0')
|
if (str[0] == '\0')
|
||||||
goto out1;
|
goto out1;
|
||||||
|
|
||||||
no_meta_len = (ENABLE_ASH_OPTIMIZE_FOR_SIZE || strpbrk(str, "*?[\\")) ? 0 : strlen(str);
|
first_escaped = (str[0] == '\\' && str[1]);
|
||||||
|
/* "first_escaped" trick allows to treat e.g. "\*no_glob_chars"
|
||||||
|
* as literal too (as it is semi-common, and easy to accomodate
|
||||||
|
* by just using str + 1).
|
||||||
|
*/
|
||||||
|
no_meta_len = strpbrk(str + first_escaped * 2, "*?[\\") ? 0 : strlen(str);
|
||||||
len = 0;
|
len = 0;
|
||||||
idx = startp;
|
idx = startp;
|
||||||
end = str - 1;
|
end = str - 1;
|
||||||
while (idx <= end) {
|
while (idx <= end) {
|
||||||
try_to_match:
|
try_to_match:
|
||||||
if (no_meta_len == 0) {
|
if (no_meta_len == 0) {
|
||||||
/* pattern has meta chars, have to glob; or ENABLE_ASH_OPTIMIZE_FOR_SIZE */
|
/* pattern has meta chars, have to glob */
|
||||||
loc = scanright(idx, rmesc, rmescend, str, quotes, /*match_at_start:*/ 1);
|
loc = scanright(idx, rmesc, rmescend, str, quotes, /*match_at_start:*/ 1);
|
||||||
} else {
|
} else {
|
||||||
/* Testcase for very slow replace (performs about 22k replaces):
|
/* Testcase for very slow replace (performs about 22k replaces):
|
||||||
* 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=$x$x;echo ${#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$x;echo ${#x}
|
||||||
* echo "${x//:/|}"
|
* echo "${x//:/|}"
|
||||||
|
* To test "first_escaped" logic, replace : with *.
|
||||||
*/
|
*/
|
||||||
if (strncmp(rmesc, str, no_meta_len) != 0)
|
if (strncmp(rmesc, str + first_escaped, no_meta_len - first_escaped) != 0)
|
||||||
goto no_match;
|
goto no_match;
|
||||||
loc = idx;
|
loc = idx;
|
||||||
if (!quotes) {
|
if (!quotes) {
|
||||||
loc += no_meta_len;
|
loc += no_meta_len - first_escaped;
|
||||||
} else {
|
} else {
|
||||||
size_t n = no_meta_len;
|
size_t n = no_meta_len - first_escaped;
|
||||||
do {
|
do {
|
||||||
if ((unsigned char)*loc == CTLESC)
|
if ((unsigned char)*loc == CTLESC)
|
||||||
loc++;
|
loc++;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user