diff options
Diffstat (limited to 'editors/sed.c')
| -rw-r--r-- | editors/sed.c | 137 |
1 files changed, 59 insertions, 78 deletions
diff --git a/editors/sed.c b/editors/sed.c index 5dd5b2654..d90d63e43 100644 --- a/editors/sed.c +++ b/editors/sed.c | |||
| @@ -165,7 +165,7 @@ static void destroy_cmd_strs(void) | |||
| 165 | * a backslash ('\'). | 165 | * a backslash ('\'). |
| 166 | */ | 166 | */ |
| 167 | static int index_of_next_unescaped_regexp_delim(const char delimiter, | 167 | static int index_of_next_unescaped_regexp_delim(const char delimiter, |
| 168 | const char *str) | 168 | const char *str) |
| 169 | { | 169 | { |
| 170 | int bracket = -1; | 170 | int bracket = -1; |
| 171 | int escaped = 0; | 171 | int escaped = 0; |
| @@ -174,8 +174,8 @@ static int index_of_next_unescaped_regexp_delim(const char delimiter, | |||
| 174 | 174 | ||
| 175 | for (; (ch = str[idx]); idx++) { | 175 | for (; (ch = str[idx]); idx++) { |
| 176 | if (bracket != -1) { | 176 | if (bracket != -1) { |
| 177 | if (ch == ']' && !(bracket == idx - 1 || | 177 | if (ch == ']' && !(bracket == idx - 1 || (bracket == idx - 2 |
| 178 | (bracket == idx - 2 && str[idx - 1] == '^'))) | 178 | && str[idx - 1] == '^'))) |
| 179 | bracket = -1; | 179 | bracket = -1; |
| 180 | } else if (escaped) | 180 | } else if (escaped) |
| 181 | escaped = 0; | 181 | escaped = 0; |
| @@ -392,7 +392,7 @@ static int parse_edit_cmd(sed_cmd_t * sed_cmd, const char *editstr) | |||
| 392 | /* store the edit line text */ | 392 | /* store the edit line text */ |
| 393 | sed_cmd->editline = xmalloc(strlen(&editstr[2]) + 2); | 393 | sed_cmd->editline = xmalloc(strlen(&editstr[2]) + 2); |
| 394 | for (i = 2, j = 0; | 394 | for (i = 2, j = 0; |
| 395 | editstr[i] != '\0' && strchr("\r\n", editstr[i]) == NULL; i++, j++) { | 395 | editstr[i] != '\0' && strchr("\r\n", editstr[i]) == NULL; i++, j++) { |
| 396 | if ((editstr[i] == '\\') && strchr("\n\r", editstr[i + 1]) != NULL) { | 396 | if ((editstr[i] == '\\') && strchr("\n\r", editstr[i + 1]) != NULL) { |
| 397 | sed_cmd->editline[j] = '\n'; | 397 | sed_cmd->editline[j] = '\n'; |
| 398 | i++; | 398 | i++; |
| @@ -449,7 +449,7 @@ static int parse_file_cmd(sed_cmd_t * sed_cmd, const char *filecmdstr) | |||
| 449 | /* | 449 | /* |
| 450 | * Process the commands arguments | 450 | * Process the commands arguments |
| 451 | */ | 451 | */ |
| 452 | static char *parse_cmd_str(sed_cmd_t *sed_cmd, char *cmdstr) | 452 | static char *parse_cmd_str(sed_cmd_t * sed_cmd, char *cmdstr) |
| 453 | { | 453 | { |
| 454 | /* handle (s)ubstitution command */ | 454 | /* handle (s)ubstitution command */ |
| 455 | if (sed_cmd->cmd == 's') { | 455 | if (sed_cmd->cmd == 's') { |
| @@ -536,7 +536,7 @@ static char *add_cmd(sed_cmd_t * sed_cmd, char *cmdstr) | |||
| 536 | idx = get_address(cmdstr, &sed_cmd->end_line, &sed_cmd->end_match); | 536 | idx = get_address(cmdstr, &sed_cmd->end_line, &sed_cmd->end_match); |
| 537 | if (idx == 0) { | 537 | if (idx == 0) { |
| 538 | bb_error_msg_and_die("get_address: no address found in string\n" | 538 | bb_error_msg_and_die("get_address: no address found in string\n" |
| 539 | "\t(you probably didn't check the string you passed me)"); | 539 | "\t(you probably didn't check the string you passed me)"); |
| 540 | } | 540 | } |
| 541 | cmdstr += idx; | 541 | cmdstr += idx; |
| 542 | } | 542 | } |
| @@ -637,8 +637,8 @@ static void load_cmd_file(char *filename) | |||
| 637 | while ((line = bb_get_line_from_file(cmdfile)) != NULL) { | 637 | while ((line = bb_get_line_from_file(cmdfile)) != NULL) { |
| 638 | /* if a line ends with '\' it needs the next line appended to it */ | 638 | /* if a line ends with '\' it needs the next line appended to it */ |
| 639 | while (((e = last_char_is(line, '\n')) != NULL) | 639 | while (((e = last_char_is(line, '\n')) != NULL) |
| 640 | && (e > line) && (e[-1] == '\\') | 640 | && (e > line) && (e[-1] == '\\') |
| 641 | && ((nextline = bb_get_line_from_file(cmdfile)) != NULL)) { | 641 | && ((nextline = bb_get_line_from_file(cmdfile)) != NULL)) { |
| 642 | line = xrealloc(line, (e - line) + 1 + strlen(nextline) + 1); | 642 | line = xrealloc(line, (e - line) + 1 + strlen(nextline) + 1); |
| 643 | strcat(line, nextline); | 643 | strcat(line, nextline); |
| 644 | free(nextline); | 644 | free(nextline); |
| @@ -686,9 +686,7 @@ void pipe_putc(struct pipeline *const pipeline, char c) | |||
| 686 | #endif | 686 | #endif |
| 687 | 687 | ||
| 688 | static void print_subst_w_backrefs(const char *line, const char *replace, | 688 | static void print_subst_w_backrefs(const char *line, const char *replace, |
| 689 | regmatch_t * regmatch, | 689 | regmatch_t * regmatch, struct pipeline *const pipeline, int matches) |
| 690 | struct pipeline *const pipeline, | ||
| 691 | int matches) | ||
| 692 | { | 690 | { |
| 693 | int i; | 691 | int i; |
| 694 | 692 | ||
| @@ -707,7 +705,7 @@ static void print_subst_w_backrefs(const char *line, const char *replace, | |||
| 707 | /* print out the text held in regmatch[backref] */ | 705 | /* print out the text held in regmatch[backref] */ |
| 708 | if (backref <= matches && regmatch[backref].rm_so != -1) | 706 | if (backref <= matches && regmatch[backref].rm_so != -1) |
| 709 | for (j = regmatch[backref].rm_so; j < regmatch[backref].rm_eo; | 707 | for (j = regmatch[backref].rm_so; j < regmatch[backref].rm_eo; |
| 710 | j++) | 708 | j++) |
| 711 | pipeputc(line[j]); | 709 | pipeputc(line[j]); |
| 712 | } | 710 | } |
| 713 | 711 | ||
| @@ -723,6 +721,7 @@ static void print_subst_w_backrefs(const char *line, const char *replace, | |||
| 723 | * purpose...) */ | 721 | * purpose...) */ |
| 724 | else if (replace[i] == '&') { | 722 | else if (replace[i] == '&') { |
| 725 | int j; | 723 | int j; |
| 724 | |||
| 726 | for (j = regmatch[0].rm_so; j < regmatch[0].rm_eo; j++) | 725 | for (j = regmatch[0].rm_so; j < regmatch[0].rm_eo; j++) |
| 727 | pipeputc(line[j]); | 726 | pipeputc(line[j]); |
| 728 | } | 727 | } |
| @@ -766,9 +765,9 @@ static int do_subst_command(sed_cmd_t * sed_cmd, char **line) | |||
| 766 | 765 | ||
| 767 | /* and now, as long as we've got a line to try matching and if we can match | 766 | /* and now, as long as we've got a line to try matching and if we can match |
| 768 | * the search string, we make substitutions */ | 767 | * the search string, we make substitutions */ |
| 769 | while ((*hackline || !altered) && (regexec(current_regex, hackline, | 768 | while ((*hackline || !altered) |
| 770 | sed_cmd->num_backrefs + 1, | 769 | && (regexec(current_regex, hackline, sed_cmd->num_backrefs + 1, |
| 771 | regmatch, 0) != REG_NOMATCH)) { | 770 | regmatch, 0) != REG_NOMATCH)) { |
| 772 | int i; | 771 | int i; |
| 773 | 772 | ||
| 774 | /* print everything before the match */ | 773 | /* print everything before the match */ |
| @@ -776,8 +775,8 @@ static int do_subst_command(sed_cmd_t * sed_cmd, char **line) | |||
| 776 | pipeputc(hackline[i]); | 775 | pipeputc(hackline[i]); |
| 777 | 776 | ||
| 778 | /* then print the substitution string */ | 777 | /* then print the substitution string */ |
| 779 | print_subst_w_backrefs(hackline, sed_cmd->replace, regmatch, | 778 | print_subst_w_backrefs(hackline, sed_cmd->replace, regmatch, pipeline, |
| 780 | pipeline, sed_cmd->num_backrefs); | 779 | sed_cmd->num_backrefs); |
| 781 | 780 | ||
| 782 | /* advance past the match */ | 781 | /* advance past the match */ |
| 783 | hackline += regmatch[0].rm_eo; | 782 | hackline += regmatch[0].rm_eo; |
| @@ -805,6 +804,7 @@ static int do_subst_command(sed_cmd_t * sed_cmd, char **line) | |||
| 805 | static sed_cmd_t *branch_to(const char *label) | 804 | static sed_cmd_t *branch_to(const char *label) |
| 806 | { | 805 | { |
| 807 | sed_cmd_t *sed_cmd; | 806 | sed_cmd_t *sed_cmd; |
| 807 | |||
| 808 | for (sed_cmd = sed_cmd_head.next; sed_cmd; sed_cmd = sed_cmd->next) { | 808 | for (sed_cmd = sed_cmd_head.next; sed_cmd; sed_cmd = sed_cmd->next) { |
| 809 | if ((sed_cmd->label) && (strcmp(sed_cmd->label, label) == 0)) { | 809 | if ((sed_cmd->label) && (strcmp(sed_cmd->label, label) == 0)) { |
| 810 | break; | 810 | break; |
| @@ -843,31 +843,26 @@ static void process_file(FILE * file) | |||
| 843 | force_print = 0; | 843 | force_print = 0; |
| 844 | 844 | ||
| 845 | /* for every line, go through all the commands */ | 845 | /* for every line, go through all the commands */ |
| 846 | for (sed_cmd = sed_cmd_head.next; sed_cmd; | 846 | for (sed_cmd = sed_cmd_head.next; sed_cmd; sed_cmd = sed_cmd->next) { |
| 847 | sed_cmd = sed_cmd->next) { | ||
| 848 | int deleted = 0; | 847 | int deleted = 0; |
| 849 | 848 | ||
| 850 | /* | 849 | /* |
| 851 | * entry point into sedding... | 850 | * entry point into sedding... |
| 852 | */ | 851 | */ |
| 853 | int matched = ( | 852 | int matched = ( |
| 854 | /* no range necessary */ | 853 | /* no range necessary */ |
| 855 | (sed_cmd->beg_line == 0 | 854 | (sed_cmd->beg_line == 0 && sed_cmd->end_line == 0 |
| 856 | && sed_cmd->end_line == 0 | 855 | && sed_cmd->beg_match == NULL |
| 857 | && sed_cmd->beg_match == NULL | 856 | && sed_cmd->end_match == NULL) || |
| 858 | && sed_cmd->end_match == NULL) || | 857 | /* this line number is the first address we're looking for */ |
| 859 | /* this line number is the first address we're looking for */ | 858 | (sed_cmd->beg_line && (sed_cmd->beg_line == linenum)) || |
| 860 | (sed_cmd->beg_line | 859 | /* this line matches our first address regex */ |
| 861 | && (sed_cmd->beg_line == linenum)) || | 860 | (sed_cmd->beg_match |
| 862 | /* this line matches our first address regex */ | 861 | && (regexec(sed_cmd->beg_match, pattern_space, 0, NULL, |
| 863 | (sed_cmd->beg_match | 862 | 0) == 0)) || |
| 864 | && | 863 | /* we are currently within the beginning & ending address range */ |
| 865 | (regexec | 864 | still_in_range || ((sed_cmd->beg_line == -1) |
| 866 | (sed_cmd->beg_match, pattern_space, 0, NULL, | 865 | && (next_line == NULL)) |
| 867 | 0) == 0)) || | ||
| 868 | /* we are currently within the beginning & ending address range */ | ||
| 869 | still_in_range || ((sed_cmd->beg_line == -1) | ||
| 870 | && (next_line == NULL)) | ||
| 871 | ); | 866 | ); |
| 872 | 867 | ||
| 873 | if (sed_cmd->invert ^ matched) { | 868 | if (sed_cmd->invert ^ matched) { |
| @@ -927,7 +922,7 @@ static void process_file(FILE * file) | |||
| 927 | 922 | ||
| 928 | pattern_space = | 923 | pattern_space = |
| 929 | xrealloc(pattern_space, | 924 | xrealloc(pattern_space, |
| 930 | strlen(pattern_space) + 2); | 925 | strlen(pattern_space) + 2); |
| 931 | tmp = strchr(pattern_space + offset, '\n'); | 926 | tmp = strchr(pattern_space + offset, '\n'); |
| 932 | memmove(tmp + 1, tmp, strlen(tmp) + 1); | 927 | memmove(tmp + 1, tmp, strlen(tmp) + 1); |
| 933 | tmp[0] = '\\'; | 928 | tmp[0] = '\\'; |
| @@ -952,8 +947,7 @@ static void process_file(FILE * file) | |||
| 952 | #endif | 947 | #endif |
| 953 | altered |= substituted; | 948 | altered |= substituted; |
| 954 | if (!be_quiet && altered && ((sed_cmd->next == NULL) | 949 | if (!be_quiet && altered && ((sed_cmd->next == NULL) |
| 955 | || (sed_cmd->next->cmd != | 950 | || (sed_cmd->next->cmd != 's'))) { |
| 956 | 's'))) { | ||
| 957 | force_print = 1; | 951 | force_print = 1; |
| 958 | } | 952 | } |
| 959 | 953 | ||
| @@ -979,10 +973,8 @@ static void process_file(FILE * file) | |||
| 979 | /* multi-address case */ | 973 | /* multi-address case */ |
| 980 | /* - matching text */ | 974 | /* - matching text */ |
| 981 | || (sed_cmd->end_match | 975 | || (sed_cmd->end_match |
| 982 | && | 976 | && (regexec(sed_cmd->end_match, pattern_space, 0, |
| 983 | (regexec | 977 | NULL, 0) == 0)) |
| 984 | (sed_cmd->end_match, pattern_space, 0, NULL, | ||
| 985 | 0) == 0)) | ||
| 986 | /* - matching line numbers */ | 978 | /* - matching line numbers */ |
| 987 | || (sed_cmd->end_line > 0 | 979 | || (sed_cmd->end_line > 0 |
| 988 | && sed_cmd->end_line == linenum)) { | 980 | && sed_cmd->end_line == linenum)) { |
| @@ -994,11 +986,17 @@ static void process_file(FILE * file) | |||
| 994 | 986 | ||
| 995 | case 'r':{ | 987 | case 'r':{ |
| 996 | FILE *outfile; | 988 | FILE *outfile; |
| 989 | |||
| 997 | outfile = fopen(sed_cmd->filename, "r"); | 990 | outfile = fopen(sed_cmd->filename, "r"); |
| 998 | if (outfile) { | 991 | if (outfile) { |
| 999 | char *line; | 992 | char *line; |
| 1000 | while ((line = bb_get_chomped_line_from_file(outfile)) != NULL) { | 993 | |
| 1001 | pattern_space = xrealloc(pattern_space, strlen(line) + strlen(pattern_space) + 2); | 994 | while ((line = |
| 995 | bb_get_chomped_line_from_file(outfile)) != | ||
| 996 | NULL) { | ||
| 997 | pattern_space = | ||
| 998 | xrealloc(pattern_space, | ||
| 999 | strlen(line) + strlen(pattern_space) + 2); | ||
| 1002 | strcat(pattern_space, "\n"); | 1000 | strcat(pattern_space, "\n"); |
| 1003 | strcat(pattern_space, line); | 1001 | strcat(pattern_space, line); |
| 1004 | } | 1002 | } |
| @@ -1023,8 +1021,7 @@ static void process_file(FILE * file) | |||
| 1023 | if (next_line) { | 1021 | if (next_line) { |
| 1024 | pattern_space = | 1022 | pattern_space = |
| 1025 | realloc(pattern_space, | 1023 | realloc(pattern_space, |
| 1026 | strlen(pattern_space) + | 1024 | strlen(pattern_space) + strlen(next_line) + 2); |
| 1027 | strlen(next_line) + 2); | ||
| 1028 | strcat(pattern_space, "\n"); | 1025 | strcat(pattern_space, "\n"); |
| 1029 | strcat(pattern_space, next_line); | 1026 | strcat(pattern_space, next_line); |
| 1030 | next_line = bb_get_chomped_line_from_file(file); | 1027 | next_line = bb_get_chomped_line_from_file(file); |
| @@ -1077,39 +1074,23 @@ static void process_file(FILE * file) | |||
| 1077 | */ | 1074 | */ |
| 1078 | if (matched) { | 1075 | if (matched) { |
| 1079 | if ( | 1076 | if ( |
| 1080 | /* this is a single-address command or... */ | 1077 | /* this is a single-address command or... */ |
| 1081 | (sed_cmd->end_line == 0 && sed_cmd->end_match == NULL) | 1078 | (sed_cmd->end_line == 0 && sed_cmd->end_match == NULL) |
| 1082 | || ( | 1079 | /* If only one address */ |
| 1083 | /* If only one address */ | 1080 | /* we were in the middle of our address range (this |
| 1084 | /* we were in the middle of our address range (this | 1081 | * isn't the first time through) and.. */ |
| 1085 | * isn't the first time through) and.. */ | 1082 | || ((still_in_range == 1) |
| 1086 | (still_in_range == 1) && ( | 1083 | /* this line number is the last address we're looking for or... */ |
| 1087 | /* this line number is the last address we're looking for or... */ | 1084 | && ((sed_cmd->end_line |
| 1088 | (sed_cmd-> | 1085 | && (sed_cmd->end_line == linenum)) |
| 1089 | end_line | 1086 | /* this line matches our last address regex */ |
| 1090 | && (sed_cmd-> | 1087 | || (sed_cmd->end_match |
| 1091 | end_line == | 1088 | && (regexec(sed_cmd->end_match, pattern_space, |
| 1092 | linenum)) | 1089 | 0, NULL, 0) == 0))))) { |
| 1093 | || | ||
| 1094 | /* this line matches our last address regex */ | ||
| 1095 | (sed_cmd-> | ||
| 1096 | end_match | ||
| 1097 | && | ||
| 1098 | (regexec | ||
| 1099 | (sed_cmd-> | ||
| 1100 | end_match, | ||
| 1101 | pattern_space, | ||
| 1102 | 0, NULL, | ||
| 1103 | 0) == 0)) | ||
| 1104 | ) | ||
| 1105 | ) | ||
| 1106 | ) { | ||
| 1107 | /* we're out of our address range */ | 1090 | /* we're out of our address range */ |
| 1108 | still_in_range = 0; | 1091 | still_in_range = 0; |
| 1109 | } | 1092 | } else { |
| 1110 | 1093 | /* didn't hit the exit? then we're still in the middle of an address range */ | |
| 1111 | /* didn't hit the exit? then we're still in the middle of an address range */ | ||
| 1112 | else { | ||
| 1113 | still_in_range = 1; | 1094 | still_in_range = 1; |
| 1114 | } | 1095 | } |
| 1115 | } | 1096 | } |
