diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2008-06-14 06:04:59 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2008-06-14 06:04:59 +0000 |
commit | 2659c63213fa3592aa1ef5eca356c7332bbb7f42 (patch) | |
tree | 5dad6f9a3c219cfccfa5adf4ff5c59728d303fd1 | |
parent | a1767a1f5d744804958b2ef0516cbd5d33292c0c (diff) | |
download | busybox-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.c | 75 | ||||
-rw-r--r-- | shell/ash_test/ash-vars/var_bash3.right | 20 | ||||
-rwxr-xr-x | shell/ash_test/ash-vars/var_bash3.tests | 41 |
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 @@ | |||
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 | ||
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 @@ | |||
1 | a='abc' | ||
2 | r=${a//b/\041#} | ||
3 | echo $r | ||
4 | echo ${a//b/\041#} | ||
5 | echo "${a//b/\041#}" | ||
6 | |||
7 | a='abc' | ||
8 | r=${a//b/\\041#} | ||
9 | echo $r | ||
10 | echo ${a//b/\\041#} | ||
11 | echo "${a//b/\\041#}" | ||
12 | |||
13 | a='abc' | ||
14 | b='\041#' | ||
15 | r=${a//b/$b} | ||
16 | echo $r | ||
17 | echo ${a//b/$b} | ||
18 | echo "${a//b/$b}" | ||
19 | |||
20 | a='abc' | ||
21 | b='\' | ||
22 | r="${a//b/$b}" | ||
23 | echo $r | ||
24 | echo ${a//b/$b} | ||
25 | echo "${a//b/$b}" | ||
26 | |||
27 | a='abc' | ||
28 | b='\\' | ||
29 | r="${a//b/$b}" | ||
30 | echo $r | ||
31 | echo ${a//b/$b} | ||
32 | echo "${a//b/$b}" | ||
33 | |||
34 | a='abc' | ||
35 | b='\t' | ||
36 | r="${a//b/$b}" | ||
37 | echo $r | ||
38 | echo ${a//b/$b} | ||
39 | echo "${a//b/$b}" | ||
40 | echo ${a//b/\t} | ||
41 | echo "${a//b/\t}" | ||