aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2010-08-05 17:19:27 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2010-08-05 17:19:27 +0200
commitb0fbe4b5409b136e0c80788cf183ec24237e9c97 (patch)
treed5ef2215b48c894721801f0fe7184a347f91d669
parente74d79866c6d125527e3ba69245a087a28fd19ce (diff)
downloadbusybox-w32-b0fbe4b5409b136e0c80788cf183ec24237e9c97.tar.gz
busybox-w32-b0fbe4b5409b136e0c80788cf183ec24237e9c97.tar.bz2
busybox-w32-b0fbe4b5409b136e0c80788cf183ec24237e9c97.zip
ash: add a testcase for bug 2281 (currently fails). Small code cleanups.
function old new delta changepath 195 192 -3 subevalvar 1204 1200 -4 readtoken1 3247 3240 -7 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/3 up/down: 0/-14) Total: -14 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r--shell/ash.c83
-rwxr-xr-x[-rw-r--r--]shell/ash_test/ash-redir/redir9.tests0
-rw-r--r--shell/ash_test/ash-vars/var_bash3.right40
-rwxr-xr-xshell/ash_test/ash-vars/var_bash3.tests47
-rw-r--r--shell/ash_test/ash-vars/var_bash4.right2
-rwxr-xr-xshell/ash_test/ash-vars/var_bash4.tests3
6 files changed, 104 insertions, 71 deletions
diff --git a/shell/ash.c b/shell/ash.c
index d8becc37a..16783f2e8 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -6296,13 +6296,14 @@ parse_sub_pattern(char *arg, int inquotes)
6296#endif /* ENABLE_ASH_BASH_COMPAT */ 6296#endif /* ENABLE_ASH_BASH_COMPAT */
6297 6297
6298static const char * 6298static const char *
6299subevalvar(char *p, char *str, int strloc, int subtype, 6299subevalvar(char *p, char *varname, int strloc, int subtype,
6300 int startloc, int varflags, int quotes, struct strlist *var_str_list) 6300 int startloc, int varflags, int quotes, struct strlist *var_str_list)
6301{ 6301{
6302 struct nodelist *saveargbackq = argbackq; 6302 struct nodelist *saveargbackq = argbackq;
6303 char *startp; 6303 char *startp;
6304 char *loc; 6304 char *loc;
6305 char *rmesc, *rmescend; 6305 char *rmesc, *rmescend;
6306 char *str;
6306 IF_ASH_BASH_COMPAT(const char *repl = NULL;) 6307 IF_ASH_BASH_COMPAT(const char *repl = NULL;)
6307 IF_ASH_BASH_COMPAT(int pos, len, orig_len;) 6308 IF_ASH_BASH_COMPAT(int pos, len, orig_len;)
6308 int saveherefd = herefd; 6309 int saveherefd = herefd;
@@ -6310,6 +6311,9 @@ subevalvar(char *p, char *str, int strloc, int subtype,
6310 int zero; 6311 int zero;
6311 char *(*scan)(char*, char*, char*, char*, int, int); 6312 char *(*scan)(char*, char*, char*, char*, int, int);
6312 6313
6314 //bb_error_msg("subevalvar(p:'%s',varname:'%s',strloc:%d,subtype:%d,startloc:%d,varflags:%x,quotes:%d",
6315 // p, varname, strloc, subtype, startloc, varflags, quotes);
6316
6313 herefd = -1; 6317 herefd = -1;
6314 argstr(p, (subtype != VSASSIGN && subtype != VSQUESTION) ? EXP_CASE : 0, 6318 argstr(p, (subtype != VSASSIGN && subtype != VSQUESTION) ? EXP_CASE : 0,
6315 var_str_list); 6319 var_str_list);
@@ -6320,11 +6324,15 @@ subevalvar(char *p, char *str, int strloc, int subtype,
6320 6324
6321 switch (subtype) { 6325 switch (subtype) {
6322 case VSASSIGN: 6326 case VSASSIGN:
6323 setvar(str, startp, 0); 6327 setvar(varname, startp, 0);
6324 amount = startp - expdest; 6328 amount = startp - expdest;
6325 STADJUST(amount, expdest); 6329 STADJUST(amount, expdest);
6326 return startp; 6330 return startp;
6327 6331
6332 case VSQUESTION:
6333 varunset(p, varname, startp, varflags);
6334 /* NOTREACHED */
6335
6328#if ENABLE_ASH_BASH_COMPAT 6336#if ENABLE_ASH_BASH_COMPAT
6329 case VSSUBSTR: 6337 case VSSUBSTR:
6330 loc = str = stackblock() + strloc; 6338 loc = str = stackblock() + strloc;
@@ -6385,11 +6393,8 @@ subevalvar(char *p, char *str, int strloc, int subtype,
6385 STADJUST(amount, expdest); 6393 STADJUST(amount, expdest);
6386 return loc; 6394 return loc;
6387#endif 6395#endif
6388
6389 case VSQUESTION:
6390 varunset(p, str, startp, varflags);
6391 /* NOTREACHED */
6392 } 6396 }
6397
6393 resetloc = expdest - (char *)stackblock(); 6398 resetloc = expdest - (char *)stackblock();
6394 6399
6395 /* We'll comeback here if we grow the stack while handling 6400 /* We'll comeback here if we grow the stack while handling
@@ -6423,13 +6428,14 @@ subevalvar(char *p, char *str, int strloc, int subtype,
6423 6428
6424 if (!repl) { 6429 if (!repl) {
6425 repl = parse_sub_pattern(str, varflags & VSQUOTE); 6430 repl = parse_sub_pattern(str, varflags & VSQUOTE);
6431 //bb_error_msg("repl:'%s'", repl);
6426 if (!repl) 6432 if (!repl)
6427 repl = nullstr; 6433 repl = nullstr;
6428 } 6434 }
6429 6435
6430 /* If there's no pattern to match, return the expansion unmolested */ 6436 /* If there's no pattern to match, return the expansion unmolested */
6431 if (str[0] == '\0') 6437 if (str[0] == '\0')
6432 return 0; 6438 return NULL;
6433 6439
6434 len = 0; 6440 len = 0;
6435 idx = startp; 6441 idx = startp;
@@ -6437,6 +6443,7 @@ subevalvar(char *p, char *str, int strloc, int subtype,
6437 while (idx < end) { 6443 while (idx < end) {
6438 try_to_match: 6444 try_to_match:
6439 loc = scanright(idx, rmesc, rmescend, str, quotes, 1); 6445 loc = scanright(idx, rmesc, rmescend, str, quotes, 1);
6446 //bb_error_msg("scanright('%s'):'%s'", str, loc);
6440 if (!loc) { 6447 if (!loc) {
6441 /* No match, advance */ 6448 /* No match, advance */
6442 char *restart_detect = stackblock(); 6449 char *restart_detect = stackblock();
@@ -6475,6 +6482,7 @@ subevalvar(char *p, char *str, int strloc, int subtype,
6475 idx = loc; 6482 idx = loc;
6476 } 6483 }
6477 6484
6485 //bb_error_msg("repl:'%s'", repl);
6478 for (loc = (char*)repl; *loc; loc++) { 6486 for (loc = (char*)repl; *loc; loc++) {
6479 char *restart_detect = stackblock(); 6487 char *restart_detect = stackblock();
6480 if (quotes && *loc == '\\') { 6488 if (quotes && *loc == '\\') {
@@ -6510,6 +6518,7 @@ subevalvar(char *p, char *str, int strloc, int subtype,
6510 STPUTC('\0', expdest); 6518 STPUTC('\0', expdest);
6511 startp = (char *)stackblock() + startloc; 6519 startp = (char *)stackblock() + startloc;
6512 memmove(startp, (char *)stackblock() + workloc, len + 1); 6520 memmove(startp, (char *)stackblock() + workloc, len + 1);
6521 //bb_error_msg("startp:'%s'", startp);
6513 amount = expdest - (startp + len); 6522 amount = expdest - (startp + len);
6514 STADJUST(-amount, expdest); 6523 STADJUST(-amount, expdest);
6515 return startp; 6524 return startp;
@@ -6810,7 +6819,7 @@ evalvar(char *p, int flags, struct strlist *var_str_list)
6810 */ 6819 */
6811 STPUTC('\0', expdest); 6820 STPUTC('\0', expdest);
6812 patloc = expdest - (char *)stackblock(); 6821 patloc = expdest - (char *)stackblock();
6813 if (NULL == subevalvar(p, /* str: */ NULL, patloc, subtype, 6822 if (NULL == subevalvar(p, /* varname: */ NULL, patloc, subtype,
6814 startloc, varflags, 6823 startloc, varflags,
6815//TODO: | EXP_REDIR too? All other such places do it too 6824//TODO: | EXP_REDIR too? All other such places do it too
6816 /* quotes: */ flags & (EXP_FULL | EXP_CASE), 6825 /* quotes: */ flags & (EXP_FULL | EXP_CASE),
@@ -11114,8 +11123,11 @@ readtoken1(int c, int syntax, char *eofmark, int striptabs)
11114 USTPUTC('\\', out); 11123 USTPUTC('\\', out);
11115 } 11124 }
11116#endif 11125#endif
11117 if (dblquote && c != '\\' 11126 /* Backslash is retained if we are in "str" and next char isn't special */
11118 && c != '`' && c != '$' 11127 if (dblquote
11128 && c != '\\'
11129 && c != '`'
11130 && c != '$'
11119 && (c != '"' || eofmark != NULL) 11131 && (c != '"' || eofmark != NULL)
11120 ) { 11132 ) {
11121 USTPUTC(CTLESC, out); 11133 USTPUTC(CTLESC, out);
@@ -11187,7 +11199,7 @@ readtoken1(int c, int syntax, char *eofmark, int striptabs)
11187 } else { 11199 } else {
11188 /* 11200 /*
11189 * unbalanced parens 11201 * unbalanced parens
11190 * (don't 2nd guess - no error) 11202 * (don't 2nd guess - no error)
11191 */ 11203 */
11192 pungetc(); 11204 pungetc();
11193 USTPUTC(')', out); 11205 USTPUTC(')', out);
@@ -11380,8 +11392,6 @@ parsesub: {
11380 unsigned char subtype; 11392 unsigned char subtype;
11381 int typeloc; 11393 int typeloc;
11382 int flags; 11394 int flags;
11383 char *p;
11384 static const char types[] ALIGN1 = "}-+?=";
11385 11395
11386 c = pgetc(); 11396 c = pgetc();
11387 if (c > 255 /* PEOA or PEOF */ 11397 if (c > 255 /* PEOA or PEOF */
@@ -11394,7 +11404,8 @@ parsesub: {
11394#endif 11404#endif
11395 USTPUTC('$', out); 11405 USTPUTC('$', out);
11396 pungetc(); 11406 pungetc();
11397 } else if (c == '(') { /* $(command) or $((arith)) */ 11407 } else if (c == '(') {
11408 /* $(command) or $((arith)) */
11398 if (pgetc() == '(') { 11409 if (pgetc() == '(') {
11399#if ENABLE_SH_MATH_SUPPORT 11410#if ENABLE_SH_MATH_SUPPORT
11400 PARSEARITH(); 11411 PARSEARITH();
@@ -11406,6 +11417,7 @@ parsesub: {
11406 PARSEBACKQNEW(); 11417 PARSEBACKQNEW();
11407 } 11418 }
11408 } else { 11419 } else {
11420 /* $VAR, $<specialchar>, ${...}, or PEOA/PEOF */
11409 USTPUTC(CTLVAR, out); 11421 USTPUTC(CTLVAR, out);
11410 typeloc = out - (char *)stackblock(); 11422 typeloc = out - (char *)stackblock();
11411 USTPUTC(VSNORMAL, out); 11423 USTPUTC(VSNORMAL, out);
@@ -11415,76 +11427,85 @@ parsesub: {
11415 if (c == '#') { 11427 if (c == '#') {
11416 c = pgetc(); 11428 c = pgetc();
11417 if (c == '}') 11429 if (c == '}')
11418 c = '#'; 11430 c = '#'; /* ${#} - same as $# */
11419 else 11431 else
11420 subtype = VSLENGTH; 11432 subtype = VSLENGTH; /* ${#VAR} */
11421 } else 11433 } else {
11422 subtype = 0; 11434 subtype = 0;
11435 }
11423 } 11436 }
11424 if (c <= 255 /* not PEOA or PEOF */ && is_name(c)) { 11437 if (c <= 255 /* not PEOA or PEOF */ && is_name(c)) {
11438 /* $[{[#]]NAME[}] */
11425 do { 11439 do {
11426 STPUTC(c, out); 11440 STPUTC(c, out);
11427 c = pgetc(); 11441 c = pgetc();
11428 } while (c <= 255 /* not PEOA or PEOF */ && is_in_name(c)); 11442 } while (c <= 255 /* not PEOA or PEOF */ && is_in_name(c));
11429 } else if (isdigit(c)) { 11443 } else if (isdigit(c)) {
11444 /* $[{[#]]NUM[}] */
11430 do { 11445 do {
11431 STPUTC(c, out); 11446 STPUTC(c, out);
11432 c = pgetc(); 11447 c = pgetc();
11433 } while (isdigit(c)); 11448 } while (isdigit(c));
11434 } else if (is_special(c)) { 11449 } else if (is_special(c)) {
11450 /* $[{[#]]<specialchar>[}] */
11435 USTPUTC(c, out); 11451 USTPUTC(c, out);
11436 c = pgetc(); 11452 c = pgetc();
11437 } else { 11453 } else {
11438 badsub: 11454 badsub:
11439 raise_error_syntax("bad substitution"); 11455 raise_error_syntax("bad substitution");
11440 } 11456 }
11441 if (c != '}' && subtype == VSLENGTH) 11457 if (c != '}' && subtype == VSLENGTH) {
11458 /* ${#VAR didn't end with } */
11442 goto badsub; 11459 goto badsub;
11460 }
11443 11461
11444 STPUTC('=', out); 11462 STPUTC('=', out);
11445 flags = 0; 11463 flags = 0;
11446 if (subtype == 0) { 11464 if (subtype == 0) {
11465 /* ${VAR...} but not $VAR or ${#VAR} */
11466 /* c == first char after VAR */
11447 switch (c) { 11467 switch (c) {
11448 case ':': 11468 case ':':
11449 c = pgetc(); 11469 c = pgetc();
11450#if ENABLE_ASH_BASH_COMPAT 11470#if ENABLE_ASH_BASH_COMPAT
11451 if (c == ':' || c == '$' || isdigit(c)) { 11471 if (c == ':' || c == '$' || isdigit(c)) {
11452 pungetc();
11453 subtype = VSSUBSTR; 11472 subtype = VSSUBSTR;
11454 break; 11473 pungetc();
11474 break; /* "goto do_pungetc" is bigger (!) */
11455 } 11475 }
11456#endif 11476#endif
11457 flags = VSNUL; 11477 flags = VSNUL;
11458 /*FALLTHROUGH*/ 11478 /*FALLTHROUGH*/
11459 default: 11479 default: {
11460 p = strchr(types, c); 11480 static const char types[] ALIGN1 = "}-+?=";
11481 const char *p = strchr(types, c);
11461 if (p == NULL) 11482 if (p == NULL)
11462 goto badsub; 11483 goto badsub;
11463 subtype = p - types + VSNORMAL; 11484 subtype = p - types + VSNORMAL;
11464 break; 11485 break;
11486 }
11465 case '%': 11487 case '%':
11466 case '#': { 11488 case '#': {
11467 int cc = c; 11489 int cc = c;
11468 subtype = c == '#' ? VSTRIMLEFT : VSTRIMRIGHT; 11490 subtype = (c == '#' ? VSTRIMLEFT : VSTRIMRIGHT);
11469 c = pgetc(); 11491 c = pgetc();
11470 if (c == cc) 11492 if (c != cc)
11471 subtype++; 11493 goto do_pungetc;
11472 else 11494 subtype++;
11473 pungetc();
11474 break; 11495 break;
11475 } 11496 }
11476#if ENABLE_ASH_BASH_COMPAT 11497#if ENABLE_ASH_BASH_COMPAT
11477 case '/': 11498 case '/':
11478 subtype = VSREPLACE; 11499 subtype = VSREPLACE;
11479 c = pgetc(); 11500 c = pgetc();
11480 if (c == '/') 11501 if (c != '/')
11481 subtype++; /* VSREPLACEALL */ 11502 goto do_pungetc;
11482 else 11503 subtype++; /* VSREPLACEALL */
11483 pungetc();
11484 break; 11504 break;
11485#endif 11505#endif
11486 } 11506 }
11487 } else { 11507 } else {
11508 do_pungetc:
11488 pungetc(); 11509 pungetc();
11489 } 11510 }
11490 if (dblquote || arinest) 11511 if (dblquote || arinest)
diff --git a/shell/ash_test/ash-redir/redir9.tests b/shell/ash_test/ash-redir/redir9.tests
index 8befa611c..8befa611c 100644..100755
--- a/shell/ash_test/ash-redir/redir9.tests
+++ b/shell/ash_test/ash-redir/redir9.tests
diff --git a/shell/ash_test/ash-vars/var_bash3.right b/shell/ash_test/ash-vars/var_bash3.right
index f7f14791e..a97c850ea 100644
--- a/shell/ash_test/ash-vars/var_bash3.right
+++ b/shell/ash_test/ash-vars/var_bash3.right
@@ -1,20 +1,20 @@
1a041#c 11 a041#c
2a041#c 22 a041#c
3a\041#c 33 a\041#c
4a\041#c 44 a\041#c
5a\041#c 55 a\041#c
6a\041#c 66 a\041#c
7a\041#c 77 a\041#c
8a\041#c 88 a\041#c
9a\041#c 99 a\041#c
10a\c 1010 a\c
11a\c 1111 a\c
12a\c 1212 a\c
13a\\c 1313 a\\c
14a\\c 1414 a\\c
15a\\c 1515 a\\c
16a\tc 1616 a\tc
17a\tc 1717 a\tc
18a\tc 1818 a\tc
19atc 1919 atc
20a\tc 2020 a\tc
diff --git a/shell/ash_test/ash-vars/var_bash3.tests b/shell/ash_test/ash-vars/var_bash3.tests
index b9050279e..eca3318e2 100755
--- a/shell/ash_test/ash-vars/var_bash3.tests
+++ b/shell/ash_test/ash-vars/var_bash3.tests
@@ -1,41 +1,48 @@
1a='abc' 1a='abc'
2r=${a//b/\041#} 2r=${a//b/\041#}
3echo $r 3echo 1 $r
4echo ${a//b/\041#} 4echo 2 ${a//b/\041#}
5echo "${a//b/\041#}" 5echo 3 "${a//b/\041#}"
6# --- var_bash3.xx
7# +++ var_bash3.right
8# -1 a\041#c
9# +1 a041#c
10# 2 a041#c
11# -3 a041#c
12# +3 a\041#c
6 13
7a='abc' 14a='abc'
8r=${a//b/\\041#} 15r=${a//b/\\041#}
9echo $r 16echo 4 $r
10echo ${a//b/\\041#} 17echo 5 ${a//b/\\041#}
11echo "${a//b/\\041#}" 18echo 6 "${a//b/\\041#}"
12 19
13a='abc' 20a='abc'
14b='\041#' 21b='\041#'
15r=${a//b/$b} 22r=${a//b/$b}
16echo $r 23echo 7 $r
17echo ${a//b/$b} 24echo 8 ${a//b/$b}
18echo "${a//b/$b}" 25echo 9 "${a//b/$b}"
19 26
20a='abc' 27a='abc'
21b='\' 28b='\'
22r="${a//b/$b}" 29r="${a//b/$b}"
23echo $r 30echo 10 $r
24echo ${a//b/$b} 31echo 11 ${a//b/$b}
25echo "${a//b/$b}" 32echo 12 "${a//b/$b}"
26 33
27a='abc' 34a='abc'
28b='\\' 35b='\\'
29r="${a//b/$b}" 36r="${a//b/$b}"
30echo $r 37echo 13 $r
31echo ${a//b/$b} 38echo 14 ${a//b/$b}
32echo "${a//b/$b}" 39echo 15 "${a//b/$b}"
33 40
34a='abc' 41a='abc'
35b='\t' 42b='\t'
36r="${a//b/$b}" 43r="${a//b/$b}"
37echo $r 44echo 16 $r
38echo ${a//b/$b} 45echo 17 ${a//b/$b}
39echo "${a//b/$b}" 46echo 18 "${a//b/$b}"
40echo ${a//b/\t} 47echo 19 ${a//b/\t}
41echo "${a//b/\t}" 48echo 20 "${a//b/\t}"
diff --git a/shell/ash_test/ash-vars/var_bash4.right b/shell/ash_test/ash-vars/var_bash4.right
new file mode 100644
index 000000000..33a511238
--- /dev/null
+++ b/shell/ash_test/ash-vars/var_bash4.right
@@ -0,0 +1,2 @@
1a*b-backslashstar-
2Done: 0
diff --git a/shell/ash_test/ash-vars/var_bash4.tests b/shell/ash_test/ash-vars/var_bash4.tests
new file mode 100755
index 000000000..304b3d91c
--- /dev/null
+++ b/shell/ash_test/ash-vars/var_bash4.tests
@@ -0,0 +1,3 @@
1FOO='a*b\*c'
2echo "${FOO//\\*/-backslashstar-}"
3echo Done: $?