aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRob Landley <rob@landley.net>2006-07-26 17:25:08 +0000
committerRob Landley <rob@landley.net>2006-07-26 17:25:08 +0000
commit4795e4e011f1a146a2a4aa06a006fff5641befb5 (patch)
tree6185ef8c9dfc1f24c094d5262b745119f6400402
parent7cc6b69bb09d2242493b7c4d882af958254e0cc7 (diff)
downloadbusybox-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.c58
-rwxr-xr-xtestsuite/sed.tests2
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
97static const char bad_format_in_subst[] =
98 "bad format in substitution expression";
99static const char *const semicolon_whitespace = "; \n\r\t\v"; 91static const char *const semicolon_whitespace = "; \n\r\t\v";
100 92
101struct sed_globals 93struct 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
178static void parse_escapes(char *dest, const char *string, int len, char from, char to) 170static 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
195static char *copy_parsing_escapes(const char *string, int len) 187static 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 */
210static int index_of_next_unescaped_regexp_delim(const char delimiter, 202static 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 */
240static int parse_regex_delim(const char *cmdstr, char **match, char **replace) 236static 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. */
304static int parse_file_cmd(sed_cmd_t *sed_cmd, const char *filecmdstr, char **retval) 292static 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
321static int parse_subst_cmd(sed_cmd_t *const sed_cmd, char *substr) 309static 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
572static void do_subst_w_backrefs(const char *line, const char *replace) 560static 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.) */
672static sed_cmd_t *branch_to(const char *label) 660static 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" "" ""
175rm ./- # Clean up 175rm ./- # Clean up
176 176
177testing "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"