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:
		
							
								
								
									
										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++; | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user