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:
Denys Vlasenko 2010-08-05 17:19:27 +02:00
parent e74d79866c
commit b0fbe4b540
6 changed files with 104 additions and 71 deletions

View File

@ -6296,13 +6296,14 @@ parse_sub_pattern(char *arg, int inquotes)
#endif /* ENABLE_ASH_BASH_COMPAT */
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)
{
struct nodelist *saveargbackq = argbackq;
char *startp;
char *loc;
char *rmesc, *rmescend;
char *str;
IF_ASH_BASH_COMPAT(const char *repl = NULL;)
IF_ASH_BASH_COMPAT(int pos, len, orig_len;)
int saveherefd = herefd;
@ -6310,6 +6311,9 @@ subevalvar(char *p, char *str, int strloc, int subtype,
int zero;
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;
argstr(p, (subtype != VSASSIGN && subtype != VSQUESTION) ? EXP_CASE : 0,
var_str_list);
@ -6320,11 +6324,15 @@ subevalvar(char *p, char *str, int strloc, int subtype,
switch (subtype) {
case VSASSIGN:
setvar(str, startp, 0);
setvar(varname, startp, 0);
amount = startp - expdest;
STADJUST(amount, expdest);
return startp;
case VSQUESTION:
varunset(p, varname, startp, varflags);
/* NOTREACHED */
#if ENABLE_ASH_BASH_COMPAT
case VSSUBSTR:
loc = str = stackblock() + strloc;
@ -6385,11 +6393,8 @@ subevalvar(char *p, char *str, int strloc, int subtype,
STADJUST(amount, expdest);
return loc;
#endif
case VSQUESTION:
varunset(p, str, startp, varflags);
/* NOTREACHED */
}
resetloc = expdest - (char *)stackblock();
/* 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) {
repl = parse_sub_pattern(str, varflags & VSQUOTE);
//bb_error_msg("repl:'%s'", repl);
if (!repl)
repl = nullstr;
}
/* If there's no pattern to match, return the expansion unmolested */
if (str[0] == '\0')
return 0;
return NULL;
len = 0;
idx = startp;
@ -6437,6 +6443,7 @@ subevalvar(char *p, char *str, int strloc, int subtype,
while (idx < end) {
try_to_match:
loc = scanright(idx, rmesc, rmescend, str, quotes, 1);
//bb_error_msg("scanright('%s'):'%s'", str, loc);
if (!loc) {
/* No match, advance */
char *restart_detect = stackblock();
@ -6475,6 +6482,7 @@ subevalvar(char *p, char *str, int strloc, int subtype,
idx = loc;
}
//bb_error_msg("repl:'%s'", repl);
for (loc = (char*)repl; *loc; loc++) {
char *restart_detect = stackblock();
if (quotes && *loc == '\\') {
@ -6510,6 +6518,7 @@ subevalvar(char *p, char *str, int strloc, int subtype,
STPUTC('\0', expdest);
startp = (char *)stackblock() + startloc;
memmove(startp, (char *)stackblock() + workloc, len + 1);
//bb_error_msg("startp:'%s'", startp);
amount = expdest - (startp + len);
STADJUST(-amount, expdest);
return startp;
@ -6810,7 +6819,7 @@ evalvar(char *p, int flags, struct strlist *var_str_list)
*/
STPUTC('\0', expdest);
patloc = expdest - (char *)stackblock();
if (NULL == subevalvar(p, /* str: */ NULL, patloc, subtype,
if (NULL == subevalvar(p, /* varname: */ NULL, patloc, subtype,
startloc, varflags,
//TODO: | EXP_REDIR too? All other such places do it too
/* quotes: */ flags & (EXP_FULL | EXP_CASE),
@ -11114,8 +11123,11 @@ readtoken1(int c, int syntax, char *eofmark, int striptabs)
USTPUTC('\\', out);
}
#endif
if (dblquote && c != '\\'
&& c != '`' && c != '$'
/* Backslash is retained if we are in "str" and next char isn't special */
if (dblquote
&& c != '\\'
&& c != '`'
&& c != '$'
&& (c != '"' || eofmark != NULL)
) {
USTPUTC(CTLESC, out);
@ -11380,8 +11392,6 @@ parsesub: {
unsigned char subtype;
int typeloc;
int flags;
char *p;
static const char types[] ALIGN1 = "}-+?=";
c = pgetc();
if (c > 255 /* PEOA or PEOF */
@ -11394,7 +11404,8 @@ parsesub: {
#endif
USTPUTC('$', out);
pungetc();
} else if (c == '(') { /* $(command) or $((arith)) */
} else if (c == '(') {
/* $(command) or $((arith)) */
if (pgetc() == '(') {
#if ENABLE_SH_MATH_SUPPORT
PARSEARITH();
@ -11406,6 +11417,7 @@ parsesub: {
PARSEBACKQNEW();
}
} else {
/* $VAR, $<specialchar>, ${...}, or PEOA/PEOF */
USTPUTC(CTLVAR, out);
typeloc = out - (char *)stackblock();
USTPUTC(VSNORMAL, out);
@ -11415,76 +11427,85 @@ parsesub: {
if (c == '#') {
c = pgetc();
if (c == '}')
c = '#';
c = '#'; /* ${#} - same as $# */
else
subtype = VSLENGTH;
} else
subtype = VSLENGTH; /* ${#VAR} */
} else {
subtype = 0;
}
}
if (c <= 255 /* not PEOA or PEOF */ && is_name(c)) {
/* $[{[#]]NAME[}] */
do {
STPUTC(c, out);
c = pgetc();
} while (c <= 255 /* not PEOA or PEOF */ && is_in_name(c));
} else if (isdigit(c)) {
/* $[{[#]]NUM[}] */
do {
STPUTC(c, out);
c = pgetc();
} while (isdigit(c));
} else if (is_special(c)) {
/* $[{[#]]<specialchar>[}] */
USTPUTC(c, out);
c = pgetc();
} else {
badsub:
raise_error_syntax("bad substitution");
}
if (c != '}' && subtype == VSLENGTH)
if (c != '}' && subtype == VSLENGTH) {
/* ${#VAR didn't end with } */
goto badsub;
}
STPUTC('=', out);
flags = 0;
if (subtype == 0) {
/* ${VAR...} but not $VAR or ${#VAR} */
/* c == first char after VAR */
switch (c) {
case ':':
c = pgetc();
#if ENABLE_ASH_BASH_COMPAT
if (c == ':' || c == '$' || isdigit(c)) {
pungetc();
subtype = VSSUBSTR;
break;
pungetc();
break; /* "goto do_pungetc" is bigger (!) */
}
#endif
flags = VSNUL;
/*FALLTHROUGH*/
default:
p = strchr(types, c);
default: {
static const char types[] ALIGN1 = "}-+?=";
const char *p = strchr(types, c);
if (p == NULL)
goto badsub;
subtype = p - types + VSNORMAL;
break;
}
case '%':
case '#': {
int cc = c;
subtype = c == '#' ? VSTRIMLEFT : VSTRIMRIGHT;
subtype = (c == '#' ? VSTRIMLEFT : VSTRIMRIGHT);
c = pgetc();
if (c == cc)
if (c != cc)
goto do_pungetc;
subtype++;
else
pungetc();
break;
}
#if ENABLE_ASH_BASH_COMPAT
case '/':
subtype = VSREPLACE;
c = pgetc();
if (c == '/')
if (c != '/')
goto do_pungetc;
subtype++; /* VSREPLACEALL */
else
pungetc();
break;
#endif
}
} else {
do_pungetc:
pungetc();
}
if (dblquote || arinest)

0
shell/ash_test/ash-redir/redir9.tests Normal file → Executable file
View File

View File

@ -1,20 +1,20 @@
a041#c
a041#c
a\041#c
a\041#c
a\041#c
a\041#c
a\041#c
a\041#c
a\041#c
a\c
a\c
a\c
a\\c
a\\c
a\\c
a\tc
a\tc
a\tc
atc
a\tc
1 a041#c
2 a041#c
3 a\041#c
4 a\041#c
5 a\041#c
6 a\041#c
7 a\041#c
8 a\041#c
9 a\041#c
10 a\c
11 a\c
12 a\c
13 a\\c
14 a\\c
15 a\\c
16 a\tc
17 a\tc
18 a\tc
19 atc
20 a\tc

View File

@ -1,41 +1,48 @@
a='abc'
r=${a//b/\041#}
echo $r
echo ${a//b/\041#}
echo "${a//b/\041#}"
echo 1 $r
echo 2 ${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'
r=${a//b/\\041#}
echo $r
echo ${a//b/\\041#}
echo "${a//b/\\041#}"
echo 4 $r
echo 5 ${a//b/\\041#}
echo 6 "${a//b/\\041#}"
a='abc'
b='\041#'
r=${a//b/$b}
echo $r
echo ${a//b/$b}
echo "${a//b/$b}"
echo 7 $r
echo 8 ${a//b/$b}
echo 9 "${a//b/$b}"
a='abc'
b='\'
r="${a//b/$b}"
echo $r
echo ${a//b/$b}
echo "${a//b/$b}"
echo 10 $r
echo 11 ${a//b/$b}
echo 12 "${a//b/$b}"
a='abc'
b='\\'
r="${a//b/$b}"
echo $r
echo ${a//b/$b}
echo "${a//b/$b}"
echo 13 $r
echo 14 ${a//b/$b}
echo 15 "${a//b/$b}"
a='abc'
b='\t'
r="${a//b/$b}"
echo $r
echo ${a//b/$b}
echo "${a//b/$b}"
echo ${a//b/\t}
echo "${a//b/\t}"
echo 16 $r
echo 17 ${a//b/$b}
echo 18 "${a//b/$b}"
echo 19 ${a//b/\t}
echo 20 "${a//b/\t}"

View File

@ -0,0 +1,2 @@
a*b-backslashstar-
Done: 0

View File

@ -0,0 +1,3 @@
FOO='a*b\*c'
echo "${FOO//\\*/-backslashstar-}"
echo Done: $?