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>
This commit is contained in:
parent
e74d79866c
commit
b0fbe4b540
77
shell/ash.c
77
shell/ash.c
@ -6296,13 +6296,14 @@ parse_sub_pattern(char *arg, int inquotes)
|
|||||||
#endif /* ENABLE_ASH_BASH_COMPAT */
|
#endif /* ENABLE_ASH_BASH_COMPAT */
|
||||||
|
|
||||||
static const char *
|
static const char *
|
||||||
subevalvar(char *p, char *str, int strloc, int subtype,
|
subevalvar(char *p, char *varname, int strloc, int subtype,
|
||||||
int startloc, int varflags, int quotes, struct strlist *var_str_list)
|
int startloc, int varflags, int quotes, struct strlist *var_str_list)
|
||||||
{
|
{
|
||||||
struct nodelist *saveargbackq = argbackq;
|
struct nodelist *saveargbackq = argbackq;
|
||||||
char *startp;
|
char *startp;
|
||||||
char *loc;
|
char *loc;
|
||||||
char *rmesc, *rmescend;
|
char *rmesc, *rmescend;
|
||||||
|
char *str;
|
||||||
IF_ASH_BASH_COMPAT(const char *repl = NULL;)
|
IF_ASH_BASH_COMPAT(const char *repl = NULL;)
|
||||||
IF_ASH_BASH_COMPAT(int pos, len, orig_len;)
|
IF_ASH_BASH_COMPAT(int pos, len, orig_len;)
|
||||||
int saveherefd = herefd;
|
int saveherefd = herefd;
|
||||||
@ -6310,6 +6311,9 @@ subevalvar(char *p, char *str, int strloc, int subtype,
|
|||||||
int zero;
|
int zero;
|
||||||
char *(*scan)(char*, char*, char*, char*, int, int);
|
char *(*scan)(char*, char*, char*, char*, int, int);
|
||||||
|
|
||||||
|
//bb_error_msg("subevalvar(p:'%s',varname:'%s',strloc:%d,subtype:%d,startloc:%d,varflags:%x,quotes:%d",
|
||||||
|
// p, varname, strloc, subtype, startloc, varflags, quotes);
|
||||||
|
|
||||||
herefd = -1;
|
herefd = -1;
|
||||||
argstr(p, (subtype != VSASSIGN && subtype != VSQUESTION) ? EXP_CASE : 0,
|
argstr(p, (subtype != VSASSIGN && subtype != VSQUESTION) ? EXP_CASE : 0,
|
||||||
var_str_list);
|
var_str_list);
|
||||||
@ -6320,11 +6324,15 @@ subevalvar(char *p, char *str, int strloc, int subtype,
|
|||||||
|
|
||||||
switch (subtype) {
|
switch (subtype) {
|
||||||
case VSASSIGN:
|
case VSASSIGN:
|
||||||
setvar(str, startp, 0);
|
setvar(varname, startp, 0);
|
||||||
amount = startp - expdest;
|
amount = startp - expdest;
|
||||||
STADJUST(amount, expdest);
|
STADJUST(amount, expdest);
|
||||||
return startp;
|
return startp;
|
||||||
|
|
||||||
|
case VSQUESTION:
|
||||||
|
varunset(p, varname, startp, varflags);
|
||||||
|
/* NOTREACHED */
|
||||||
|
|
||||||
#if ENABLE_ASH_BASH_COMPAT
|
#if ENABLE_ASH_BASH_COMPAT
|
||||||
case VSSUBSTR:
|
case VSSUBSTR:
|
||||||
loc = str = stackblock() + strloc;
|
loc = str = stackblock() + strloc;
|
||||||
@ -6385,11 +6393,8 @@ subevalvar(char *p, char *str, int strloc, int subtype,
|
|||||||
STADJUST(amount, expdest);
|
STADJUST(amount, expdest);
|
||||||
return loc;
|
return loc;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
case VSQUESTION:
|
|
||||||
varunset(p, str, startp, varflags);
|
|
||||||
/* NOTREACHED */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
resetloc = expdest - (char *)stackblock();
|
resetloc = expdest - (char *)stackblock();
|
||||||
|
|
||||||
/* We'll comeback here if we grow the stack while handling
|
/* We'll comeback here if we grow the stack while handling
|
||||||
@ -6423,13 +6428,14 @@ subevalvar(char *p, char *str, int strloc, int subtype,
|
|||||||
|
|
||||||
if (!repl) {
|
if (!repl) {
|
||||||
repl = parse_sub_pattern(str, varflags & VSQUOTE);
|
repl = parse_sub_pattern(str, varflags & VSQUOTE);
|
||||||
|
//bb_error_msg("repl:'%s'", repl);
|
||||||
if (!repl)
|
if (!repl)
|
||||||
repl = nullstr;
|
repl = nullstr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If there's no pattern to match, return the expansion unmolested */
|
/* If there's no pattern to match, return the expansion unmolested */
|
||||||
if (str[0] == '\0')
|
if (str[0] == '\0')
|
||||||
return 0;
|
return NULL;
|
||||||
|
|
||||||
len = 0;
|
len = 0;
|
||||||
idx = startp;
|
idx = startp;
|
||||||
@ -6437,6 +6443,7 @@ subevalvar(char *p, char *str, int strloc, int subtype,
|
|||||||
while (idx < end) {
|
while (idx < end) {
|
||||||
try_to_match:
|
try_to_match:
|
||||||
loc = scanright(idx, rmesc, rmescend, str, quotes, 1);
|
loc = scanright(idx, rmesc, rmescend, str, quotes, 1);
|
||||||
|
//bb_error_msg("scanright('%s'):'%s'", str, loc);
|
||||||
if (!loc) {
|
if (!loc) {
|
||||||
/* No match, advance */
|
/* No match, advance */
|
||||||
char *restart_detect = stackblock();
|
char *restart_detect = stackblock();
|
||||||
@ -6475,6 +6482,7 @@ subevalvar(char *p, char *str, int strloc, int subtype,
|
|||||||
idx = loc;
|
idx = loc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//bb_error_msg("repl:'%s'", repl);
|
||||||
for (loc = (char*)repl; *loc; loc++) {
|
for (loc = (char*)repl; *loc; loc++) {
|
||||||
char *restart_detect = stackblock();
|
char *restart_detect = stackblock();
|
||||||
if (quotes && *loc == '\\') {
|
if (quotes && *loc == '\\') {
|
||||||
@ -6510,6 +6518,7 @@ subevalvar(char *p, char *str, int strloc, int subtype,
|
|||||||
STPUTC('\0', expdest);
|
STPUTC('\0', expdest);
|
||||||
startp = (char *)stackblock() + startloc;
|
startp = (char *)stackblock() + startloc;
|
||||||
memmove(startp, (char *)stackblock() + workloc, len + 1);
|
memmove(startp, (char *)stackblock() + workloc, len + 1);
|
||||||
|
//bb_error_msg("startp:'%s'", startp);
|
||||||
amount = expdest - (startp + len);
|
amount = expdest - (startp + len);
|
||||||
STADJUST(-amount, expdest);
|
STADJUST(-amount, expdest);
|
||||||
return startp;
|
return startp;
|
||||||
@ -6810,7 +6819,7 @@ evalvar(char *p, int flags, struct strlist *var_str_list)
|
|||||||
*/
|
*/
|
||||||
STPUTC('\0', expdest);
|
STPUTC('\0', expdest);
|
||||||
patloc = expdest - (char *)stackblock();
|
patloc = expdest - (char *)stackblock();
|
||||||
if (NULL == subevalvar(p, /* str: */ NULL, patloc, subtype,
|
if (NULL == subevalvar(p, /* varname: */ NULL, patloc, subtype,
|
||||||
startloc, varflags,
|
startloc, varflags,
|
||||||
//TODO: | EXP_REDIR too? All other such places do it too
|
//TODO: | EXP_REDIR too? All other such places do it too
|
||||||
/* quotes: */ flags & (EXP_FULL | EXP_CASE),
|
/* quotes: */ flags & (EXP_FULL | EXP_CASE),
|
||||||
@ -11114,8 +11123,11 @@ readtoken1(int c, int syntax, char *eofmark, int striptabs)
|
|||||||
USTPUTC('\\', out);
|
USTPUTC('\\', out);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (dblquote && c != '\\'
|
/* Backslash is retained if we are in "str" and next char isn't special */
|
||||||
&& c != '`' && c != '$'
|
if (dblquote
|
||||||
|
&& c != '\\'
|
||||||
|
&& c != '`'
|
||||||
|
&& c != '$'
|
||||||
&& (c != '"' || eofmark != NULL)
|
&& (c != '"' || eofmark != NULL)
|
||||||
) {
|
) {
|
||||||
USTPUTC(CTLESC, out);
|
USTPUTC(CTLESC, out);
|
||||||
@ -11380,8 +11392,6 @@ parsesub: {
|
|||||||
unsigned char subtype;
|
unsigned char subtype;
|
||||||
int typeloc;
|
int typeloc;
|
||||||
int flags;
|
int flags;
|
||||||
char *p;
|
|
||||||
static const char types[] ALIGN1 = "}-+?=";
|
|
||||||
|
|
||||||
c = pgetc();
|
c = pgetc();
|
||||||
if (c > 255 /* PEOA or PEOF */
|
if (c > 255 /* PEOA or PEOF */
|
||||||
@ -11394,7 +11404,8 @@ parsesub: {
|
|||||||
#endif
|
#endif
|
||||||
USTPUTC('$', out);
|
USTPUTC('$', out);
|
||||||
pungetc();
|
pungetc();
|
||||||
} else if (c == '(') { /* $(command) or $((arith)) */
|
} else if (c == '(') {
|
||||||
|
/* $(command) or $((arith)) */
|
||||||
if (pgetc() == '(') {
|
if (pgetc() == '(') {
|
||||||
#if ENABLE_SH_MATH_SUPPORT
|
#if ENABLE_SH_MATH_SUPPORT
|
||||||
PARSEARITH();
|
PARSEARITH();
|
||||||
@ -11406,6 +11417,7 @@ parsesub: {
|
|||||||
PARSEBACKQNEW();
|
PARSEBACKQNEW();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
/* $VAR, $<specialchar>, ${...}, or PEOA/PEOF */
|
||||||
USTPUTC(CTLVAR, out);
|
USTPUTC(CTLVAR, out);
|
||||||
typeloc = out - (char *)stackblock();
|
typeloc = out - (char *)stackblock();
|
||||||
USTPUTC(VSNORMAL, out);
|
USTPUTC(VSNORMAL, out);
|
||||||
@ -11415,76 +11427,85 @@ parsesub: {
|
|||||||
if (c == '#') {
|
if (c == '#') {
|
||||||
c = pgetc();
|
c = pgetc();
|
||||||
if (c == '}')
|
if (c == '}')
|
||||||
c = '#';
|
c = '#'; /* ${#} - same as $# */
|
||||||
else
|
else
|
||||||
subtype = VSLENGTH;
|
subtype = VSLENGTH; /* ${#VAR} */
|
||||||
} else
|
} else {
|
||||||
subtype = 0;
|
subtype = 0;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (c <= 255 /* not PEOA or PEOF */ && is_name(c)) {
|
if (c <= 255 /* not PEOA or PEOF */ && is_name(c)) {
|
||||||
|
/* $[{[#]]NAME[}] */
|
||||||
do {
|
do {
|
||||||
STPUTC(c, out);
|
STPUTC(c, out);
|
||||||
c = pgetc();
|
c = pgetc();
|
||||||
} while (c <= 255 /* not PEOA or PEOF */ && is_in_name(c));
|
} while (c <= 255 /* not PEOA or PEOF */ && is_in_name(c));
|
||||||
} else if (isdigit(c)) {
|
} else if (isdigit(c)) {
|
||||||
|
/* $[{[#]]NUM[}] */
|
||||||
do {
|
do {
|
||||||
STPUTC(c, out);
|
STPUTC(c, out);
|
||||||
c = pgetc();
|
c = pgetc();
|
||||||
} while (isdigit(c));
|
} while (isdigit(c));
|
||||||
} else if (is_special(c)) {
|
} else if (is_special(c)) {
|
||||||
|
/* $[{[#]]<specialchar>[}] */
|
||||||
USTPUTC(c, out);
|
USTPUTC(c, out);
|
||||||
c = pgetc();
|
c = pgetc();
|
||||||
} else {
|
} else {
|
||||||
badsub:
|
badsub:
|
||||||
raise_error_syntax("bad substitution");
|
raise_error_syntax("bad substitution");
|
||||||
}
|
}
|
||||||
if (c != '}' && subtype == VSLENGTH)
|
if (c != '}' && subtype == VSLENGTH) {
|
||||||
|
/* ${#VAR didn't end with } */
|
||||||
goto badsub;
|
goto badsub;
|
||||||
|
}
|
||||||
|
|
||||||
STPUTC('=', out);
|
STPUTC('=', out);
|
||||||
flags = 0;
|
flags = 0;
|
||||||
if (subtype == 0) {
|
if (subtype == 0) {
|
||||||
|
/* ${VAR...} but not $VAR or ${#VAR} */
|
||||||
|
/* c == first char after VAR */
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case ':':
|
case ':':
|
||||||
c = pgetc();
|
c = pgetc();
|
||||||
#if ENABLE_ASH_BASH_COMPAT
|
#if ENABLE_ASH_BASH_COMPAT
|
||||||
if (c == ':' || c == '$' || isdigit(c)) {
|
if (c == ':' || c == '$' || isdigit(c)) {
|
||||||
pungetc();
|
|
||||||
subtype = VSSUBSTR;
|
subtype = VSSUBSTR;
|
||||||
break;
|
pungetc();
|
||||||
|
break; /* "goto do_pungetc" is bigger (!) */
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
flags = VSNUL;
|
flags = VSNUL;
|
||||||
/*FALLTHROUGH*/
|
/*FALLTHROUGH*/
|
||||||
default:
|
default: {
|
||||||
p = strchr(types, c);
|
static const char types[] ALIGN1 = "}-+?=";
|
||||||
|
const char *p = strchr(types, c);
|
||||||
if (p == NULL)
|
if (p == NULL)
|
||||||
goto badsub;
|
goto badsub;
|
||||||
subtype = p - types + VSNORMAL;
|
subtype = p - types + VSNORMAL;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case '%':
|
case '%':
|
||||||
case '#': {
|
case '#': {
|
||||||
int cc = c;
|
int cc = c;
|
||||||
subtype = c == '#' ? VSTRIMLEFT : VSTRIMRIGHT;
|
subtype = (c == '#' ? VSTRIMLEFT : VSTRIMRIGHT);
|
||||||
c = pgetc();
|
c = pgetc();
|
||||||
if (c == cc)
|
if (c != cc)
|
||||||
|
goto do_pungetc;
|
||||||
subtype++;
|
subtype++;
|
||||||
else
|
|
||||||
pungetc();
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#if ENABLE_ASH_BASH_COMPAT
|
#if ENABLE_ASH_BASH_COMPAT
|
||||||
case '/':
|
case '/':
|
||||||
subtype = VSREPLACE;
|
subtype = VSREPLACE;
|
||||||
c = pgetc();
|
c = pgetc();
|
||||||
if (c == '/')
|
if (c != '/')
|
||||||
|
goto do_pungetc;
|
||||||
subtype++; /* VSREPLACEALL */
|
subtype++; /* VSREPLACEALL */
|
||||||
else
|
|
||||||
pungetc();
|
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
do_pungetc:
|
||||||
pungetc();
|
pungetc();
|
||||||
}
|
}
|
||||||
if (dblquote || arinest)
|
if (dblquote || arinest)
|
||||||
|
0
shell/ash_test/ash-redir/redir9.tests
Normal file → Executable file
0
shell/ash_test/ash-redir/redir9.tests
Normal file → Executable file
@ -1,20 +1,20 @@
|
|||||||
a041#c
|
1 a041#c
|
||||||
a041#c
|
2 a041#c
|
||||||
a\041#c
|
3 a\041#c
|
||||||
a\041#c
|
4 a\041#c
|
||||||
a\041#c
|
5 a\041#c
|
||||||
a\041#c
|
6 a\041#c
|
||||||
a\041#c
|
7 a\041#c
|
||||||
a\041#c
|
8 a\041#c
|
||||||
a\041#c
|
9 a\041#c
|
||||||
a\c
|
10 a\c
|
||||||
a\c
|
11 a\c
|
||||||
a\c
|
12 a\c
|
||||||
a\\c
|
13 a\\c
|
||||||
a\\c
|
14 a\\c
|
||||||
a\\c
|
15 a\\c
|
||||||
a\tc
|
16 a\tc
|
||||||
a\tc
|
17 a\tc
|
||||||
a\tc
|
18 a\tc
|
||||||
atc
|
19 atc
|
||||||
a\tc
|
20 a\tc
|
||||||
|
@ -1,41 +1,48 @@
|
|||||||
a='abc'
|
a='abc'
|
||||||
r=${a//b/\041#}
|
r=${a//b/\041#}
|
||||||
echo $r
|
echo 1 $r
|
||||||
echo ${a//b/\041#}
|
echo 2 ${a//b/\041#}
|
||||||
echo "${a//b/\041#}"
|
echo 3 "${a//b/\041#}"
|
||||||
|
# --- var_bash3.xx
|
||||||
|
# +++ var_bash3.right
|
||||||
|
# -1 a\041#c
|
||||||
|
# +1 a041#c
|
||||||
|
# 2 a041#c
|
||||||
|
# -3 a041#c
|
||||||
|
# +3 a\041#c
|
||||||
|
|
||||||
a='abc'
|
a='abc'
|
||||||
r=${a//b/\\041#}
|
r=${a//b/\\041#}
|
||||||
echo $r
|
echo 4 $r
|
||||||
echo ${a//b/\\041#}
|
echo 5 ${a//b/\\041#}
|
||||||
echo "${a//b/\\041#}"
|
echo 6 "${a//b/\\041#}"
|
||||||
|
|
||||||
a='abc'
|
a='abc'
|
||||||
b='\041#'
|
b='\041#'
|
||||||
r=${a//b/$b}
|
r=${a//b/$b}
|
||||||
echo $r
|
echo 7 $r
|
||||||
echo ${a//b/$b}
|
echo 8 ${a//b/$b}
|
||||||
echo "${a//b/$b}"
|
echo 9 "${a//b/$b}"
|
||||||
|
|
||||||
a='abc'
|
a='abc'
|
||||||
b='\'
|
b='\'
|
||||||
r="${a//b/$b}"
|
r="${a//b/$b}"
|
||||||
echo $r
|
echo 10 $r
|
||||||
echo ${a//b/$b}
|
echo 11 ${a//b/$b}
|
||||||
echo "${a//b/$b}"
|
echo 12 "${a//b/$b}"
|
||||||
|
|
||||||
a='abc'
|
a='abc'
|
||||||
b='\\'
|
b='\\'
|
||||||
r="${a//b/$b}"
|
r="${a//b/$b}"
|
||||||
echo $r
|
echo 13 $r
|
||||||
echo ${a//b/$b}
|
echo 14 ${a//b/$b}
|
||||||
echo "${a//b/$b}"
|
echo 15 "${a//b/$b}"
|
||||||
|
|
||||||
a='abc'
|
a='abc'
|
||||||
b='\t'
|
b='\t'
|
||||||
r="${a//b/$b}"
|
r="${a//b/$b}"
|
||||||
echo $r
|
echo 16 $r
|
||||||
echo ${a//b/$b}
|
echo 17 ${a//b/$b}
|
||||||
echo "${a//b/$b}"
|
echo 18 "${a//b/$b}"
|
||||||
echo ${a//b/\t}
|
echo 19 ${a//b/\t}
|
||||||
echo "${a//b/\t}"
|
echo 20 "${a//b/\t}"
|
||||||
|
2
shell/ash_test/ash-vars/var_bash4.right
Normal file
2
shell/ash_test/ash-vars/var_bash4.right
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
a*b-backslashstar-
|
||||||
|
Done: 0
|
3
shell/ash_test/ash-vars/var_bash4.tests
Executable file
3
shell/ash_test/ash-vars/var_bash4.tests
Executable file
@ -0,0 +1,3 @@
|
|||||||
|
FOO='a*b\*c'
|
||||||
|
echo "${FOO//\\*/-backslashstar-}"
|
||||||
|
echo Done: $?
|
Loading…
x
Reference in New Issue
Block a user