diff options
author | Glenn L McGrath <bug1@ihug.co.nz> | 2003-04-08 11:56:11 +0000 |
---|---|---|
committer | Glenn L McGrath <bug1@ihug.co.nz> | 2003-04-08 11:56:11 +0000 |
commit | 8d6395d41a4784352cbba5b61e73bfc8afec3f31 (patch) | |
tree | 9e1cae748c71f2a8e1c7b7247905f9acf42b4bf2 | |
parent | c1d95076f0b775977ff12c3a55fc78fee437ba45 (diff) | |
download | busybox-w32-8d6395d41a4784352cbba5b61e73bfc8afec3f31.tar.gz busybox-w32-8d6395d41a4784352cbba5b61e73bfc8afec3f31.tar.bz2 busybox-w32-8d6395d41a4784352cbba5b61e73bfc8afec3f31.zip |
Run through indent
-rw-r--r-- | editors/sed.c | 661 |
1 files changed, 360 insertions, 301 deletions
diff --git a/editors/sed.c b/editors/sed.c index 1e2191864..a616c992c 100644 --- a/editors/sed.c +++ b/editors/sed.c | |||
@@ -47,11 +47,11 @@ | |||
47 | */ | 47 | */ |
48 | 48 | ||
49 | #include <stdio.h> | 49 | #include <stdio.h> |
50 | #include <unistd.h> /* for getopt() */ | 50 | #include <unistd.h> /* for getopt() */ |
51 | #include <regex.h> | 51 | #include <regex.h> |
52 | #include <string.h> /* for strdup() */ | 52 | #include <string.h> /* for strdup() */ |
53 | #include <errno.h> | 53 | #include <errno.h> |
54 | #include <ctype.h> /* for isspace() */ | 54 | #include <ctype.h> /* for isspace() */ |
55 | #include <stdlib.h> | 55 | #include <stdlib.h> |
56 | #include "busybox.h" | 56 | #include "busybox.h" |
57 | 57 | ||
@@ -59,20 +59,21 @@ | |||
59 | #define SED_LABEL_LENGTH 8 | 59 | #define SED_LABEL_LENGTH 8 |
60 | 60 | ||
61 | /* externs */ | 61 | /* externs */ |
62 | extern void xregcomp(regex_t *preg, const char *regex, int cflags); | 62 | extern void xregcomp(regex_t * preg, const char *regex, int cflags); |
63 | extern int optind; /* in unistd.h */ | 63 | extern int optind; /* in unistd.h */ |
64 | extern char *optarg; /* ditto */ | 64 | extern char *optarg; /* ditto */ |
65 | 65 | ||
66 | /* options */ | 66 | /* options */ |
67 | static int be_quiet = 0; | 67 | static int be_quiet = 0; |
68 | static const char bad_format_in_subst[] = "bad format in substitution expression"; | 68 | static const char bad_format_in_subst[] = |
69 | "bad format in substitution expression"; | ||
69 | 70 | ||
70 | typedef struct sed_cmd_s { | 71 | typedef struct sed_cmd_s { |
71 | /* Order by alignment requirements */ | 72 | /* Order by alignment requirements */ |
72 | 73 | ||
73 | /* address storage */ | 74 | /* address storage */ |
74 | regex_t *beg_match; /* sed -e '/match/cmd' */ | 75 | regex_t *beg_match; /* sed -e '/match/cmd' */ |
75 | regex_t *end_match; /* sed -e '/match/,/end_match/cmd' */ | 76 | regex_t *end_match; /* sed -e '/match/,/end_match/cmd' */ |
76 | 77 | ||
77 | /* SUBSTITUTION COMMAND SPECIFIC FIELDS */ | 78 | /* SUBSTITUTION COMMAND SPECIFIC FIELDS */ |
78 | 79 | ||
@@ -87,25 +88,25 @@ typedef struct sed_cmd_s { | |||
87 | char *filename; | 88 | char *filename; |
88 | 89 | ||
89 | /* address storage */ | 90 | /* address storage */ |
90 | int beg_line; /* 'sed 1p' 0 == no begining line, apply commands to all lines */ | 91 | int beg_line; /* 'sed 1p' 0 == no begining line, apply commands to all lines */ |
91 | int end_line; /* 'sed 1,3p' 0 == no end line, use only beginning. -1 == $ */ | 92 | int end_line; /* 'sed 1,3p' 0 == no end line, use only beginning. -1 == $ */ |
92 | /* SUBSTITUTION COMMAND SPECIFIC FIELDS */ | 93 | /* SUBSTITUTION COMMAND SPECIFIC FIELDS */ |
93 | 94 | ||
94 | unsigned int num_backrefs:4; /* how many back references (\1..\9) */ | 95 | unsigned int num_backrefs:4; /* how many back references (\1..\9) */ |
95 | /* Note: GNU/POSIX sed does not save more than nine backrefs, so | 96 | /* Note: GNU/POSIX sed does not save more than nine backrefs, so |
96 | * we only use 4 bits to hold the number */ | 97 | * we only use 4 bits to hold the number */ |
97 | unsigned int sub_g:1; /* sed -e 's/foo/bar/g' (global) */ | 98 | unsigned int sub_g:1; /* sed -e 's/foo/bar/g' (global) */ |
98 | unsigned int sub_p:1; /* sed -e 's/foo/bar/p' (print substitution) */ | 99 | unsigned int sub_p:1; /* sed -e 's/foo/bar/p' (print substitution) */ |
99 | 100 | ||
100 | /* TRANSLATE COMMAND */ | 101 | /* TRANSLATE COMMAND */ |
101 | char *translate; | 102 | char *translate; |
102 | 103 | ||
103 | /* GENERAL FIELDS */ | 104 | /* GENERAL FIELDS */ |
104 | /* the command */ | 105 | /* the command */ |
105 | char cmd; /* p,d,s (add more at your leisure :-) */ | 106 | char cmd; /* p,d,s (add more at your leisure :-) */ |
106 | 107 | ||
107 | /* inversion flag */ | 108 | /* inversion flag */ |
108 | int invert; /* the '!' after the address */ | 109 | int invert; /* the '!' after the address */ |
109 | 110 | ||
110 | /* Branch commands */ | 111 | /* Branch commands */ |
111 | char label[SED_LABEL_LENGTH + 1]; | 112 | char label[SED_LABEL_LENGTH + 1]; |
@@ -122,7 +123,7 @@ static sed_cmd_t *sed_cmd_tail = &sed_cmd_head; | |||
122 | static sed_cmd_t *block_cmd; | 123 | static sed_cmd_t *block_cmd; |
123 | 124 | ||
124 | static int in_block = 0; | 125 | static int in_block = 0; |
125 | const char * const semicolon_whitespace = "; \n\r\t\v\0"; | 126 | const char *const semicolon_whitespace = "; \n\r\t\v\0"; |
126 | static regex_t *previous_regex_ptr = NULL; | 127 | static regex_t *previous_regex_ptr = NULL; |
127 | 128 | ||
128 | #ifdef CONFIG_FEATURE_CLEAN_UP | 129 | #ifdef CONFIG_FEATURE_CLEAN_UP |
@@ -158,17 +159,18 @@ static void destroy_cmd_strs(void) | |||
158 | * expression delimiter (typically a forward * slash ('/')) not preceeded by | 159 | * expression delimiter (typically a forward * slash ('/')) not preceeded by |
159 | * a backslash ('\'). | 160 | * a backslash ('\'). |
160 | */ | 161 | */ |
161 | static int index_of_next_unescaped_regexp_delim(const char delimiter, const char *str) | 162 | static int index_of_next_unescaped_regexp_delim(const char delimiter, |
163 | const char *str) | ||
162 | { | 164 | { |
163 | int bracket = -1; | 165 | int bracket = -1; |
164 | int escaped = 0; | 166 | int escaped = 0; |
165 | int idx = 0; | 167 | int idx = 0; |
166 | char ch; | 168 | char ch; |
167 | 169 | ||
168 | for ( ; (ch = str[idx]); idx++) { | 170 | for (; (ch = str[idx]); idx++) { |
169 | if (bracket != -1) { | 171 | if (bracket != -1) { |
170 | if (ch == ']' && !(bracket == idx - 1 || | 172 | if (ch == ']' && !(bracket == idx - 1 || |
171 | (bracket == idx - 2 && str[idx-1] == '^'))) | 173 | (bracket == idx - 2 && str[idx - 1] == '^'))) |
172 | bracket = -1; | 174 | bracket = -1; |
173 | } else if (escaped) | 175 | } else if (escaped) |
174 | escaped = 0; | 176 | escaped = 0; |
@@ -214,26 +216,26 @@ static int parse_regex_delim(const char *cmdstr, char **match, char **replace) | |||
214 | } | 216 | } |
215 | *replace = bb_xstrndup(cmdstr_ptr, idx); | 217 | *replace = bb_xstrndup(cmdstr_ptr, idx); |
216 | 218 | ||
217 | return((cmdstr_ptr - cmdstr) + idx); | 219 | return ((cmdstr_ptr - cmdstr) + idx); |
218 | } | 220 | } |
219 | 221 | ||
220 | /* | 222 | /* |
221 | * returns the index in the string just past where the address ends. | 223 | * returns the index in the string just past where the address ends. |
222 | */ | 224 | */ |
223 | static int get_address(char *my_str, int *linenum, regex_t **regex) | 225 | static int get_address(char *my_str, int *linenum, regex_t ** regex) |
224 | { | 226 | { |
225 | int idx = 0; | 227 | int idx = 0; |
228 | |||
226 | if (isdigit(my_str[idx])) { | 229 | if (isdigit(my_str[idx])) { |
227 | char *endstr; | 230 | char *endstr; |
231 | |||
228 | *linenum = strtol(my_str, &endstr, 10); | 232 | *linenum = strtol(my_str, &endstr, 10); |
229 | /* endstr shouldnt ever equal NULL */ | 233 | /* endstr shouldnt ever equal NULL */ |
230 | idx = endstr - my_str; | 234 | idx = endstr - my_str; |
231 | } | 235 | } else if (my_str[idx] == '$') { |
232 | else if (my_str[idx] == '$') { | ||
233 | *linenum = -1; | 236 | *linenum = -1; |
234 | idx++; | 237 | idx++; |
235 | } | 238 | } else if (my_str[idx] == '/' || my_str[idx] == '\\') { |
236 | else if (my_str[idx] == '/' || my_str[idx] == '\\') { | ||
237 | int idx_start = 1; | 239 | int idx_start = 1; |
238 | char delimiter; | 240 | char delimiter; |
239 | 241 | ||
@@ -248,10 +250,10 @@ static int get_address(char *my_str, int *linenum, regex_t **regex) | |||
248 | bb_error_msg_and_die("unterminated match expression"); | 250 | bb_error_msg_and_die("unterminated match expression"); |
249 | } | 251 | } |
250 | my_str[idx] = '\0'; | 252 | my_str[idx] = '\0'; |
251 | 253 | ||
252 | *regex = (regex_t *)xmalloc(sizeof(regex_t)); | 254 | *regex = (regex_t *) xmalloc(sizeof(regex_t)); |
253 | xregcomp(*regex, my_str+idx_start, REG_NEWLINE); | 255 | xregcomp(*regex, my_str + idx_start, REG_NEWLINE); |
254 | idx++; /* so it points to the next character after the last '/' */ | 256 | idx++; /* so it points to the next character after the last '/' */ |
255 | } | 257 | } |
256 | return idx; | 258 | return idx; |
257 | } | 259 | } |
@@ -277,41 +279,42 @@ static int parse_subst_cmd(sed_cmd_t * const sed_cmd, const char *substr) | |||
277 | /* Note: we compute this here rather than in the do_subst_command() | 279 | /* Note: we compute this here rather than in the do_subst_command() |
278 | * function to save processor time, at the expense of a little more memory | 280 | * function to save processor time, at the expense of a little more memory |
279 | * (4 bits) per sed_cmd */ | 281 | * (4 bits) per sed_cmd */ |
280 | 282 | ||
281 | /* sed_cmd->num_backrefs = 0; */ /* XXX: not needed? --apparently not */ | 283 | /* sed_cmd->num_backrefs = 0; *//* XXX: not needed? --apparently not */ |
282 | for (j = 0; match[j]; j++) { | 284 | for (j = 0; match[j]; j++) { |
283 | /* GNU/POSIX sed does not save more than nine backrefs */ | 285 | /* GNU/POSIX sed does not save more than nine backrefs */ |
284 | if (match[j] == '\\' && match[j+1] == '(' && sed_cmd->num_backrefs <= 9) | 286 | if (match[j] == '\\' && match[j + 1] == '(' |
287 | && sed_cmd->num_backrefs <= 9) | ||
285 | sed_cmd->num_backrefs++; | 288 | sed_cmd->num_backrefs++; |
286 | } | 289 | } |
287 | 290 | ||
288 | /* process the flags */ | 291 | /* process the flags */ |
289 | while (substr[++idx]) { | 292 | while (substr[++idx]) { |
290 | switch (substr[idx]) { | 293 | switch (substr[idx]) { |
291 | case 'g': | 294 | case 'g': |
292 | sed_cmd->sub_g = 1; | 295 | sed_cmd->sub_g = 1; |
293 | break; | 296 | break; |
294 | /* Hmm, i dont see the I option mentioned in the standard */ | 297 | /* Hmm, i dont see the I option mentioned in the standard */ |
295 | case 'I': | 298 | case 'I': |
296 | cflags |= REG_ICASE; | 299 | cflags |= REG_ICASE; |
297 | break; | 300 | break; |
298 | case 'p': | 301 | case 'p': |
299 | sed_cmd->sub_p = 1; | 302 | sed_cmd->sub_p = 1; |
300 | break; | 303 | break; |
301 | default: | 304 | default: |
302 | /* any whitespace or semicolon trailing after a s/// is ok */ | 305 | /* any whitespace or semicolon trailing after a s/// is ok */ |
303 | if (strchr(semicolon_whitespace, substr[idx])) | 306 | if (strchr(semicolon_whitespace, substr[idx])) |
304 | goto out; | 307 | goto out; |
305 | /* else */ | 308 | /* else */ |
306 | bb_error_msg_and_die("bad option in substitution expression"); | 309 | bb_error_msg_and_die("bad option in substitution expression"); |
307 | } | 310 | } |
308 | } | 311 | } |
309 | 312 | ||
310 | out: | 313 | out: |
311 | /* compile the match string into a regex */ | 314 | /* compile the match string into a regex */ |
312 | if (*match != '\0') { | 315 | if (*match != '\0') { |
313 | /* If match is empty, we use last regex used at runtime */ | 316 | /* If match is empty, we use last regex used at runtime */ |
314 | sed_cmd->sub_match = (regex_t *)xmalloc(sizeof(regex_t)); | 317 | sed_cmd->sub_match = (regex_t *) xmalloc(sizeof(regex_t)); |
315 | xregcomp(sed_cmd->sub_match, match, cflags); | 318 | xregcomp(sed_cmd->sub_match, match, cflags); |
316 | } | 319 | } |
317 | free(match); | 320 | free(match); |
@@ -349,10 +352,10 @@ static int parse_translate_cmd(sed_cmd_t * const sed_cmd, const char *cmdstr) | |||
349 | sed_cmd->translate[i * 2] = match[i]; | 352 | sed_cmd->translate[i * 2] = match[i]; |
350 | sed_cmd->translate[(i * 2) + 1] = replace[i]; | 353 | sed_cmd->translate[(i * 2) + 1] = replace[i]; |
351 | } | 354 | } |
352 | return(idx + 1); | 355 | return (idx + 1); |
353 | } | 356 | } |
354 | 357 | ||
355 | static int parse_edit_cmd(sed_cmd_t *sed_cmd, const char *editstr) | 358 | static int parse_edit_cmd(sed_cmd_t * sed_cmd, const char *editstr) |
356 | { | 359 | { |
357 | int i, j; | 360 | int i, j; |
358 | 361 | ||
@@ -383,9 +386,9 @@ static int parse_edit_cmd(sed_cmd_t *sed_cmd, const char *editstr) | |||
383 | 386 | ||
384 | /* store the edit line text */ | 387 | /* store the edit line text */ |
385 | sed_cmd->editline = xmalloc(strlen(&editstr[2]) + 2); | 388 | sed_cmd->editline = xmalloc(strlen(&editstr[2]) + 2); |
386 | for (i = 2, j = 0; editstr[i] != '\0' && strchr("\r\n", editstr[i]) == NULL; | 389 | for (i = 2, j = 0; |
387 | i++, j++) { | 390 | editstr[i] != '\0' && strchr("\r\n", editstr[i]) == NULL; i++, j++) { |
388 | if ((editstr[i] == '\\') && strchr("\n\r", editstr[i+1]) != NULL) { | 391 | if ((editstr[i] == '\\') && strchr("\n\r", editstr[i + 1]) != NULL) { |
389 | sed_cmd->editline[j] = '\n'; | 392 | sed_cmd->editline[j] = '\n'; |
390 | i++; | 393 | i++; |
391 | } else | 394 | } else |
@@ -393,7 +396,7 @@ static int parse_edit_cmd(sed_cmd_t *sed_cmd, const char *editstr) | |||
393 | } | 396 | } |
394 | 397 | ||
395 | /* figure out if we need to add a newline */ | 398 | /* figure out if we need to add a newline */ |
396 | if (sed_cmd->editline[j-1] != '\n') | 399 | if (sed_cmd->editline[j - 1] != '\n') |
397 | sed_cmd->editline[j++] = '\n'; | 400 | sed_cmd->editline[j++] = '\n'; |
398 | 401 | ||
399 | /* terminate string */ | 402 | /* terminate string */ |
@@ -403,7 +406,7 @@ static int parse_edit_cmd(sed_cmd_t *sed_cmd, const char *editstr) | |||
403 | } | 406 | } |
404 | 407 | ||
405 | 408 | ||
406 | static int parse_file_cmd(sed_cmd_t *sed_cmd, const char *filecmdstr) | 409 | static int parse_file_cmd(sed_cmd_t * sed_cmd, const char *filecmdstr) |
407 | { | 410 | { |
408 | int idx = 0; | 411 | int idx = 0; |
409 | int filenamelen = 0; | 412 | int filenamelen = 0; |
@@ -427,9 +430,9 @@ static int parse_file_cmd(sed_cmd_t *sed_cmd, const char *filecmdstr) | |||
427 | */ | 430 | */ |
428 | 431 | ||
429 | /* the file command may be followed by whitespace; move past it. */ | 432 | /* the file command may be followed by whitespace; move past it. */ |
430 | while (isspace(filecmdstr[++idx])) | 433 | while (isspace(filecmdstr[++idx])) {; |
431 | { ; } | 434 | } |
432 | 435 | ||
433 | /* the first non-whitespace we get is a filename. the filename ends when we | 436 | /* the first non-whitespace we get is a filename. the filename ends when we |
434 | * hit a normal sed command terminator or end of string */ | 437 | * hit a normal sed command terminator or end of string */ |
435 | filenamelen = strcspn(&filecmdstr[idx], semicolon_whitespace); | 438 | filenamelen = strcspn(&filecmdstr[idx], semicolon_whitespace); |
@@ -451,7 +454,8 @@ static char *parse_cmd_str(sed_cmd_t * const sed_cmd, char *cmdstr) | |||
451 | /* handle edit cmds: (a)ppend, (i)nsert, and (c)hange */ | 454 | /* handle edit cmds: (a)ppend, (i)nsert, and (c)hange */ |
452 | else if (strchr("aic", sed_cmd->cmd)) { | 455 | else if (strchr("aic", sed_cmd->cmd)) { |
453 | if ((sed_cmd->end_line || sed_cmd->end_match) && sed_cmd->cmd != 'c') | 456 | if ((sed_cmd->end_line || sed_cmd->end_match) && sed_cmd->cmd != 'c') |
454 | bb_error_msg_and_die("only a beginning address can be specified for edit commands"); | 457 | bb_error_msg_and_die |
458 | ("only a beginning address can be specified for edit commands"); | ||
455 | cmdstr += parse_edit_cmd(sed_cmd, cmdstr); | 459 | cmdstr += parse_edit_cmd(sed_cmd, cmdstr); |
456 | } | 460 | } |
457 | /* handle file cmds: (r)ead */ | 461 | /* handle file cmds: (r)ead */ |
@@ -470,7 +474,7 @@ static char *parse_cmd_str(sed_cmd_t * const sed_cmd, char *cmdstr) | |||
470 | length = SED_LABEL_LENGTH; | 474 | length = SED_LABEL_LENGTH; |
471 | } | 475 | } |
472 | strncpy(sed_cmd->label, cmdstr, length); | 476 | strncpy(sed_cmd->label, cmdstr, length); |
473 | cmdstr += length; | 477 | cmdstr += length; |
474 | } | 478 | } |
475 | /* translation command */ | 479 | /* translation command */ |
476 | else if (sed_cmd->cmd == 'y') { | 480 | else if (sed_cmd->cmd == 'y') { |
@@ -484,10 +488,10 @@ static char *parse_cmd_str(sed_cmd_t * const sed_cmd, char *cmdstr) | |||
484 | } | 488 | } |
485 | 489 | ||
486 | /* give back whatever's left over */ | 490 | /* give back whatever's left over */ |
487 | return(cmdstr); | 491 | return (cmdstr); |
488 | } | 492 | } |
489 | 493 | ||
490 | static char *add_cmd(sed_cmd_t *sed_cmd, char *cmdstr) | 494 | static char *add_cmd(sed_cmd_t * sed_cmd, char *cmdstr) |
491 | { | 495 | { |
492 | /* Skip over leading whitespace and semicolons */ | 496 | /* Skip over leading whitespace and semicolons */ |
493 | cmdstr += strspn(cmdstr, semicolon_whitespace); | 497 | cmdstr += strspn(cmdstr, semicolon_whitespace); |
@@ -495,7 +499,7 @@ static char *add_cmd(sed_cmd_t *sed_cmd, char *cmdstr) | |||
495 | /* if we ate the whole thing, that means there was just trailing | 499 | /* if we ate the whole thing, that means there was just trailing |
496 | * whitespace or a final / no-op semicolon. either way, get out */ | 500 | * whitespace or a final / no-op semicolon. either way, get out */ |
497 | if (*cmdstr == '\0') { | 501 | if (*cmdstr == '\0') { |
498 | return(NULL); | 502 | return (NULL); |
499 | } | 503 | } |
500 | 504 | ||
501 | /* if this is a comment, jump past it and keep going */ | 505 | /* if this is a comment, jump past it and keep going */ |
@@ -504,14 +508,14 @@ static char *add_cmd(sed_cmd_t *sed_cmd, char *cmdstr) | |||
504 | if (cmdstr[1] == 'n') { | 508 | if (cmdstr[1] == 'n') { |
505 | be_quiet++; | 509 | be_quiet++; |
506 | } | 510 | } |
507 | return(strpbrk(cmdstr, "\n\r")); | 511 | return (strpbrk(cmdstr, "\n\r")); |
508 | } | 512 | } |
509 | 513 | ||
510 | /* Test for end of block */ | 514 | /* Test for end of block */ |
511 | if (*cmdstr == '}') { | 515 | if (*cmdstr == '}') { |
512 | in_block = 0; | 516 | in_block = 0; |
513 | cmdstr++; | 517 | cmdstr++; |
514 | return(cmdstr); | 518 | return (cmdstr); |
515 | } | 519 | } |
516 | 520 | ||
517 | /* parse the command | 521 | /* parse the command |
@@ -526,11 +530,12 @@ static char *add_cmd(sed_cmd_t *sed_cmd, char *cmdstr) | |||
526 | /* second part (if present) will begin with a comma */ | 530 | /* second part (if present) will begin with a comma */ |
527 | if (*cmdstr == ',') { | 531 | if (*cmdstr == ',') { |
528 | int idx; | 532 | int idx; |
533 | |||
529 | cmdstr++; | 534 | cmdstr++; |
530 | idx = get_address(cmdstr, &sed_cmd->end_line, &sed_cmd->end_match); | 535 | idx = get_address(cmdstr, &sed_cmd->end_line, &sed_cmd->end_match); |
531 | if (idx == 0) { | 536 | if (idx == 0) { |
532 | bb_error_msg_and_die("get_address: no address found in string\n" | 537 | bb_error_msg_and_die("get_address: no address found in string\n" |
533 | "\t(you probably didn't check the string you passed me)"); | 538 | "\t(you probably didn't check the string you passed me)"); |
534 | } | 539 | } |
535 | cmdstr += idx; | 540 | cmdstr += idx; |
536 | } | 541 | } |
@@ -552,9 +557,8 @@ static char *add_cmd(sed_cmd_t *sed_cmd, char *cmdstr) | |||
552 | * with <blank>s. | 557 | * with <blank>s. |
553 | */ | 558 | */ |
554 | if (isblank(cmdstr[idx]) { | 559 | if (isblank(cmdstr[idx]) { |
555 | bb_error_msg_and_die("blank follows '!'"); | 560 | bb_error_msg_and_die("blank follows '!'");} |
556 | } | 561 | #else |
557 | #else | ||
558 | /* skip whitespace before the command */ | 562 | /* skip whitespace before the command */ |
559 | while (isspace(*cmdstr)) { | 563 | while (isspace(*cmdstr)) { |
560 | cmdstr++; | 564 | cmdstr++; |
@@ -573,8 +577,8 @@ static char *add_cmd(sed_cmd_t *sed_cmd, char *cmdstr) | |||
573 | } | 577 | } |
574 | in_block = 1; | 578 | in_block = 1; |
575 | block_cmd = sed_cmd; | 579 | block_cmd = sed_cmd; |
576 | 580 | ||
577 | return(cmdstr + 1); | 581 | return (cmdstr + 1); |
578 | } | 582 | } |
579 | 583 | ||
580 | sed_cmd->cmd = *cmdstr; | 584 | sed_cmd->cmd = *cmdstr; |
@@ -594,7 +598,7 @@ static char *add_cmd(sed_cmd_t *sed_cmd, char *cmdstr) | |||
594 | sed_cmd_tail->linear = sed_cmd; | 598 | sed_cmd_tail->linear = sed_cmd; |
595 | sed_cmd_tail = sed_cmd_tail->linear; | 599 | sed_cmd_tail = sed_cmd_tail->linear; |
596 | 600 | ||
597 | return(cmdstr); | 601 | return (cmdstr); |
598 | } | 602 | } |
599 | 603 | ||
600 | static void add_cmd_str(char *cmdstr) | 604 | static void add_cmd_str(char *cmdstr) |
@@ -603,7 +607,7 @@ static void add_cmd_str(char *cmdstr) | |||
603 | char *cmdstr_ptr = cmdstr; | 607 | char *cmdstr_ptr = cmdstr; |
604 | 608 | ||
605 | /* HACK: convert "\n" to match tranlated '\n' string */ | 609 | /* HACK: convert "\n" to match tranlated '\n' string */ |
606 | while((cmdstr_ptr = strstr(cmdstr_ptr, "\\n")) != NULL) { | 610 | while ((cmdstr_ptr = strstr(cmdstr_ptr, "\\n")) != NULL) { |
607 | cmdstr = xrealloc(cmdstr, strlen(cmdstr) + 2); | 611 | cmdstr = xrealloc(cmdstr, strlen(cmdstr) + 2); |
608 | cmdstr_ptr = strstr(cmdstr, "\\n"); | 612 | cmdstr_ptr = strstr(cmdstr, "\\n"); |
609 | memmove(cmdstr_ptr + 1, cmdstr_ptr, strlen(cmdstr_ptr) + 1); | 613 | memmove(cmdstr_ptr + 1, cmdstr_ptr, strlen(cmdstr_ptr) + 1); |
@@ -613,6 +617,7 @@ static void add_cmd_str(char *cmdstr) | |||
613 | #endif | 617 | #endif |
614 | do { | 618 | do { |
615 | sed_cmd_t *sed_cmd; | 619 | sed_cmd_t *sed_cmd; |
620 | |||
616 | sed_cmd = xcalloc(1, sizeof(sed_cmd_t)); | 621 | sed_cmd = xcalloc(1, sizeof(sed_cmd_t)); |
617 | cmdstr = add_cmd(sed_cmd, cmdstr); | 622 | cmdstr = add_cmd(sed_cmd, cmdstr); |
618 | } while (cmdstr && strlen(cmdstr)); | 623 | } while (cmdstr && strlen(cmdstr)); |
@@ -652,13 +657,12 @@ struct pipeline { | |||
652 | }; | 657 | }; |
653 | 658 | ||
654 | #define PIPE_MAGIC 0x7f | 659 | #define PIPE_MAGIC 0x7f |
655 | #define PIPE_GROW 64 | 660 | #define PIPE_GROW 64 |
656 | 661 | ||
657 | void pipe_putc(struct pipeline *const pipeline, char c) | 662 | void pipe_putc(struct pipeline *const pipeline, char c) |
658 | { | 663 | { |
659 | if (pipeline->buf[pipeline->idx] == PIPE_MAGIC) { | 664 | if (pipeline->buf[pipeline->idx] == PIPE_MAGIC) { |
660 | pipeline->buf = | 665 | pipeline->buf = xrealloc(pipeline->buf, pipeline->len + PIPE_GROW); |
661 | xrealloc(pipeline->buf, pipeline->len + PIPE_GROW); | ||
662 | memset(pipeline->buf + pipeline->len, 0, PIPE_GROW); | 666 | memset(pipeline->buf + pipeline->len, 0, PIPE_GROW); |
663 | pipeline->len += PIPE_GROW; | 667 | pipeline->len += PIPE_GROW; |
664 | pipeline->buf[pipeline->len - 1] = PIPE_MAGIC; | 668 | pipeline->buf[pipeline->len - 1] = PIPE_MAGIC; |
@@ -669,33 +673,40 @@ void pipe_putc(struct pipeline *const pipeline, char c) | |||
669 | #define pipeputc(c) pipe_putc(pipeline, c) | 673 | #define pipeputc(c) pipe_putc(pipeline, c) |
670 | 674 | ||
671 | #if 0 | 675 | #if 0 |
672 | { if (pipeline[pipeline_idx] == PIPE_MAGIC) { \ | 676 | { |
673 | pipeline = xrealloc(pipeline, pipeline_len+PIPE_GROW); \ | 677 | if (pipeline[pipeline_idx] == PIPE_MAGIC) { |
674 | memset(pipeline+pipeline_len, 0, PIPE_GROW); \ | 678 | pipeline = xrealloc(pipeline, pipeline_len + PIPE_GROW); |
675 | pipeline_len += PIPE_GROW; \ | 679 | memset(pipeline + pipeline_len, 0, PIPE_GROW); |
676 | pipeline[pipeline_len-1] = PIPE_MAGIC; } \ | 680 | pipeline_len += PIPE_GROW; |
677 | pipeline[pipeline_idx++] = (c); } | 681 | pipeline[pipeline_len - 1] = PIPE_MAGIC; |
682 | } | ||
683 | pipeline[pipeline_idx++] = (c); | ||
684 | } | ||
678 | #endif | 685 | #endif |
679 | 686 | ||
680 | static void print_subst_w_backrefs(const char *line, const char *replace, | 687 | static void print_subst_w_backrefs(const char *line, const char *replace, |
681 | regmatch_t *regmatch, struct pipeline *const pipeline, int matches) | 688 | regmatch_t * regmatch, |
689 | struct pipeline *const pipeline, | ||
690 | int matches) | ||
682 | { | 691 | { |
683 | int i; | 692 | int i; |
684 | 693 | ||
685 | /* go through the replacement string */ | 694 | /* go through the replacement string */ |
686 | for (i = 0; replace[i]; i++) { | 695 | for (i = 0; replace[i]; i++) { |
687 | /* if we find a backreference (\1, \2, etc.) print the backref'ed * text */ | 696 | /* if we find a backreference (\1, \2, etc.) print the backref'ed * text */ |
688 | if (replace[i] == '\\' && isdigit(replace[i+1])) { | 697 | if (replace[i] == '\\' && isdigit(replace[i + 1])) { |
689 | int j; | 698 | int j; |
690 | char tmpstr[2]; | 699 | char tmpstr[2]; |
691 | int backref; | 700 | int backref; |
692 | ++i; /* i now indexes the backref number, instead of the leading slash */ | 701 | |
702 | ++i; /* i now indexes the backref number, instead of the leading slash */ | ||
693 | tmpstr[0] = replace[i]; | 703 | tmpstr[0] = replace[i]; |
694 | tmpstr[1] = 0; | 704 | tmpstr[1] = 0; |
695 | backref = atoi(tmpstr); | 705 | backref = atoi(tmpstr); |
696 | /* print out the text held in regmatch[backref] */ | 706 | /* print out the text held in regmatch[backref] */ |
697 | if (backref <= matches && regmatch[backref].rm_so != -1) | 707 | if (backref <= matches && regmatch[backref].rm_so != -1) |
698 | for (j = regmatch[backref].rm_so; j < regmatch[backref].rm_eo; j++) | 708 | for (j = regmatch[backref].rm_so; j < regmatch[backref].rm_eo; |
709 | j++) | ||
699 | pipeputc(line[j]); | 710 | pipeputc(line[j]); |
700 | } | 711 | } |
701 | 712 | ||
@@ -709,8 +720,9 @@ static void print_subst_w_backrefs(const char *line, const char *replace, | |||
709 | * fortunately, regmatch[0] contains the indicies to the whole matched | 720 | * fortunately, regmatch[0] contains the indicies to the whole matched |
710 | * expression (kinda seems like it was designed for just such a | 721 | * expression (kinda seems like it was designed for just such a |
711 | * purpose...) */ | 722 | * purpose...) */ |
712 | else if (replace[i] == '&' && replace[i-1] != '\\') { | 723 | else if (replace[i] == '&' && replace[i - 1] != '\\') { |
713 | int j; | 724 | int j; |
725 | |||
714 | for (j = regmatch[0].rm_so; j < regmatch[0].rm_eo; j++) | 726 | for (j = regmatch[0].rm_so; j < regmatch[0].rm_eo; j++) |
715 | pipeputc(line[j]); | 727 | pipeputc(line[j]); |
716 | } | 728 | } |
@@ -720,10 +732,10 @@ static void print_subst_w_backrefs(const char *line, const char *replace, | |||
720 | } | 732 | } |
721 | } | 733 | } |
722 | 734 | ||
723 | static int do_subst_command(sed_cmd_t *sed_cmd, char **line) | 735 | static int do_subst_command(sed_cmd_t * sed_cmd, char **line) |
724 | { | 736 | { |
725 | char *hackline = *line; | 737 | char *hackline = *line; |
726 | struct pipeline thepipe = { NULL, 0 , 0}; | 738 | struct pipeline thepipe = { NULL, 0, 0 }; |
727 | struct pipeline *const pipeline = &thepipe; | 739 | struct pipeline *const pipeline = &thepipe; |
728 | int altered = 0; | 740 | int altered = 0; |
729 | int result; | 741 | int result; |
@@ -743,19 +755,20 @@ static int do_subst_command(sed_cmd_t *sed_cmd, char **line) | |||
743 | } | 755 | } |
744 | 756 | ||
745 | /* whaddaya know, it matched. get the number of back references */ | 757 | /* whaddaya know, it matched. get the number of back references */ |
746 | regmatch = xmalloc(sizeof(regmatch_t) * (sed_cmd->num_backrefs+1)); | 758 | regmatch = xmalloc(sizeof(regmatch_t) * (sed_cmd->num_backrefs + 1)); |
747 | 759 | ||
748 | /* allocate more PIPE_GROW bytes | 760 | /* allocate more PIPE_GROW bytes |
749 | if replaced string is larger than original */ | 761 | if replaced string is larger than original */ |
750 | thepipe.len = strlen(hackline)+PIPE_GROW; | 762 | thepipe.len = strlen(hackline) + PIPE_GROW; |
751 | thepipe.buf = xcalloc(1, thepipe.len); | 763 | thepipe.buf = xcalloc(1, thepipe.len); |
752 | /* buffer magic */ | 764 | /* buffer magic */ |
753 | thepipe.buf[thepipe.len-1] = PIPE_MAGIC; | 765 | thepipe.buf[thepipe.len - 1] = PIPE_MAGIC; |
754 | 766 | ||
755 | /* and now, as long as we've got a line to try matching and if we can match | 767 | /* and now, as long as we've got a line to try matching and if we can match |
756 | * the search string, we make substitutions */ | 768 | * the search string, we make substitutions */ |
757 | while ((*hackline || !altered) && (regexec(current_regex, hackline, | 769 | while ((*hackline || !altered) && (regexec(current_regex, hackline, |
758 | sed_cmd->num_backrefs+1, regmatch, 0) != REG_NOMATCH) ) { | 770 | sed_cmd->num_backrefs + 1, |
771 | regmatch, 0) != REG_NOMATCH)) { | ||
759 | int i; | 772 | int i; |
760 | 773 | ||
761 | /* print everything before the match */ | 774 | /* print everything before the match */ |
@@ -763,8 +776,8 @@ static int do_subst_command(sed_cmd_t *sed_cmd, char **line) | |||
763 | pipeputc(hackline[i]); | 776 | pipeputc(hackline[i]); |
764 | 777 | ||
765 | /* then print the substitution string */ | 778 | /* then print the substitution string */ |
766 | print_subst_w_backrefs(hackline, sed_cmd->replace, regmatch, | 779 | print_subst_w_backrefs(hackline, sed_cmd->replace, regmatch, |
767 | pipeline, sed_cmd->num_backrefs); | 780 | pipeline, sed_cmd->num_backrefs); |
768 | 781 | ||
769 | /* advance past the match */ | 782 | /* advance past the match */ |
770 | hackline += regmatch[0].rm_eo; | 783 | hackline += regmatch[0].rm_eo; |
@@ -776,8 +789,10 @@ static int do_subst_command(sed_cmd_t *sed_cmd, char **line) | |||
776 | break; | 789 | break; |
777 | } | 790 | } |
778 | } | 791 | } |
779 | for (; *hackline; hackline++) pipeputc(*hackline); | 792 | for (; *hackline; hackline++) |
780 | if (thepipe.buf[thepipe.idx] == PIPE_MAGIC) thepipe.buf[thepipe.idx] = 0; | 793 | pipeputc(*hackline); |
794 | if (thepipe.buf[thepipe.idx] == PIPE_MAGIC) | ||
795 | thepipe.buf[thepipe.idx] = 0; | ||
781 | 796 | ||
782 | /* cleanup */ | 797 | /* cleanup */ |
783 | free(regmatch); | 798 | free(regmatch); |
@@ -790,21 +805,22 @@ static int do_subst_command(sed_cmd_t *sed_cmd, char **line) | |||
790 | static sed_cmd_t *branch_to(const char *label) | 805 | static sed_cmd_t *branch_to(const char *label) |
791 | { | 806 | { |
792 | sed_cmd_t *sed_cmd; | 807 | sed_cmd_t *sed_cmd; |
793 | for(sed_cmd = sed_cmd_head.linear; sed_cmd; sed_cmd = sed_cmd->linear) { | 808 | |
809 | for (sed_cmd = sed_cmd_head.linear; sed_cmd; sed_cmd = sed_cmd->linear) { | ||
794 | if (strcmp(sed_cmd->label, label) == 0) { | 810 | if (strcmp(sed_cmd->label, label) == 0) { |
795 | break; | 811 | break; |
796 | } | 812 | } |
797 | } | 813 | } |
798 | 814 | ||
799 | /* If no match returns last command */ | 815 | /* If no match returns last command */ |
800 | return(sed_cmd); | 816 | return (sed_cmd); |
801 | } | 817 | } |
802 | 818 | ||
803 | static void process_file(FILE *file) | 819 | static void process_file(FILE * file) |
804 | { | 820 | { |
805 | char *pattern_space; /* Posix requires it be able to hold at least 8192 bytes */ | 821 | char *pattern_space; /* Posix requires it be able to hold at least 8192 bytes */ |
806 | char *hold_space = NULL; /* Posix requires it be able to hold at least 8192 bytes */ | 822 | char *hold_space = NULL; /* Posix requires it be able to hold at least 8192 bytes */ |
807 | static int linenum = 0; /* GNU sed does not restart counting lines at EOF */ | 823 | static int linenum = 0; /* GNU sed does not restart counting lines at EOF */ |
808 | unsigned int still_in_range = 0; | 824 | unsigned int still_in_range = 0; |
809 | int altered; | 825 | int altered; |
810 | int force_print; | 826 | int force_print; |
@@ -828,24 +844,32 @@ static void process_file(FILE *file) | |||
828 | force_print = 0; | 844 | force_print = 0; |
829 | 845 | ||
830 | /* for every line, go through all the commands */ | 846 | /* for every line, go through all the commands */ |
831 | for (sed_cmd = sed_cmd_head.linear; sed_cmd; sed_cmd = sed_cmd->linear) { | 847 | for (sed_cmd = sed_cmd_head.linear; sed_cmd; |
848 | sed_cmd = sed_cmd->linear) { | ||
832 | int deleted = 0; | 849 | int deleted = 0; |
833 | 850 | ||
834 | /* | 851 | /* |
835 | * entry point into sedding... | 852 | * entry point into sedding... |
836 | */ | 853 | */ |
837 | int matched = ( | 854 | int matched = ( |
838 | /* no range necessary */ | 855 | /* no range necessary */ |
839 | (sed_cmd->beg_line == 0 && sed_cmd->end_line == 0 && | 856 | (sed_cmd->beg_line == 0 |
840 | sed_cmd->beg_match == NULL && | 857 | && sed_cmd->end_line == 0 |
841 | sed_cmd->end_match == NULL) || | 858 | && sed_cmd->beg_match == NULL |
842 | /* this line number is the first address we're looking for */ | 859 | && sed_cmd->end_match == NULL) || |
843 | (sed_cmd->beg_line && (sed_cmd->beg_line == linenum)) || | 860 | /* this line number is the first address we're looking for */ |
844 | /* this line matches our first address regex */ | 861 | (sed_cmd->beg_line |
845 | (sed_cmd->beg_match && (regexec(sed_cmd->beg_match, pattern_space, 0, NULL, 0) == 0)) || | 862 | && (sed_cmd->beg_line == linenum)) || |
846 | /* we are currently within the beginning & ending address range */ | 863 | /* this line matches our first address regex */ |
847 | still_in_range || ((sed_cmd->beg_line == -1) && (next_line == NULL)) | 864 | (sed_cmd->beg_match |
848 | ); | 865 | && |
866 | (regexec | ||
867 | (sed_cmd->beg_match, pattern_space, 0, NULL, | ||
868 | 0) == 0)) || | ||
869 | /* we are currently within the beginning & ending address range */ | ||
870 | still_in_range || ((sed_cmd->beg_line == -1) | ||
871 | && (next_line == NULL)) | ||
872 | ); | ||
849 | 873 | ||
850 | if (sed_cmd->invert ^ matched) { | 874 | if (sed_cmd->invert ^ matched) { |
851 | /* Update last used regex incase a blank substitute BRE is found */ | 875 | /* Update last used regex incase a blank substitute BRE is found */ |
@@ -857,172 +881,192 @@ static void process_file(FILE *file) | |||
857 | * actual sedding | 881 | * actual sedding |
858 | */ | 882 | */ |
859 | switch (sed_cmd->cmd) { | 883 | switch (sed_cmd->cmd) { |
860 | case '=': | 884 | case '=': |
861 | printf("%d\n", linenum); | 885 | printf("%d\n", linenum); |
862 | break; | 886 | break; |
863 | case 'P': { /* Write the current pattern space upto the first newline */ | 887 | case 'P':{ |
864 | char *tmp = strchr(pattern_space, '\n'); | 888 | /* Write the current pattern space upto the first newline */ |
865 | if (tmp) { | 889 | char *tmp = strchr(pattern_space, '\n'); |
866 | *tmp = '\0'; | 890 | |
867 | } | 891 | if (tmp) { |
868 | } | 892 | *tmp = '\0'; |
869 | case 'p': /* Write the current pattern space to output */ | 893 | } |
870 | puts(pattern_space); | 894 | } |
871 | break; | 895 | case 'p': /* Write the current pattern space to output */ |
872 | case 'd': | 896 | puts(pattern_space); |
873 | altered++; | 897 | break; |
874 | deleted = 1; | 898 | case 'd': |
875 | break; | 899 | altered++; |
876 | 900 | deleted = 1; | |
877 | case 's': | 901 | break; |
878 | 902 | ||
879 | /* | 903 | case 's': |
880 | * Some special cases for 's' printing to make it compliant with | 904 | |
881 | * GNU sed printing behavior (aka "The -n | s///p Matrix"): | 905 | /* |
882 | * | 906 | * Some special cases for 's' printing to make it compliant with |
883 | * -n ONLY = never print anything regardless of any successful | 907 | * GNU sed printing behavior (aka "The -n | s///p Matrix"): |
884 | * substitution | 908 | * |
885 | * | 909 | * -n ONLY = never print anything regardless of any successful |
886 | * s///p ONLY = always print successful substitutions, even if | 910 | * substitution |
887 | * the pattern_space is going to be printed anyway (pattern_space | 911 | * |
888 | * will be printed twice). | 912 | * s///p ONLY = always print successful substitutions, even if |
889 | * | 913 | * the pattern_space is going to be printed anyway (pattern_space |
890 | * -n AND s///p = print ONLY a successful substitution ONE TIME; | 914 | * will be printed twice). |
891 | * no other lines are printed - this is the reason why the 'p' | 915 | * |
892 | * flag exists in the first place. | 916 | * -n AND s///p = print ONLY a successful substitution ONE TIME; |
893 | */ | 917 | * no other lines are printed - this is the reason why the 'p' |
918 | * flag exists in the first place. | ||
919 | */ | ||
894 | 920 | ||
895 | #ifdef CONFIG_FEATURE_SED_EMBEDED_NEWLINE | 921 | #ifdef CONFIG_FEATURE_SED_EMBEDED_NEWLINE |
896 | /* HACK: escape newlines twice so regex can match them */ | 922 | /* HACK: escape newlines twice so regex can match them */ |
897 | { | 923 | { |
898 | int offset = 0; | 924 | int offset = 0; |
899 | while(strchr(pattern_space + offset, '\n') != NULL) { | 925 | |
900 | char *tmp; | 926 | while (strchr(pattern_space + offset, '\n') != NULL) { |
901 | pattern_space = xrealloc(pattern_space, strlen(pattern_space) + 2); | 927 | char *tmp; |
902 | tmp = strchr(pattern_space + offset, '\n'); | 928 | |
903 | memmove(tmp + 1, tmp, strlen(tmp) + 1); | 929 | pattern_space = |
904 | tmp[0] = '\\'; | 930 | xrealloc(pattern_space, |
905 | tmp[1] = 'n'; | 931 | strlen(pattern_space) + 2); |
906 | offset = tmp - pattern_space + 2; | 932 | tmp = strchr(pattern_space + offset, '\n'); |
907 | } | 933 | memmove(tmp + 1, tmp, strlen(tmp) + 1); |
908 | } | 934 | tmp[0] = '\\'; |
935 | tmp[1] = 'n'; | ||
936 | offset = tmp - pattern_space + 2; | ||
937 | } | ||
938 | } | ||
909 | #endif | 939 | #endif |
910 | /* we print the pattern_space once, unless we were told to be quiet */ | 940 | /* we print the pattern_space once, unless we were told to be quiet */ |
911 | substituted = do_subst_command(sed_cmd, &pattern_space); | 941 | substituted = do_subst_command(sed_cmd, &pattern_space); |
912 | 942 | ||
913 | #ifdef CONFIG_FEATURE_SED_EMBEDED_NEWLINE | 943 | #ifdef CONFIG_FEATURE_SED_EMBEDED_NEWLINE |
914 | /* undo HACK: escape newlines twice so regex can match them */ | 944 | /* undo HACK: escape newlines twice so regex can match them */ |
915 | { | 945 | { |
916 | char *tmp = pattern_space; | 946 | char *tmp = pattern_space; |
917 | 947 | ||
918 | while((tmp = strstr(tmp, "\\n")) != NULL) { | 948 | while ((tmp = strstr(tmp, "\\n")) != NULL) { |
919 | memmove(tmp, tmp + 1, strlen(tmp + 1) + 1); | 949 | memmove(tmp, tmp + 1, strlen(tmp + 1) + 1); |
920 | tmp[0] = '\n'; | 950 | tmp[0] = '\n'; |
921 | } | ||
922 | } | 951 | } |
952 | } | ||
923 | #endif | 953 | #endif |
924 | altered |= substituted; | 954 | altered |= substituted; |
925 | if (!be_quiet && altered && ((sed_cmd->linear == NULL) || (sed_cmd->linear->cmd != 's'))) { | 955 | if (!be_quiet && altered && ((sed_cmd->linear == NULL) |
926 | force_print = 1; | 956 | || (sed_cmd->linear->cmd != |
927 | } | 957 | 's'))) { |
928 | 958 | force_print = 1; | |
929 | /* we also print the line if we were given the 'p' flag | 959 | } |
930 | * (this is quite possibly the second printing) */ | 960 | |
931 | if ((sed_cmd->sub_p) && altered) { | 961 | /* we also print the line if we were given the 'p' flag |
932 | puts(pattern_space); | 962 | * (this is quite possibly the second printing) */ |
933 | } | 963 | if ((sed_cmd->sub_p) && altered) { |
934 | break; | ||
935 | case 'a': | ||
936 | puts(pattern_space); | 964 | puts(pattern_space); |
937 | fputs(sed_cmd->editline, stdout); | 965 | } |
938 | altered++; | 966 | break; |
939 | break; | 967 | case 'a': |
940 | 968 | puts(pattern_space); | |
941 | case 'i': | 969 | fputs(sed_cmd->editline, stdout); |
942 | fputs(sed_cmd->editline, stdout); | 970 | altered++; |
943 | break; | 971 | break; |
944 | 972 | ||
945 | case 'c': | 973 | case 'i': |
946 | /* single-address case */ | 974 | fputs(sed_cmd->editline, stdout); |
947 | if ((sed_cmd->end_match == NULL && sed_cmd->end_line == 0) | 975 | break; |
976 | |||
977 | case 'c': | ||
978 | /* single-address case */ | ||
979 | if ((sed_cmd->end_match == NULL && sed_cmd->end_line == 0) | ||
948 | /* multi-address case */ | 980 | /* multi-address case */ |
949 | /* - matching text */ | 981 | /* - matching text */ |
950 | || (sed_cmd->end_match && (regexec(sed_cmd->end_match, pattern_space, 0, NULL, 0) == 0)) | 982 | || (sed_cmd->end_match |
983 | && | ||
984 | (regexec | ||
985 | (sed_cmd->end_match, pattern_space, 0, NULL, | ||
986 | 0) == 0)) | ||
951 | /* - matching line numbers */ | 987 | /* - matching line numbers */ |
952 | || (sed_cmd->end_line > 0 && sed_cmd->end_line == linenum)) | 988 | || (sed_cmd->end_line > 0 |
953 | { | 989 | && sed_cmd->end_line == linenum)) { |
954 | fputs(sed_cmd->editline, stdout); | 990 | fputs(sed_cmd->editline, stdout); |
955 | } | 991 | } |
956 | altered++; | 992 | altered++; |
957 | 993 | ||
958 | break; | 994 | break; |
959 | 995 | ||
960 | case 'r': { | 996 | case 'r':{ |
961 | FILE *outfile; | 997 | FILE *outfile; |
962 | puts(pattern_space); | 998 | |
963 | outfile = fopen(sed_cmd->filename, "r"); | 999 | puts(pattern_space); |
964 | if (outfile) | 1000 | outfile = fopen(sed_cmd->filename, "r"); |
965 | bb_xprint_and_close_file(outfile); | 1001 | if (outfile) |
966 | /* else if we couldn't open the output file, | 1002 | bb_xprint_and_close_file(outfile); |
967 | * no biggie, just don't print anything */ | 1003 | /* else if we couldn't open the output file, |
968 | altered++; | 1004 | * no biggie, just don't print anything */ |
969 | } | 1005 | altered++; |
970 | break; | 1006 | } |
971 | case 'q': /* Branch to end of script and quit */ | 1007 | break; |
972 | deleted = 1; | 1008 | case 'q': /* Branch to end of script and quit */ |
973 | /* Exit the outer while loop */ | 1009 | deleted = 1; |
974 | free(next_line); | 1010 | /* Exit the outer while loop */ |
975 | next_line = NULL; | 1011 | free(next_line); |
976 | break; | 1012 | next_line = NULL; |
977 | case 'n': /* Read next line from input */ | 1013 | break; |
978 | free(pattern_space); | 1014 | case 'n': /* Read next line from input */ |
979 | pattern_space = next_line; | 1015 | free(pattern_space); |
1016 | pattern_space = next_line; | ||
1017 | next_line = bb_get_chomped_line_from_file(file); | ||
1018 | linenum++; | ||
1019 | break; | ||
1020 | case 'N': /* Append the next line to the current line */ | ||
1021 | if (next_line) { | ||
1022 | pattern_space = | ||
1023 | realloc(pattern_space, | ||
1024 | strlen(pattern_space) + | ||
1025 | strlen(next_line) + 2); | ||
1026 | strcat(pattern_space, "\n"); | ||
1027 | strcat(pattern_space, next_line); | ||
980 | next_line = bb_get_chomped_line_from_file(file); | 1028 | next_line = bb_get_chomped_line_from_file(file); |
981 | linenum++; | 1029 | linenum++; |
982 | break; | 1030 | } |
983 | case 'N': /* Append the next line to the current line */ | 1031 | break; |
984 | if (next_line) { | 1032 | case 'b': |
985 | pattern_space = realloc(pattern_space, strlen(pattern_space) + strlen(next_line) + 2); | 1033 | sed_cmd = branch_to(sed_cmd->label); |
986 | strcat(pattern_space, "\n"); | 1034 | break; |
987 | strcat(pattern_space, next_line); | 1035 | case 't': |
988 | next_line = bb_get_chomped_line_from_file(file); | 1036 | if (substituted) { |
989 | linenum++; | ||
990 | } | ||
991 | break; | ||
992 | case 'b': | ||
993 | sed_cmd = branch_to(sed_cmd->label); | 1037 | sed_cmd = branch_to(sed_cmd->label); |
994 | break; | 1038 | } |
995 | case 't': | 1039 | break; |
996 | if (substituted) { | 1040 | case 'y':{ |
997 | sed_cmd = branch_to(sed_cmd->label); | 1041 | int i; |
998 | } | 1042 | |
999 | break; | 1043 | for (i = 0; pattern_space[i] != 0; i++) { |
1000 | case 'y': { | 1044 | int j; |
1001 | int i; | 1045 | |
1002 | for (i = 0; pattern_space[i] != 0; i++) { | 1046 | for (j = 0; sed_cmd->translate[j]; j += 2) { |
1003 | int j; | 1047 | if (pattern_space[i] == sed_cmd->translate[j]) { |
1004 | for (j = 0; sed_cmd->translate[j] ;j += 2) { | 1048 | pattern_space[i] = sed_cmd->translate[j + 1]; |
1005 | if (pattern_space[i] == sed_cmd->translate[j]) { | ||
1006 | pattern_space[i] = sed_cmd->translate[j + 1]; | ||
1007 | } | ||
1008 | } | ||
1009 | } | 1049 | } |
1010 | } | 1050 | } |
1011 | break; | 1051 | } |
1012 | case 'g': /* Replace pattern space with hold space */ | 1052 | } |
1013 | free(pattern_space); | 1053 | break; |
1014 | pattern_space = strdup(hold_space); | 1054 | case 'g': /* Replace pattern space with hold space */ |
1015 | break; | 1055 | free(pattern_space); |
1016 | case 'h': /* Replace hold space with pattern space */ | 1056 | pattern_space = strdup(hold_space); |
1017 | free(hold_space); | 1057 | break; |
1018 | hold_space = strdup(pattern_space); | 1058 | case 'h': /* Replace hold space with pattern space */ |
1019 | break; | 1059 | free(hold_space); |
1020 | case 'x': { /* Swap hold and pattern space */ | 1060 | hold_space = strdup(pattern_space); |
1021 | char *tmp; | 1061 | break; |
1022 | tmp = pattern_space; | 1062 | case 'x':{ |
1023 | pattern_space = hold_space; | 1063 | /* Swap hold and pattern space */ |
1024 | hold_space = tmp; | 1064 | char *tmp; |
1025 | } | 1065 | |
1066 | tmp = pattern_space; | ||
1067 | pattern_space = hold_space; | ||
1068 | hold_space = tmp; | ||
1069 | } | ||
1026 | } | 1070 | } |
1027 | } | 1071 | } |
1028 | 1072 | ||
@@ -1031,20 +1075,33 @@ static void process_file(FILE *file) | |||
1031 | */ | 1075 | */ |
1032 | if (matched) { | 1076 | if (matched) { |
1033 | if ( | 1077 | if ( |
1034 | /* this is a single-address command or... */ | 1078 | /* this is a single-address command or... */ |
1035 | (sed_cmd->end_line == 0 && sed_cmd->end_match == NULL) || ( | 1079 | (sed_cmd->end_line == 0 && sed_cmd->end_match == NULL) |
1036 | /* If only one address */ | 1080 | || ( |
1037 | 1081 | /* If only one address */ | |
1038 | /* we were in the middle of our address range (this | 1082 | /* we were in the middle of our address range (this |
1039 | * isn't the first time through) and.. */ | 1083 | * isn't the first time through) and.. */ |
1040 | (still_in_range == 1) && ( | 1084 | (still_in_range == 1) && ( |
1041 | /* this line number is the last address we're looking for or... */ | 1085 | /* this line number is the last address we're looking for or... */ |
1042 | (sed_cmd->end_line && (sed_cmd->end_line == linenum)) || | 1086 | (sed_cmd-> |
1043 | /* this line matches our last address regex */ | 1087 | end_line |
1044 | (sed_cmd->end_match && (regexec(sed_cmd->end_match, pattern_space, 0, NULL, 0) == 0)) | 1088 | && (sed_cmd-> |
1045 | ) | 1089 | end_line == |
1046 | ) | 1090 | linenum)) |
1047 | ) { | 1091 | || |
1092 | /* this line matches our last address regex */ | ||
1093 | (sed_cmd-> | ||
1094 | end_match | ||
1095 | && | ||
1096 | (regexec | ||
1097 | (sed_cmd-> | ||
1098 | end_match, | ||
1099 | pattern_space, | ||
1100 | 0, NULL, | ||
1101 | 0) == 0)) | ||
1102 | ) | ||
1103 | ) | ||
1104 | ) { | ||
1048 | /* we're out of our address range */ | 1105 | /* we're out of our address range */ |
1049 | still_in_range = 0; | 1106 | still_in_range = 0; |
1050 | } | 1107 | } |
@@ -1056,13 +1113,13 @@ static void process_file(FILE *file) | |||
1056 | } | 1113 | } |
1057 | 1114 | ||
1058 | if (deleted) | 1115 | if (deleted) |
1059 | break; | 1116 | break; |
1060 | } | 1117 | } |
1061 | 1118 | ||
1062 | /* we will print the line unless we were told to be quiet or if the | 1119 | /* we will print the line unless we were told to be quiet or if the |
1063 | * line was altered (via a 'd'elete or 's'ubstitution), in which case | 1120 | * line was altered (via a 'd'elete or 's'ubstitution), in which case |
1064 | * the altered line was already printed */ | 1121 | * the altered line was already printed */ |
1065 | if ((!be_quiet && !altered) || force_print){ | 1122 | if ((!be_quiet && !altered) || force_print) { |
1066 | puts(pattern_space); | 1123 | puts(pattern_space); |
1067 | } | 1124 | } |
1068 | free(pattern_space); | 1125 | free(pattern_space); |
@@ -1083,20 +1140,21 @@ extern int sed_main(int argc, char **argv) | |||
1083 | /* do normal option parsing */ | 1140 | /* do normal option parsing */ |
1084 | while ((opt = getopt(argc, argv, "ne:f:")) > 0) { | 1141 | while ((opt = getopt(argc, argv, "ne:f:")) > 0) { |
1085 | switch (opt) { | 1142 | switch (opt) { |
1086 | case 'n': | 1143 | case 'n': |
1087 | be_quiet++; | 1144 | be_quiet++; |
1088 | break; | 1145 | break; |
1089 | case 'e': { | 1146 | case 'e':{ |
1090 | char *str_cmd = strdup(optarg); | 1147 | char *str_cmd = strdup(optarg); |
1091 | add_cmd_str(str_cmd); | 1148 | |
1092 | free(str_cmd); | 1149 | add_cmd_str(str_cmd); |
1093 | break; | 1150 | free(str_cmd); |
1094 | } | 1151 | break; |
1095 | case 'f': | 1152 | } |
1096 | load_cmd_file(optarg); | 1153 | case 'f': |
1097 | break; | 1154 | load_cmd_file(optarg); |
1098 | default: | 1155 | break; |
1099 | bb_show_usage(); | 1156 | default: |
1157 | bb_show_usage(); | ||
1100 | } | 1158 | } |
1101 | } | 1159 | } |
1102 | 1160 | ||
@@ -1107,6 +1165,7 @@ extern int sed_main(int argc, char **argv) | |||
1107 | bb_show_usage(); | 1165 | bb_show_usage(); |
1108 | else { | 1166 | else { |
1109 | char *str_cmd = strdup(argv[optind]); | 1167 | char *str_cmd = strdup(argv[optind]); |
1168 | |||
1110 | add_cmd_str(strdup(str_cmd)); | 1169 | add_cmd_str(strdup(str_cmd)); |
1111 | free(str_cmd); | 1170 | free(str_cmd); |
1112 | optind++; | 1171 | optind++; |
@@ -1118,10 +1177,10 @@ extern int sed_main(int argc, char **argv) | |||
1118 | * Otherwise, we process all the files specified. */ | 1177 | * Otherwise, we process all the files specified. */ |
1119 | if (argv[optind] == NULL || (strcmp(argv[optind], "-") == 0)) { | 1178 | if (argv[optind] == NULL || (strcmp(argv[optind], "-") == 0)) { |
1120 | process_file(stdin); | 1179 | process_file(stdin); |
1121 | } | 1180 | } else { |
1122 | else { | ||
1123 | int i; | 1181 | int i; |
1124 | FILE *file; | 1182 | FILE *file; |
1183 | |||
1125 | for (i = optind; i < argc; i++) { | 1184 | for (i = optind; i < argc; i++) { |
1126 | file = bb_wfopen(argv[i], "r"); | 1185 | file = bb_wfopen(argv[i], "r"); |
1127 | if (file) { | 1186 | if (file) { |
@@ -1131,6 +1190,6 @@ extern int sed_main(int argc, char **argv) | |||
1131 | status = EXIT_FAILURE; | 1190 | status = EXIT_FAILURE; |
1132 | } | 1191 | } |
1133 | } | 1192 | } |
1134 | 1193 | ||
1135 | return status; | 1194 | return status; |
1136 | } | 1195 | } |