diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2007-11-13 16:48:10 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2007-11-13 16:48:10 +0000 |
commit | 40276648ab31822068c3408ae43a5ecaafd03a5c (patch) | |
tree | a10fa0510807ec1d784aae112c512ef40b1922ac | |
parent | 6df9e3c9a38095c0c56728a81926aca53d28733f (diff) | |
download | busybox-w32-40276648ab31822068c3408ae43a5ecaafd03a5c.tar.gz busybox-w32-40276648ab31822068c3408ae43a5ecaafd03a5c.tar.bz2 busybox-w32-40276648ab31822068c3408ae43a5ecaafd03a5c.zip |
sed: support GNU-like '\t' escape in substitutions
-rw-r--r-- | editors/sed.c | 14 | ||||
-rw-r--r-- | testsuite/README | 4 | ||||
-rwxr-xr-x | testsuite/sed.tests | 1 |
3 files changed, 13 insertions, 6 deletions
diff --git a/editors/sed.c b/editors/sed.c index f75fceea5..0f5cab2b7 100644 --- a/editors/sed.c +++ b/editors/sed.c | |||
@@ -173,7 +173,7 @@ static void cleanup_outname(void) | |||
173 | if (G.outname) unlink(G.outname); | 173 | if (G.outname) unlink(G.outname); |
174 | } | 174 | } |
175 | 175 | ||
176 | /* strdup, replacing "\n" with '\n', and "\delimiter" with 'delimiter' */ | 176 | /* strcpy, replacing "\from" with 'to'. If to is NUL, replacing "\any" with 'any' */ |
177 | 177 | ||
178 | static void parse_escapes(char *dest, const char *string, int len, char from, char to) | 178 | static void parse_escapes(char *dest, const char *string, int len, char from, char to) |
179 | { | 179 | { |
@@ -188,9 +188,10 @@ static void parse_escapes(char *dest, const char *string, int len, char from, ch | |||
188 | } | 188 | } |
189 | *dest++ = string[i++]; | 189 | *dest++ = string[i++]; |
190 | } | 190 | } |
191 | /* TODO: is it safe wrt a string with trailing '\\' ? */ | ||
191 | *dest++ = string[i++]; | 192 | *dest++ = string[i++]; |
192 | } | 193 | } |
193 | *dest = 0; | 194 | *dest = '\0'; |
194 | } | 195 | } |
195 | 196 | ||
196 | static char *copy_parsing_escapes(const char *string, int len) | 197 | static char *copy_parsing_escapes(const char *string, int len) |
@@ -198,6 +199,8 @@ static char *copy_parsing_escapes(const char *string, int len) | |||
198 | char *dest = xmalloc(len + 1); | 199 | char *dest = xmalloc(len + 1); |
199 | 200 | ||
200 | parse_escapes(dest, string, len, 'n', '\n'); | 201 | parse_escapes(dest, string, len, 'n', '\n'); |
202 | /* GNU sed also recognizes \t */ | ||
203 | parse_escapes(dest, dest, strlen(dest), 't', '\t'); | ||
201 | return dest; | 204 | return dest; |
202 | } | 205 | } |
203 | 206 | ||
@@ -205,7 +208,7 @@ static char *copy_parsing_escapes(const char *string, int len) | |||
205 | /* | 208 | /* |
206 | * index_of_next_unescaped_regexp_delim - walks left to right through a string | 209 | * index_of_next_unescaped_regexp_delim - walks left to right through a string |
207 | * beginning at a specified index and returns the index of the next regular | 210 | * beginning at a specified index and returns the index of the next regular |
208 | * expression delimiter (typically a forward * slash ('/')) not preceded by | 211 | * expression delimiter (typically a forward slash ('/')) not preceded by |
209 | * a backslash ('\'). A negative delimiter disables square bracket checking. | 212 | * a backslash ('\'). A negative delimiter disables square bracket checking. |
210 | */ | 213 | */ |
211 | static int index_of_next_unescaped_regexp_delim(int delimiter, const char *str) | 214 | static int index_of_next_unescaped_regexp_delim(int delimiter, const char *str) |
@@ -425,7 +428,8 @@ static const char *parse_cmd_args(sed_cmd_t *sed_cmd, const char *cmdstr) | |||
425 | break; | 428 | break; |
426 | } | 429 | } |
427 | sed_cmd->string = xstrdup(cmdstr); | 430 | sed_cmd->string = xstrdup(cmdstr); |
428 | parse_escapes(sed_cmd->string, sed_cmd->string, strlen(cmdstr), 0, 0); | 431 | /* "\anychar" -> "anychar" */ |
432 | parse_escapes(sed_cmd->string, sed_cmd->string, strlen(cmdstr), '\0', '\0'); | ||
429 | cmdstr += strlen(cmdstr); | 433 | cmdstr += strlen(cmdstr); |
430 | /* handle file cmds: (r)ead */ | 434 | /* handle file cmds: (r)ead */ |
431 | } else if (strchr("rw", sed_cmd->cmd)) { | 435 | } else if (strchr("rw", sed_cmd->cmd)) { |
@@ -1337,7 +1341,7 @@ int sed_main(int argc, char **argv) | |||
1337 | // FIXME: error check / message? | 1341 | // FIXME: error check / message? |
1338 | rename(G.outname, argv[i]); | 1342 | rename(G.outname, argv[i]); |
1339 | free(G.outname); | 1343 | free(G.outname); |
1340 | G.outname = 0; | 1344 | G.outname = NULL; |
1341 | } | 1345 | } |
1342 | if (G.input_file_count > G.current_input_file) | 1346 | if (G.input_file_count > G.current_input_file) |
1343 | process_files(); | 1347 | process_files(); |
diff --git a/testsuite/README b/testsuite/README index 377f20ef8..a44846dbb 100644 --- a/testsuite/README +++ b/testsuite/README | |||
@@ -4,7 +4,9 @@ Update: doesn't work as described. Try "make check" from parent dir... | |||
4 | To run the test suite, change to this directory and run "./runtest". It will | 4 | To run the test suite, change to this directory and run "./runtest". It will |
5 | run all of the test cases, and list those with unexpected outcomes. Adding the | 5 | run all of the test cases, and list those with unexpected outcomes. Adding the |
6 | -v option will cause it to show expected outcomes as well. To only run the test | 6 | -v option will cause it to show expected outcomes as well. To only run the test |
7 | cases for particular applets, specify them as parameters to runtest. | 7 | cases for particular applets: |
8 | |||
9 | ./runtest <applet1> <applet2>... | ||
8 | 10 | ||
9 | The test cases for an applet reside in the subdirectory of the applet name. The | 11 | The test cases for an applet reside in the subdirectory of the applet name. The |
10 | name of the test case should be the assertion that is tested. The test case | 12 | name of the test case should be the assertion that is tested. The test case |
diff --git a/testsuite/sed.tests b/testsuite/sed.tests index a054de6d7..7471ed5fc 100755 --- a/testsuite/sed.tests +++ b/testsuite/sed.tests | |||
@@ -57,6 +57,7 @@ testing "sed s arbitrary delimiter" "sed -e 's woo boing '" "boing\n" "" "woo\n" | |||
57 | testing "sed s chains" "sed -e s/foo/bar/ -e s/bar/baz/" "baz\n" "" "foo\n" | 57 | testing "sed s chains" "sed -e s/foo/bar/ -e s/bar/baz/" "baz\n" "" "foo\n" |
58 | testing "sed s chains2" "sed -e s/foo/bar/ -e s/baz/nee/" "bar\n" "" "foo\n" | 58 | testing "sed s chains2" "sed -e s/foo/bar/ -e s/baz/nee/" "bar\n" "" "foo\n" |
59 | testing "sed s [delimiter]" "sed -e 's@[@]@@'" "onetwo" "" "one@two" | 59 | testing "sed s [delimiter]" "sed -e 's@[@]@@'" "onetwo" "" "one@two" |
60 | testing "sed s with \\t (GNU ext)" "sed 's/\t/ /'" "one two" "" "one\ttwo" | ||
60 | 61 | ||
61 | # branch | 62 | # branch |
62 | testing "sed b (branch)" "sed -e 'b one;p;: one'" "foo\n" "" "foo\n" | 63 | testing "sed b (branch)" "sed -e 'b one;p;: one'" "foo\n" "" "foo\n" |