diff options
author | bug1 <bug1@69ca8d6d-28ef-0310-b511-8ec308f3f277> | 2003-04-08 06:42:45 +0000 |
---|---|---|
committer | bug1 <bug1@69ca8d6d-28ef-0310-b511-8ec308f3f277> | 2003-04-08 06:42:45 +0000 |
commit | 525f775a1f7c27b97efc36d31644a7faee84dd59 (patch) | |
tree | 22914a84a0ba6b1ba4a32c54acd2a8b9a2314ef5 | |
parent | e8a89de0637429ebad10eac8bda102539853f59c (diff) | |
download | busybox-w32-525f775a1f7c27b97efc36d31644a7faee84dd59.tar.gz busybox-w32-525f775a1f7c27b97efc36d31644a7faee84dd59.tar.bz2 busybox-w32-525f775a1f7c27b97efc36d31644a7faee84dd59.zip |
Fixes block commands to correctly identify end of block, recognise the #n directive, fix substitue command when regex isnt specified
git-svn-id: svn://busybox.net/trunk/busybox@6785 69ca8d6d-28ef-0310-b511-8ec308f3f277
-rw-r--r-- | editors/sed.c | 90 |
1 files changed, 63 insertions, 27 deletions
diff --git a/editors/sed.c b/editors/sed.c index 1673ee2d4..1e2191864 100644 --- a/editors/sed.c +++ b/editors/sed.c | |||
@@ -119,8 +119,11 @@ typedef struct sed_cmd_s { | |||
119 | /* linked list of sed commands */ | 119 | /* linked list of sed commands */ |
120 | static sed_cmd_t sed_cmd_head; | 120 | static sed_cmd_t sed_cmd_head; |
121 | static sed_cmd_t *sed_cmd_tail = &sed_cmd_head; | 121 | static sed_cmd_t *sed_cmd_tail = &sed_cmd_head; |
122 | static sed_cmd_t *block_cmd; | ||
122 | 123 | ||
124 | static int in_block = 0; | ||
123 | const char * const semicolon_whitespace = "; \n\r\t\v\0"; | 125 | const char * const semicolon_whitespace = "; \n\r\t\v\0"; |
126 | static regex_t *previous_regex_ptr = NULL; | ||
124 | 127 | ||
125 | #ifdef CONFIG_FEATURE_CLEAN_UP | 128 | #ifdef CONFIG_FEATURE_CLEAN_UP |
126 | static void destroy_cmd_strs(void) | 129 | static void destroy_cmd_strs(void) |
@@ -245,6 +248,7 @@ static int get_address(char *my_str, int *linenum, regex_t **regex) | |||
245 | bb_error_msg_and_die("unterminated match expression"); | 248 | bb_error_msg_and_die("unterminated match expression"); |
246 | } | 249 | } |
247 | my_str[idx] = '\0'; | 250 | my_str[idx] = '\0'; |
251 | |||
248 | *regex = (regex_t *)xmalloc(sizeof(regex_t)); | 252 | *regex = (regex_t *)xmalloc(sizeof(regex_t)); |
249 | xregcomp(*regex, my_str+idx_start, REG_NEWLINE); | 253 | xregcomp(*regex, my_str+idx_start, REG_NEWLINE); |
250 | idx++; /* so it points to the next character after the last '/' */ | 254 | idx++; /* so it points to the next character after the last '/' */ |
@@ -305,8 +309,11 @@ static int parse_subst_cmd(sed_cmd_t * const sed_cmd, const char *substr) | |||
305 | 309 | ||
306 | out: | 310 | out: |
307 | /* compile the match string into a regex */ | 311 | /* compile the match string into a regex */ |
308 | sed_cmd->sub_match = (regex_t *)xmalloc(sizeof(regex_t)); | 312 | if (*match != '\0') { |
309 | xregcomp(sed_cmd->sub_match, match, cflags); | 313 | /* If match is empty, we use last regex used at runtime */ |
314 | sed_cmd->sub_match = (regex_t *)xmalloc(sizeof(regex_t)); | ||
315 | xregcomp(sed_cmd->sub_match, match, cflags); | ||
316 | } | ||
310 | free(match); | 317 | free(match); |
311 | 318 | ||
312 | return idx; | 319 | return idx; |
@@ -493,8 +500,19 @@ static char *add_cmd(sed_cmd_t *sed_cmd, char *cmdstr) | |||
493 | 500 | ||
494 | /* if this is a comment, jump past it and keep going */ | 501 | /* if this is a comment, jump past it and keep going */ |
495 | if (*cmdstr == '#') { | 502 | if (*cmdstr == '#') { |
503 | /* "#n" is the same as using -n on the command line */ | ||
504 | if (cmdstr[1] == 'n') { | ||
505 | be_quiet++; | ||
506 | } | ||
496 | return(strpbrk(cmdstr, "\n\r")); | 507 | return(strpbrk(cmdstr, "\n\r")); |
497 | } | 508 | } |
509 | |||
510 | /* Test for end of block */ | ||
511 | if (*cmdstr == '}') { | ||
512 | in_block = 0; | ||
513 | cmdstr++; | ||
514 | return(cmdstr); | ||
515 | } | ||
498 | 516 | ||
499 | /* parse the command | 517 | /* parse the command |
500 | * format is: [addr][,addr]cmd | 518 | * format is: [addr][,addr]cmd |
@@ -548,32 +566,34 @@ static char *add_cmd(sed_cmd_t *sed_cmd, char *cmdstr) | |||
548 | if (*cmdstr == '\0') | 566 | if (*cmdstr == '\0') |
549 | bb_error_msg_and_die("missing command"); | 567 | bb_error_msg_and_die("missing command"); |
550 | 568 | ||
569 | /* This is the start of a block of commands */ | ||
570 | if (*cmdstr == '{') { | ||
571 | if (in_block != 0) { | ||
572 | bb_error_msg_and_die("cant handle sub-blocks"); | ||
573 | } | ||
574 | in_block = 1; | ||
575 | block_cmd = sed_cmd; | ||
576 | |||
577 | return(cmdstr + 1); | ||
578 | } | ||
579 | |||
551 | sed_cmd->cmd = *cmdstr; | 580 | sed_cmd->cmd = *cmdstr; |
552 | cmdstr++; | 581 | cmdstr++; |
553 | 582 | ||
554 | if (sed_cmd->cmd == '{') { | 583 | if (in_block == 1) { |
555 | do { | 584 | sed_cmd->beg_match = block_cmd->beg_match; |
556 | sed_cmd_t *sed_cmd_new; | 585 | sed_cmd->end_match = block_cmd->end_match; |
557 | char *end_ptr = strpbrk(cmdstr, ";}"); | 586 | sed_cmd->beg_line = block_cmd->beg_line; |
558 | 587 | sed_cmd->end_line = block_cmd->end_line; | |
559 | *end_ptr = '\0'; | 588 | sed_cmd->invert = block_cmd->invert; |
560 | sed_cmd_new = xcalloc(1, sizeof(sed_cmd_t)); | ||
561 | sed_cmd_new->beg_match = sed_cmd->beg_match; | ||
562 | sed_cmd_new->end_match = sed_cmd->end_match; | ||
563 | sed_cmd_new->beg_line = sed_cmd->beg_line; | ||
564 | sed_cmd_new->end_line = sed_cmd->end_line; | ||
565 | sed_cmd_new->invert = sed_cmd->invert; | ||
566 | |||
567 | add_cmd(sed_cmd_new, cmdstr); | ||
568 | cmdstr = end_ptr + 1; | ||
569 | } while (*cmdstr != '\0'); | ||
570 | } else { | ||
571 | cmdstr = parse_cmd_str(sed_cmd, cmdstr); | ||
572 | |||
573 | /* Add the command to the command array */ | ||
574 | sed_cmd_tail->linear = sed_cmd; | ||
575 | sed_cmd_tail = sed_cmd_tail->linear; | ||
576 | } | 589 | } |
590 | |||
591 | cmdstr = parse_cmd_str(sed_cmd, cmdstr); | ||
592 | |||
593 | /* Add the command to the command array */ | ||
594 | sed_cmd_tail->linear = sed_cmd; | ||
595 | sed_cmd_tail = sed_cmd_tail->linear; | ||
596 | |||
577 | return(cmdstr); | 597 | return(cmdstr); |
578 | } | 598 | } |
579 | 599 | ||
@@ -700,17 +720,27 @@ static void print_subst_w_backrefs(const char *line, const char *replace, | |||
700 | } | 720 | } |
701 | } | 721 | } |
702 | 722 | ||
703 | static int do_subst_command(const sed_cmd_t *sed_cmd, char **line) | 723 | static int do_subst_command(sed_cmd_t *sed_cmd, char **line) |
704 | { | 724 | { |
705 | char *hackline = *line; | 725 | char *hackline = *line; |
706 | struct pipeline thepipe = { NULL, 0 , 0}; | 726 | struct pipeline thepipe = { NULL, 0 , 0}; |
707 | struct pipeline *const pipeline = &thepipe; | 727 | struct pipeline *const pipeline = &thepipe; |
708 | int altered = 0; | 728 | int altered = 0; |
729 | int result; | ||
709 | regmatch_t *regmatch = NULL; | 730 | regmatch_t *regmatch = NULL; |
731 | regex_t *current_regex; | ||
732 | |||
733 | if (sed_cmd->sub_match == NULL) { | ||
734 | current_regex = previous_regex_ptr; | ||
735 | } else { | ||
736 | previous_regex_ptr = current_regex = sed_cmd->sub_match; | ||
737 | } | ||
738 | result = regexec(current_regex, hackline, 0, NULL, 0); | ||
710 | 739 | ||
711 | /* we only proceed if the substitution 'search' expression matches */ | 740 | /* we only proceed if the substitution 'search' expression matches */ |
712 | if (regexec(sed_cmd->sub_match, hackline, 0, NULL, 0) == REG_NOMATCH) | 741 | if (result == REG_NOMATCH) { |
713 | return 0; | 742 | return 0; |
743 | } | ||
714 | 744 | ||
715 | /* whaddaya know, it matched. get the number of back references */ | 745 | /* whaddaya know, it matched. get the number of back references */ |
716 | regmatch = xmalloc(sizeof(regmatch_t) * (sed_cmd->num_backrefs+1)); | 746 | regmatch = xmalloc(sizeof(regmatch_t) * (sed_cmd->num_backrefs+1)); |
@@ -724,7 +754,7 @@ static int do_subst_command(const sed_cmd_t *sed_cmd, char **line) | |||
724 | 754 | ||
725 | /* and now, as long as we've got a line to try matching and if we can match | 755 | /* and now, as long as we've got a line to try matching and if we can match |
726 | * the search string, we make substitutions */ | 756 | * the search string, we make substitutions */ |
727 | while ((*hackline || !altered) && (regexec(sed_cmd->sub_match, hackline, | 757 | while ((*hackline || !altered) && (regexec(current_regex, hackline, |
728 | sed_cmd->num_backrefs+1, regmatch, 0) != REG_NOMATCH) ) { | 758 | sed_cmd->num_backrefs+1, regmatch, 0) != REG_NOMATCH) ) { |
729 | int i; | 759 | int i; |
730 | 760 | ||
@@ -818,6 +848,10 @@ static void process_file(FILE *file) | |||
818 | ); | 848 | ); |
819 | 849 | ||
820 | if (sed_cmd->invert ^ matched) { | 850 | if (sed_cmd->invert ^ matched) { |
851 | /* Update last used regex incase a blank substitute BRE is found */ | ||
852 | if (sed_cmd->beg_match) { | ||
853 | previous_regex_ptr = sed_cmd->beg_match; | ||
854 | } | ||
821 | 855 | ||
822 | /* | 856 | /* |
823 | * actual sedding | 857 | * actual sedding |
@@ -999,6 +1033,8 @@ static void process_file(FILE *file) | |||
999 | if ( | 1033 | if ( |
1000 | /* this is a single-address command or... */ | 1034 | /* this is a single-address command or... */ |
1001 | (sed_cmd->end_line == 0 && sed_cmd->end_match == NULL) || ( | 1035 | (sed_cmd->end_line == 0 && sed_cmd->end_match == NULL) || ( |
1036 | /* If only one address */ | ||
1037 | |||
1002 | /* we were in the middle of our address range (this | 1038 | /* we were in the middle of our address range (this |
1003 | * isn't the first time through) and.. */ | 1039 | * isn't the first time through) and.. */ |
1004 | (still_in_range == 1) && ( | 1040 | (still_in_range == 1) && ( |