OSDN Git Service

ash: add a testcase for bug 2281 (currently fails). Small code cleanups.
authorDenys Vlasenko <vda.linux@googlemail.com>
Thu, 5 Aug 2010 15:19:27 +0000 (17:19 +0200)
committerDenys Vlasenko <vda.linux@googlemail.com>
Thu, 5 Aug 2010 15:19:27 +0000 (17:19 +0200)
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>
shell/ash.c
shell/ash_test/ash-redir/redir9.tests [changed mode: 0644->0755]
shell/ash_test/ash-vars/var_bash3.right
shell/ash_test/ash-vars/var_bash3.tests
shell/ash_test/ash-vars/var_bash4.right [new file with mode: 0644]
shell/ash_test/ash-vars/var_bash4.tests [new file with mode: 0755]

index d8becc3..16783f2 100644 (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);
@@ -11187,7 +11199,7 @@ readtoken1(int c, int syntax, char *eofmark, int striptabs)
                                        } else {
                                                /*
                                                 * unbalanced parens
-                                                *  (don't 2nd guess - no error)
+                                                * (don't 2nd guess - no error)
                                                 */
                                                pungetc();
                                                USTPUTC(')', 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)
-                                       subtype++;
-                               else
-                                       pungetc();
+                               if (c != cc)
+                                       goto do_pungetc;
+                               subtype++;
                                break;
                        }
 #if ENABLE_ASH_BASH_COMPAT
                        case '/':
                                subtype = VSREPLACE;
                                c = pgetc();
-                               if (c == '/')
-                                       subtype++; /* VSREPLACEALL */
-                               else
-                                       pungetc();
+                               if (c != '/')
+                                       goto do_pungetc;
+                               subtype++; /* VSREPLACEALL */
                                break;
 #endif
                        }
                } else {
+ do_pungetc:
                        pungetc();
                }
                if (dblquote || arinest)
old mode 100644 (file)
new mode 100755 (executable)
index f7f1479..a97c850 100644 (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
+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
+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
index b905027..eca3318 100755 (executable)
@@ -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 $r
+echo ${a//b/\\041#}
+echo "${a//b/\\041#}"
 
 a='abc'
 b='\041#'
 r=${a//b/$b}
-echo $r
-echo ${a//b/$b}
-echo "${a//b/$b}"
+echo $r
+echo ${a//b/$b}
+echo "${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}"
diff --git a/shell/ash_test/ash-vars/var_bash4.right b/shell/ash_test/ash-vars/var_bash4.right
new file mode 100644 (file)
index 0000000..33a5112
--- /dev/null
@@ -0,0 +1,2 @@
+a*b-backslashstar-
+Done: 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 (executable)
index 0000000..304b3d9
--- /dev/null
@@ -0,0 +1,3 @@
+FOO='a*b\*c'
+echo "${FOO//\\*/-backslashstar-}"
+echo Done: $?