diff options
author | Rob Landley <rob@landley.net> | 2006-07-26 17:25:08 +0000 |
---|---|---|
committer | Rob Landley <rob@landley.net> | 2006-07-26 17:25:08 +0000 |
commit | 4795e4e011f1a146a2a4aa06a006fff5641befb5 (patch) | |
tree | 6185ef8c9dfc1f24c094d5262b745119f6400402 | |
parent | 7cc6b69bb09d2242493b7c4d882af958254e0cc7 (diff) | |
download | busybox-w32-4795e4e011f1a146a2a4aa06a006fff5641befb5.tar.gz busybox-w32-4795e4e011f1a146a2a4aa06a006fff5641befb5.tar.bz2 busybox-w32-4795e4e011f1a146a2a4aa06a006fff5641befb5.zip |
Rich Filker spotted that sed -e 's/xxx/[/' didn't work right. Did a smaller
fix than his, and shrank the code a bit on top of that so the net size is
smaller, and added a test to the test suite for this case. Plus I cleaned up
the #includes and removed unnecessary "const"s while I was there.
-rw-r--r-- | editors/sed.c | 58 | ||||
-rwxr-xr-x | testsuite/sed.tests | 2 |
2 files changed, 25 insertions, 35 deletions
diff --git a/editors/sed.c b/editors/sed.c index ed584e5df..89b8dd72c 100644 --- a/editors/sed.c +++ b/editors/sed.c | |||
@@ -58,12 +58,6 @@ | |||
58 | Reference http://www.opengroup.org/onlinepubs/007904975/utilities/sed.html | 58 | Reference http://www.opengroup.org/onlinepubs/007904975/utilities/sed.html |
59 | */ | 59 | */ |
60 | 60 | ||
61 | #include <stdio.h> | ||
62 | #include <unistd.h> /* for getopt() */ | ||
63 | #include <errno.h> | ||
64 | #include <ctype.h> /* for isspace() */ | ||
65 | #include <stdlib.h> | ||
66 | #include <string.h> | ||
67 | #include "busybox.h" | 61 | #include "busybox.h" |
68 | #include "xregex.h" | 62 | #include "xregex.h" |
69 | 63 | ||
@@ -94,8 +88,6 @@ typedef struct sed_cmd_s { | |||
94 | struct sed_cmd_s *next; /* Next command (linked list, NULL terminated) */ | 88 | struct sed_cmd_s *next; /* Next command (linked list, NULL terminated) */ |
95 | } sed_cmd_t; | 89 | } sed_cmd_t; |
96 | 90 | ||
97 | static const char bad_format_in_subst[] = | ||
98 | "bad format in substitution expression"; | ||
99 | static const char *const semicolon_whitespace = "; \n\r\t\v"; | 91 | static const char *const semicolon_whitespace = "; \n\r\t\v"; |
100 | 92 | ||
101 | struct sed_globals | 93 | struct sed_globals |
@@ -175,7 +167,7 @@ static void cleanup_outname(void) | |||
175 | 167 | ||
176 | /* strdup, replacing "\n" with '\n', and "\delimiter" with 'delimiter' */ | 168 | /* strdup, replacing "\n" with '\n', and "\delimiter" with 'delimiter' */ |
177 | 169 | ||
178 | static void parse_escapes(char *dest, const char *string, int len, char from, char to) | 170 | static void parse_escapes(char *dest, char *string, int len, char from, char to) |
179 | { | 171 | { |
180 | int i=0; | 172 | int i=0; |
181 | 173 | ||
@@ -192,7 +184,7 @@ static void parse_escapes(char *dest, const char *string, int len, char from, ch | |||
192 | *dest=0; | 184 | *dest=0; |
193 | } | 185 | } |
194 | 186 | ||
195 | static char *copy_parsing_escapes(const char *string, int len) | 187 | static char *copy_parsing_escapes(char *string, int len) |
196 | { | 188 | { |
197 | char *dest=xmalloc(len+1); | 189 | char *dest=xmalloc(len+1); |
198 | 190 | ||
@@ -205,18 +197,22 @@ static char *copy_parsing_escapes(const char *string, int len) | |||
205 | * index_of_next_unescaped_regexp_delim - walks left to right through a string | 197 | * index_of_next_unescaped_regexp_delim - walks left to right through a string |
206 | * beginning at a specified index and returns the index of the next regular | 198 | * beginning at a specified index and returns the index of the next regular |
207 | * expression delimiter (typically a forward * slash ('/')) not preceded by | 199 | * expression delimiter (typically a forward * slash ('/')) not preceded by |
208 | * a backslash ('\'). | 200 | * a backslash ('\'). A negative delimiter disables square bracket checking. |
209 | */ | 201 | */ |
210 | static int index_of_next_unescaped_regexp_delim(const char delimiter, | 202 | static int index_of_next_unescaped_regexp_delim(int delimiter, char *str) |
211 | const char *str) | ||
212 | { | 203 | { |
213 | int bracket = -1; | 204 | int bracket = -1; |
214 | int escaped = 0; | 205 | int escaped = 0; |
215 | int idx = 0; | 206 | int idx = 0; |
216 | char ch; | 207 | char ch; |
217 | 208 | ||
209 | if (delimiter < 0) { | ||
210 | bracket--; | ||
211 | delimiter *= -1; | ||
212 | } | ||
213 | |||
218 | for (; (ch = str[idx]); idx++) { | 214 | for (; (ch = str[idx]); idx++) { |
219 | if (bracket != -1) { | 215 | if (bracket >= 0) { |
220 | if (ch == ']' && !(bracket == idx - 1 || (bracket == idx - 2 | 216 | if (ch == ']' && !(bracket == idx - 1 || (bracket == idx - 2 |
221 | && str[idx - 1] == '^'))) | 217 | && str[idx - 1] == '^'))) |
222 | bracket = -1; | 218 | bracket = -1; |
@@ -224,43 +220,38 @@ static int index_of_next_unescaped_regexp_delim(const char delimiter, | |||
224 | escaped = 0; | 220 | escaped = 0; |
225 | else if (ch == '\\') | 221 | else if (ch == '\\') |
226 | escaped = 1; | 222 | escaped = 1; |
227 | else if (ch == '[') | 223 | else if (bracket == -1 && ch == '[') |
228 | bracket = idx; | 224 | bracket = idx; |
229 | else if (ch == delimiter) | 225 | else if (ch == delimiter) |
230 | return idx; | 226 | return idx; |
231 | } | 227 | } |
232 | 228 | ||
233 | /* if we make it to here, we've hit the end of the string */ | 229 | /* if we make it to here, we've hit the end of the string */ |
234 | return -1; | 230 | bb_error_msg_and_die("unmatched '%c'",delimiter); |
235 | } | 231 | } |
236 | 232 | ||
237 | /* | 233 | /* |
238 | * Returns the index of the third delimiter | 234 | * Returns the index of the third delimiter |
239 | */ | 235 | */ |
240 | static int parse_regex_delim(const char *cmdstr, char **match, char **replace) | 236 | static int parse_regex_delim(char *cmdstr, char **match, char **replace) |
241 | { | 237 | { |
242 | const char *cmdstr_ptr = cmdstr; | 238 | char *cmdstr_ptr = cmdstr; |
243 | char delimiter; | 239 | char delimiter; |
244 | int idx = 0; | 240 | int idx = 0; |
245 | 241 | ||
246 | /* verify that the 's' or 'y' is followed by something. That something | 242 | /* verify that the 's' or 'y' is followed by something. That something |
247 | * (typically a 'slash') is now our regexp delimiter... */ | 243 | * (typically a 'slash') is now our regexp delimiter... */ |
248 | if (*cmdstr == '\0') bb_error_msg_and_die(bad_format_in_subst); | 244 | if (*cmdstr == '\0') |
245 | bb_error_msg_and_die("bad format in substitution expression"); | ||
249 | delimiter = *(cmdstr_ptr++); | 246 | delimiter = *(cmdstr_ptr++); |
250 | 247 | ||
251 | /* save the match string */ | 248 | /* save the match string */ |
252 | idx = index_of_next_unescaped_regexp_delim(delimiter, cmdstr_ptr); | 249 | idx = index_of_next_unescaped_regexp_delim(delimiter, cmdstr_ptr); |
253 | if (idx == -1) { | ||
254 | bb_error_msg_and_die(bad_format_in_subst); | ||
255 | } | ||
256 | *match = copy_parsing_escapes(cmdstr_ptr, idx); | 250 | *match = copy_parsing_escapes(cmdstr_ptr, idx); |
257 | 251 | ||
258 | /* save the replacement string */ | 252 | /* save the replacement string */ |
259 | cmdstr_ptr += idx + 1; | 253 | cmdstr_ptr += idx + 1; |
260 | idx = index_of_next_unescaped_regexp_delim(delimiter, cmdstr_ptr); | 254 | idx = index_of_next_unescaped_regexp_delim(-delimiter, cmdstr_ptr); |
261 | if (idx == -1) { | ||
262 | bb_error_msg_and_die(bad_format_in_subst); | ||
263 | } | ||
264 | *replace = copy_parsing_escapes(cmdstr_ptr, idx); | 255 | *replace = copy_parsing_escapes(cmdstr_ptr, idx); |
265 | 256 | ||
266 | return ((cmdstr_ptr - cmdstr) + idx); | 257 | return ((cmdstr_ptr - cmdstr) + idx); |
@@ -287,21 +278,18 @@ static int get_address(char *my_str, int *linenum, regex_t ** regex) | |||
287 | if (*my_str == '\\') delimiter = *(++pos); | 278 | if (*my_str == '\\') delimiter = *(++pos); |
288 | else delimiter = '/'; | 279 | else delimiter = '/'; |
289 | next = index_of_next_unescaped_regexp_delim(delimiter, ++pos); | 280 | next = index_of_next_unescaped_regexp_delim(delimiter, ++pos); |
290 | if (next == -1) | 281 | temp = copy_parsing_escapes(pos,next); |
291 | bb_error_msg_and_die("unterminated match expression"); | ||
292 | |||
293 | temp=copy_parsing_escapes(pos,next); | ||
294 | *regex = (regex_t *) xmalloc(sizeof(regex_t)); | 282 | *regex = (regex_t *) xmalloc(sizeof(regex_t)); |
295 | xregcomp(*regex, temp, bbg.regex_type|REG_NEWLINE); | 283 | xregcomp(*regex, temp, bbg.regex_type|REG_NEWLINE); |
296 | free(temp); | 284 | free(temp); |
297 | /* Move position to next character after last delimiter */ | 285 | /* Move position to next character after last delimiter */ |
298 | pos+=(next+1); | 286 | pos += (next+1); |
299 | } | 287 | } |
300 | return pos - my_str; | 288 | return pos - my_str; |
301 | } | 289 | } |
302 | 290 | ||
303 | /* Grab a filename. Whitespace at start is skipped, then goes to EOL. */ | 291 | /* Grab a filename. Whitespace at start is skipped, then goes to EOL. */ |
304 | static int parse_file_cmd(sed_cmd_t *sed_cmd, const char *filecmdstr, char **retval) | 292 | static int parse_file_cmd(sed_cmd_t *sed_cmd, char *filecmdstr, char **retval) |
305 | { | 293 | { |
306 | int start = 0, idx, hack=0; | 294 | int start = 0, idx, hack=0; |
307 | 295 | ||
@@ -318,7 +306,7 @@ static int parse_file_cmd(sed_cmd_t *sed_cmd, const char *filecmdstr, char **ret | |||
318 | return idx; | 306 | return idx; |
319 | } | 307 | } |
320 | 308 | ||
321 | static int parse_subst_cmd(sed_cmd_t *const sed_cmd, char *substr) | 309 | static int parse_subst_cmd(sed_cmd_t *sed_cmd, char *substr) |
322 | { | 310 | { |
323 | int cflags = bbg.regex_type; | 311 | int cflags = bbg.regex_type; |
324 | char *match; | 312 | char *match; |
@@ -569,7 +557,7 @@ static void pipe_putc(char c) | |||
569 | bbg.pipeline.buf[bbg.pipeline.idx++] = c; | 557 | bbg.pipeline.buf[bbg.pipeline.idx++] = c; |
570 | } | 558 | } |
571 | 559 | ||
572 | static void do_subst_w_backrefs(const char *line, const char *replace) | 560 | static void do_subst_w_backrefs(char *line, char *replace) |
573 | { | 561 | { |
574 | int i,j; | 562 | int i,j; |
575 | 563 | ||
@@ -669,7 +657,7 @@ static int do_subst_command(sed_cmd_t *sed_cmd, char **line) | |||
669 | } | 657 | } |
670 | 658 | ||
671 | /* Set command pointer to point to this label. (Does not handle null label.) */ | 659 | /* Set command pointer to point to this label. (Does not handle null label.) */ |
672 | static sed_cmd_t *branch_to(const char *label) | 660 | static sed_cmd_t *branch_to(char *label) |
673 | { | 661 | { |
674 | sed_cmd_t *sed_cmd; | 662 | sed_cmd_t *sed_cmd; |
675 | 663 | ||
diff --git a/testsuite/sed.tests b/testsuite/sed.tests index 4d6e2e67e..9d2be5570 100755 --- a/testsuite/sed.tests +++ b/testsuite/sed.tests | |||
@@ -174,6 +174,8 @@ testing "sed -i with no arg [GNUFAIL]" "sed -e '' -i 2> /dev/null || echo yes" \ | |||
174 | "yes\n" "" "" | 174 | "yes\n" "" "" |
175 | rm ./- # Clean up | 175 | rm ./- # Clean up |
176 | 176 | ||
177 | testing "sed s/xxx/[/" "sed -e 's/xxx/[/'" "[\n" "" "xxx\n" | ||
178 | |||
177 | # Ponder this a bit more, why "woo not found" from gnu version? | 179 | # Ponder this a bit more, why "woo not found" from gnu version? |
178 | #testing "sed doesn't substitute in deleted line" \ | 180 | #testing "sed doesn't substitute in deleted line" \ |
179 | # "sed -e '/ook/d;s/ook//;t woo;a bang;'" "bang" "" "ook\n" | 181 | # "sed -e '/ook/d;s/ook//;t woo;a bang;'" "bang" "" "ook\n" |