aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2008-06-14 06:04:59 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2008-06-14 06:04:59 +0000
commit2659c63213fa3592aa1ef5eca356c7332bbb7f42 (patch)
tree5dad6f9a3c219cfccfa5adf4ff5c59728d303fd1
parenta1767a1f5d744804958b2ef0516cbd5d33292c0c (diff)
downloadbusybox-w32-2659c63213fa3592aa1ef5eca356c7332bbb7f42.tar.gz
busybox-w32-2659c63213fa3592aa1ef5eca356c7332bbb7f42.tar.bz2
busybox-w32-2659c63213fa3592aa1ef5eca356c7332bbb7f42.zip
ash: fix ${var/s/r} handling, add testcase.
-rw-r--r--shell/ash.c75
-rw-r--r--shell/ash_test/ash-vars/var_bash3.right20
-rwxr-xr-xshell/ash_test/ash-vars/var_bash3.tests41
3 files changed, 75 insertions, 61 deletions
diff --git a/shell/ash.c b/shell/ash.c
index a8428b9dc..0913a2f41 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -5818,73 +5818,26 @@ parse_sub_pattern(char *arg, int inquotes)
5818 char *idx, *repl = NULL; 5818 char *idx, *repl = NULL;
5819 unsigned char c; 5819 unsigned char c;
5820 5820
5821 for (idx = arg; *arg; arg++) { 5821 idx = arg;
5822 if (*arg == '/') { 5822 while (1) {
5823 /* Only the first '/' seen is our seperator */ 5823 c = *arg;
5824 if (!c)
5825 break;
5826 if (c == '/') {
5827 /* Only the first '/' seen is our separator */
5824 if (!repl) { 5828 if (!repl) {
5825 *idx++ = '\0'; 5829 repl = idx + 1;
5826 repl = idx; 5830 c = '\0';
5827 } else
5828 *idx++ = *arg;
5829 } else if (*arg != '\\') {
5830 *idx++ = *arg;
5831 } else {
5832 if (inquotes)
5833 arg++;
5834 else {
5835 if (*(arg + 1) != '\\')
5836 goto single_backslash;
5837 arg += 2;
5838 }
5839
5840 switch (*arg) {
5841 case 'n': c = '\n'; break;
5842 case 'r': c = '\r'; break;
5843 case 't': c = '\t'; break;
5844 case 'v': c = '\v'; break;
5845 case 'f': c = '\f'; break;
5846 case 'b': c = '\b'; break;
5847 case 'a': c = '\a'; break;
5848 case '\\':
5849 if (*(arg + 1) != '\\' && !inquotes)
5850 goto single_backslash;
5851 arg++;
5852 /* FALLTHROUGH */
5853 case '\0':
5854 /* Trailing backslash, just stuff one in the buffer
5855 * and backup arg so the loop will exit.
5856 */
5857 c = '\\';
5858 if (!*arg)
5859 arg--;
5860 break;
5861 default:
5862 c = *arg;
5863 if (isdigit(c)) {
5864 /* It's an octal number, parse it. */
5865 int i;
5866 c = 0;
5867
5868 for (i = 0; *arg && i < 3; arg++, i++) {
5869 if (*arg >= '8' || *arg < '0')
5870 ash_msg_and_raise_error("Invalid octal char in pattern");
5871// TODO: number() instead? It does error checking...
5872 c = (c << 3) + atoi(arg);
5873 }
5874 /* back off one (so outer loop can do it) */
5875 arg--;
5876 }
5877 } 5831 }
5878 *idx++ = c;
5879 } 5832 }
5833 *idx++ = c;
5834 if (!inquotes && c == '\\' && arg[1] == '\\')
5835 arg++; /* skip both \\, not just first one */
5836 arg++;
5880 } 5837 }
5881 *idx = *arg; 5838 *idx++ = c;
5882 5839
5883 return repl; 5840 return repl;
5884
5885 single_backslash:
5886 ash_msg_and_raise_error("single backslash unexpected");
5887 /* NOTREACHED */
5888} 5841}
5889#endif /* ENABLE_ASH_BASH_COMPAT */ 5842#endif /* ENABLE_ASH_BASH_COMPAT */
5890 5843
diff --git a/shell/ash_test/ash-vars/var_bash3.right b/shell/ash_test/ash-vars/var_bash3.right
new file mode 100644
index 000000000..f7f14791e
--- /dev/null
+++ b/shell/ash_test/ash-vars/var_bash3.right
@@ -0,0 +1,20 @@
1a041#c
2a041#c
3a\041#c
4a\041#c
5a\041#c
6a\041#c
7a\041#c
8a\041#c
9a\041#c
10a\c
11a\c
12a\c
13a\\c
14a\\c
15a\\c
16a\tc
17a\tc
18a\tc
19atc
20a\tc
diff --git a/shell/ash_test/ash-vars/var_bash3.tests b/shell/ash_test/ash-vars/var_bash3.tests
new file mode 100755
index 000000000..b9050279e
--- /dev/null
+++ b/shell/ash_test/ash-vars/var_bash3.tests
@@ -0,0 +1,41 @@
1a='abc'
2r=${a//b/\041#}
3echo $r
4echo ${a//b/\041#}
5echo "${a//b/\041#}"
6
7a='abc'
8r=${a//b/\\041#}
9echo $r
10echo ${a//b/\\041#}
11echo "${a//b/\\041#}"
12
13a='abc'
14b='\041#'
15r=${a//b/$b}
16echo $r
17echo ${a//b/$b}
18echo "${a//b/$b}"
19
20a='abc'
21b='\'
22r="${a//b/$b}"
23echo $r
24echo ${a//b/$b}
25echo "${a//b/$b}"
26
27a='abc'
28b='\\'
29r="${a//b/$b}"
30echo $r
31echo ${a//b/$b}
32echo "${a//b/$b}"
33
34a='abc'
35b='\t'
36r="${a//b/$b}"
37echo $r
38echo ${a//b/$b}
39echo "${a//b/$b}"
40echo ${a//b/\t}
41echo "${a//b/\t}"