aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2007-11-13 16:48:10 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2007-11-13 16:48:10 +0000
commit40276648ab31822068c3408ae43a5ecaafd03a5c (patch)
treea10fa0510807ec1d784aae112c512ef40b1922ac
parent6df9e3c9a38095c0c56728a81926aca53d28733f (diff)
downloadbusybox-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.c14
-rw-r--r--testsuite/README4
-rwxr-xr-xtestsuite/sed.tests1
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
178static void parse_escapes(char *dest, const char *string, int len, char from, char to) 178static 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
196static char *copy_parsing_escapes(const char *string, int len) 197static 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 */
211static int index_of_next_unescaped_regexp_delim(int delimiter, const char *str) 214static 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...
4To run the test suite, change to this directory and run "./runtest". It will 4To run the test suite, change to this directory and run "./runtest". It will
5run all of the test cases, and list those with unexpected outcomes. Adding the 5run 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
7cases for particular applets, specify them as parameters to runtest. 7cases for particular applets:
8
9./runtest <applet1> <applet2>...
8 10
9The test cases for an applet reside in the subdirectory of the applet name. The 11The test cases for an applet reside in the subdirectory of the applet name. The
10name of the test case should be the assertion that is tested. The test case 12name 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"
57testing "sed s chains" "sed -e s/foo/bar/ -e s/bar/baz/" "baz\n" "" "foo\n" 57testing "sed s chains" "sed -e s/foo/bar/ -e s/bar/baz/" "baz\n" "" "foo\n"
58testing "sed s chains2" "sed -e s/foo/bar/ -e s/baz/nee/" "bar\n" "" "foo\n" 58testing "sed s chains2" "sed -e s/foo/bar/ -e s/baz/nee/" "bar\n" "" "foo\n"
59testing "sed s [delimiter]" "sed -e 's@[@]@@'" "onetwo" "" "one@two" 59testing "sed s [delimiter]" "sed -e 's@[@]@@'" "onetwo" "" "one@two"
60testing "sed s with \\t (GNU ext)" "sed 's/\t/ /'" "one two" "" "one\ttwo"
60 61
61# branch 62# branch
62testing "sed b (branch)" "sed -e 'b one;p;: one'" "foo\n" "" "foo\n" 63testing "sed b (branch)" "sed -e 'b one;p;: one'" "foo\n" "" "foo\n"