diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2006-12-10 02:09:12 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2006-12-10 02:09:12 +0000 |
commit | 2f8f71b20dbce1328a5175bb75ae15564f7e9489 (patch) | |
tree | b806ee9d337d89ec3bc4f57eaaed1626560b68c8 | |
parent | b15b7f7a4a06733fde996737110524d119b69106 (diff) | |
download | busybox-w32-2f8f71b20dbce1328a5175bb75ae15564f7e9489.tar.gz busybox-w32-2f8f71b20dbce1328a5175bb75ae15564f7e9489.tar.bz2 busybox-w32-2f8f71b20dbce1328a5175bb75ae15564f7e9489.zip |
sed: style fixes
-rw-r--r-- | editors/sed.c | 666 |
1 files changed, 338 insertions, 328 deletions
diff --git a/editors/sed.c b/editors/sed.c index 94368aa68..877d1c420 100644 --- a/editors/sed.c +++ b/editors/sed.c | |||
@@ -91,15 +91,14 @@ typedef struct sed_cmd_s { | |||
91 | 91 | ||
92 | static const char *const semicolon_whitespace = "; \n\r\t\v"; | 92 | static const char *const semicolon_whitespace = "; \n\r\t\v"; |
93 | 93 | ||
94 | struct sed_globals | 94 | struct sed_globals { |
95 | { | ||
96 | /* options */ | 95 | /* options */ |
97 | int be_quiet, in_place, regex_type; | 96 | int be_quiet, regex_type; |
98 | FILE *nonstdout; | 97 | FILE *nonstdout; |
99 | char *outname, *hold_space; | 98 | char *outname, *hold_space; |
100 | 99 | ||
101 | /* List of input files */ | 100 | /* List of input files */ |
102 | int input_file_count,current_input_file; | 101 | int input_file_count, current_input_file; |
103 | FILE **input_file_list; | 102 | FILE **input_file_list; |
104 | 103 | ||
105 | regmatch_t regmatch[10]; | 104 | regmatch_t regmatch[10]; |
@@ -123,7 +122,7 @@ struct sed_globals | |||
123 | 122 | ||
124 | void sed_free_and_close_stuff(void); | 123 | void sed_free_and_close_stuff(void); |
125 | #if ENABLE_FEATURE_CLEAN_UP | 124 | #if ENABLE_FEATURE_CLEAN_UP |
126 | void sed_free_and_close_stuff(void) | 125 | static void sed_free_and_close_stuff(void) |
127 | { | 126 | { |
128 | sed_cmd_t *sed_cmd = bbg.sed_cmd_head.next; | 127 | sed_cmd_t *sed_cmd = bbg.sed_cmd_head.next; |
129 | 128 | ||
@@ -187,9 +186,9 @@ static void parse_escapes(char *dest, char *string, int len, char from, char to) | |||
187 | 186 | ||
188 | static char *copy_parsing_escapes(char *string, int len) | 187 | static char *copy_parsing_escapes(char *string, int len) |
189 | { | 188 | { |
190 | char *dest = xmalloc(len+1); | 189 | char *dest = xmalloc(len + 1); |
191 | 190 | ||
192 | parse_escapes(dest,string,len,'n','\n'); | 191 | parse_escapes(dest, string, len, 'n', '\n'); |
193 | return dest; | 192 | return dest; |
194 | } | 193 | } |
195 | 194 | ||
@@ -209,7 +208,7 @@ static int index_of_next_unescaped_regexp_delim(int delimiter, char *str) | |||
209 | 208 | ||
210 | if (delimiter < 0) { | 209 | if (delimiter < 0) { |
211 | bracket--; | 210 | bracket--; |
212 | delimiter *= -1; | 211 | delimiter = -delimiter; |
213 | } | 212 | } |
214 | 213 | ||
215 | for (; (ch = str[idx]); idx++) { | 214 | for (; (ch = str[idx]); idx++) { |
@@ -228,7 +227,7 @@ static int index_of_next_unescaped_regexp_delim(int delimiter, char *str) | |||
228 | } | 227 | } |
229 | 228 | ||
230 | /* 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 */ |
231 | bb_error_msg_and_die("unmatched '%c'",delimiter); | 230 | bb_error_msg_and_die("unmatched '%c'", delimiter); |
232 | } | 231 | } |
233 | 232 | ||
234 | /* | 233 | /* |
@@ -279,7 +278,7 @@ static int get_address(char *my_str, int *linenum, regex_t ** regex) | |||
279 | delimiter = '/'; | 278 | delimiter = '/'; |
280 | if (*my_str == '\\') delimiter = *++pos; | 279 | if (*my_str == '\\') delimiter = *++pos; |
281 | next = index_of_next_unescaped_regexp_delim(delimiter, ++pos); | 280 | next = index_of_next_unescaped_regexp_delim(delimiter, ++pos); |
282 | temp = copy_parsing_escapes(pos,next); | 281 | temp = copy_parsing_escapes(pos, next); |
283 | *regex = xmalloc(sizeof(regex_t)); | 282 | *regex = xmalloc(sizeof(regex_t)); |
284 | xregcomp(*regex, temp, bbg.regex_type|REG_NEWLINE); | 283 | xregcomp(*regex, temp, bbg.regex_type|REG_NEWLINE); |
285 | free(temp); | 284 | free(temp); |
@@ -336,9 +335,10 @@ static int parse_subst_cmd(sed_cmd_t *sed_cmd, char *substr) | |||
336 | if (isdigit(substr[idx])) { | 335 | if (isdigit(substr[idx])) { |
337 | if (match[0] != '^') { | 336 | if (match[0] != '^') { |
338 | /* Match 0 treated as all, multiple matches we take the last one. */ | 337 | /* Match 0 treated as all, multiple matches we take the last one. */ |
339 | char *pos = substr+idx; | 338 | char *pos = substr + idx; |
340 | sed_cmd->which_match = (unsigned short)strtol(substr+idx,&pos,10); | 339 | /* FIXME: error check? */ |
341 | idx = pos-substr; | 340 | sed_cmd->which_match = (unsigned short)strtol(substr+idx, &pos, 10); |
341 | idx = pos - substr; | ||
342 | } | 342 | } |
343 | continue; | 343 | continue; |
344 | } | 344 | } |
@@ -358,7 +358,7 @@ static int parse_subst_cmd(sed_cmd_t *sed_cmd, char *substr) | |||
358 | case 'w': | 358 | case 'w': |
359 | { | 359 | { |
360 | char *temp; | 360 | char *temp; |
361 | idx += parse_file_cmd(sed_cmd,substr+idx,&temp); | 361 | idx += parse_file_cmd(sed_cmd, substr+idx, &temp); |
362 | 362 | ||
363 | break; | 363 | break; |
364 | } | 364 | } |
@@ -413,7 +413,7 @@ static char *parse_cmd_args(sed_cmd_t *sed_cmd, char *cmdstr) | |||
413 | break; | 413 | break; |
414 | } | 414 | } |
415 | sed_cmd->string = xstrdup(cmdstr); | 415 | sed_cmd->string = xstrdup(cmdstr); |
416 | parse_escapes(sed_cmd->string,sed_cmd->string,strlen(cmdstr),0,0); | 416 | parse_escapes(sed_cmd->string, sed_cmd->string, strlen(cmdstr), 0, 0); |
417 | cmdstr += strlen(cmdstr); | 417 | cmdstr += strlen(cmdstr); |
418 | /* handle file cmds: (r)ead */ | 418 | /* handle file cmds: (r)ead */ |
419 | } else if (strchr("rw", sed_cmd->cmd)) { | 419 | } else if (strchr("rw", sed_cmd->cmd)) { |
@@ -421,7 +421,7 @@ static char *parse_cmd_args(sed_cmd_t *sed_cmd, char *cmdstr) | |||
421 | bb_error_msg_and_die("command only uses one address"); | 421 | bb_error_msg_and_die("command only uses one address"); |
422 | cmdstr += parse_file_cmd(sed_cmd, cmdstr, &sed_cmd->string); | 422 | cmdstr += parse_file_cmd(sed_cmd, cmdstr, &sed_cmd->string); |
423 | if (sed_cmd->cmd == 'w') | 423 | if (sed_cmd->cmd == 'w') |
424 | sed_cmd->file = xfopen(sed_cmd->string,"w"); | 424 | sed_cmd->file = xfopen(sed_cmd->string, "w"); |
425 | /* handle branch commands */ | 425 | /* handle branch commands */ |
426 | } else if (strchr(":btT", sed_cmd->cmd)) { | 426 | } else if (strchr(":btT", sed_cmd->cmd)) { |
427 | int length; | 427 | int length; |
@@ -440,8 +440,8 @@ static char *parse_cmd_args(sed_cmd_t *sed_cmd, char *cmdstr) | |||
440 | 440 | ||
441 | cmdstr += parse_regex_delim(cmdstr, &match, &replace)+1; | 441 | cmdstr += parse_regex_delim(cmdstr, &match, &replace)+1; |
442 | /* \n already parsed, but \delimiter needs unescaping. */ | 442 | /* \n already parsed, but \delimiter needs unescaping. */ |
443 | parse_escapes(match,match,strlen(match),i,i); | 443 | parse_escapes(match, match, strlen(match), i, i); |
444 | parse_escapes(replace,replace,strlen(replace),i,i); | 444 | parse_escapes(replace, replace, strlen(replace), i, i); |
445 | 445 | ||
446 | sed_cmd->string = xzalloc((strlen(match) + 1) * 2); | 446 | sed_cmd->string = xzalloc((strlen(match) + 1) * 2); |
447 | for (i = 0; match[i] && replace[i]; i++) { | 447 | for (i = 0; match[i] && replace[i]; i++) { |
@@ -641,7 +641,7 @@ static int do_subst_command(sed_cmd_t *sed_cmd, char **line) | |||
641 | 641 | ||
642 | /* If we aren't interested in this match, output old line to | 642 | /* If we aren't interested in this match, output old line to |
643 | end of match and continue */ | 643 | end of match and continue */ |
644 | if (sed_cmd->which_match && sed_cmd->which_match!=match_count) { | 644 | if (sed_cmd->which_match && sed_cmd->which_match != match_count) { |
645 | for (i = 0; i < bbg.regmatch[0].rm_eo; i++) | 645 | for (i = 0; i < bbg.regmatch[0].rm_eo; i++) |
646 | pipe_putc(*oldline++); | 646 | pipe_putc(*oldline++); |
647 | continue; | 647 | continue; |
@@ -698,7 +698,7 @@ static void flush_append(void) | |||
698 | 698 | ||
699 | /* Output appended lines. */ | 699 | /* Output appended lines. */ |
700 | while ((data = (char *)llist_pop(&bbg.append_head))) { | 700 | while ((data = (char *)llist_pop(&bbg.append_head))) { |
701 | fprintf(bbg.nonstdout,"%s\n",data); | 701 | fprintf(bbg.nonstdout, "%s\n", data); |
702 | free(data); | 702 | free(data); |
703 | } | 703 | } |
704 | } | 704 | } |
@@ -801,325 +801,327 @@ static void process_files(void) | |||
801 | next_line = get_next_line(&next_last_char); | 801 | next_line = get_next_line(&next_last_char); |
802 | 802 | ||
803 | /* go through every line in each file */ | 803 | /* go through every line in each file */ |
804 | for (;;) { | 804 | again: |
805 | sed_cmd_t *sed_cmd; | ||
806 | int substituted = 0; | ||
807 | |||
808 | /* Advance to next line. Stop if out of lines. */ | ||
809 | pattern_space = next_line; | ||
810 | if (!pattern_space) break; | ||
811 | last_char = next_last_char; | ||
812 | |||
813 | /* Read one line in advance so we can act on the last line, | ||
814 | * the '$' address */ | ||
815 | next_line = get_next_line(&next_last_char); | ||
816 | linenum++; | ||
817 | restart: | ||
818 | /* for every line, go through all the commands */ | ||
819 | for (sed_cmd = bbg.sed_cmd_head.next; sed_cmd; sed_cmd = sed_cmd->next) { | ||
820 | int old_matched, matched; | ||
821 | |||
822 | old_matched = sed_cmd->in_match; | ||
823 | |||
824 | /* Determine if this command matches this line: */ | ||
825 | |||
826 | /* Are we continuing a previous multi-line match? */ | ||
827 | sed_cmd->in_match = sed_cmd->in_match | ||
828 | /* Or is no range necessary? */ | ||
829 | || (!sed_cmd->beg_line && !sed_cmd->end_line | ||
830 | && !sed_cmd->beg_match && !sed_cmd->end_match) | ||
831 | /* Or did we match the start of a numerical range? */ | ||
832 | || (sed_cmd->beg_line > 0 && (sed_cmd->beg_line == linenum)) | ||
833 | /* Or does this line match our begin address regex? */ | ||
834 | || (sed_cmd->beg_match && | ||
835 | !regexec(sed_cmd->beg_match, pattern_space, 0, NULL, 0)) | ||
836 | /* Or did we match last line of input? */ | ||
837 | || (sed_cmd->beg_line == -1 && next_line == NULL); | ||
838 | |||
839 | /* Snapshot the value */ | ||
840 | |||
841 | matched = sed_cmd->in_match; | ||
842 | |||
843 | /* Is this line the end of the current match? */ | ||
844 | |||
845 | if (matched) { | ||
846 | sed_cmd->in_match = !( | ||
847 | /* has the ending line come, or is this a single address command? */ | ||
848 | (sed_cmd->end_line ? | ||
849 | sed_cmd->end_line==-1 ? | ||
850 | !next_line | ||
851 | : sed_cmd->end_line<=linenum | ||
852 | : !sed_cmd->end_match) | ||
853 | /* or does this line matches our last address regex */ | ||
854 | || (sed_cmd->end_match && old_matched && (regexec(sed_cmd->end_match, pattern_space, 0, NULL, 0) == 0)) | ||
855 | ); | ||
856 | } | ||
857 | 805 | ||
858 | /* Skip blocks of commands we didn't match. */ | 806 | sed_cmd_t *sed_cmd; |
859 | if (sed_cmd->cmd == '{') { | 807 | int substituted = 0; |
860 | if (sed_cmd->invert ? matched : !matched) | ||
861 | while (sed_cmd && sed_cmd->cmd != '}') | ||
862 | sed_cmd = sed_cmd->next; | ||
863 | if (!sed_cmd) bb_error_msg_and_die("unterminated {"); | ||
864 | continue; | ||
865 | } | ||
866 | 808 | ||
867 | /* Okay, so did this line match? */ | 809 | /* Advance to next line. Stop if out of lines. */ |
868 | if (sed_cmd->invert ? !matched : matched) { | 810 | pattern_space = next_line; |
869 | /* Update last used regex in case a blank substitute BRE is found */ | 811 | if (!pattern_space) return; |
870 | if (sed_cmd->beg_match) { | 812 | last_char = next_last_char; |
871 | bbg.previous_regex_ptr = sed_cmd->beg_match; | ||
872 | } | ||
873 | 813 | ||
874 | /* actual sedding */ | 814 | /* Read one line in advance so we can act on the last line, |
875 | switch (sed_cmd->cmd) { | 815 | * the '$' address */ |
816 | next_line = get_next_line(&next_last_char); | ||
817 | linenum++; | ||
818 | restart: | ||
819 | /* for every line, go through all the commands */ | ||
820 | for (sed_cmd = bbg.sed_cmd_head.next; sed_cmd; sed_cmd = sed_cmd->next) { | ||
821 | int old_matched, matched; | ||
822 | |||
823 | old_matched = sed_cmd->in_match; | ||
824 | |||
825 | /* Determine if this command matches this line: */ | ||
826 | |||
827 | /* Are we continuing a previous multi-line match? */ | ||
828 | sed_cmd->in_match = sed_cmd->in_match | ||
829 | /* Or is no range necessary? */ | ||
830 | || (!sed_cmd->beg_line && !sed_cmd->end_line | ||
831 | && !sed_cmd->beg_match && !sed_cmd->end_match) | ||
832 | /* Or did we match the start of a numerical range? */ | ||
833 | || (sed_cmd->beg_line > 0 && (sed_cmd->beg_line == linenum)) | ||
834 | /* Or does this line match our begin address regex? */ | ||
835 | || (sed_cmd->beg_match && | ||
836 | !regexec(sed_cmd->beg_match, pattern_space, 0, NULL, 0)) | ||
837 | /* Or did we match last line of input? */ | ||
838 | || (sed_cmd->beg_line == -1 && next_line == NULL); | ||
839 | |||
840 | /* Snapshot the value */ | ||
841 | |||
842 | matched = sed_cmd->in_match; | ||
843 | |||
844 | /* Is this line the end of the current match? */ | ||
845 | |||
846 | if (matched) { | ||
847 | sed_cmd->in_match = !( | ||
848 | /* has the ending line come, or is this a single address command? */ | ||
849 | (sed_cmd->end_line ? | ||
850 | sed_cmd->end_line == -1 ? | ||
851 | !next_line | ||
852 | : (sed_cmd->end_line <= linenum) | ||
853 | : !sed_cmd->end_match | ||
854 | ) | ||
855 | /* or does this line matches our last address regex */ | ||
856 | || (sed_cmd->end_match && old_matched | ||
857 | && (regexec(sed_cmd->end_match, | ||
858 | pattern_space, 0, NULL, 0) == 0)) | ||
859 | ); | ||
860 | } | ||
876 | 861 | ||
877 | /* Print line number */ | 862 | /* Skip blocks of commands we didn't match. */ |
878 | case '=': | 863 | if (sed_cmd->cmd == '{') { |
879 | fprintf(bbg.nonstdout, "%d\n", linenum); | 864 | if (sed_cmd->invert ? matched : !matched) |
880 | break; | 865 | while (sed_cmd && sed_cmd->cmd != '}') |
866 | sed_cmd = sed_cmd->next; | ||
867 | if (!sed_cmd) bb_error_msg_and_die("unterminated {"); | ||
868 | continue; | ||
869 | } | ||
881 | 870 | ||
882 | /* Write the current pattern space up to the first newline */ | 871 | /* Okay, so did this line match? */ |
883 | case 'P': | 872 | if (sed_cmd->invert ? !matched : matched) { |
884 | { | 873 | /* Update last used regex in case a blank substitute BRE is found */ |
885 | char *tmp = strchr(pattern_space, '\n'); | 874 | if (sed_cmd->beg_match) { |
875 | bbg.previous_regex_ptr = sed_cmd->beg_match; | ||
876 | } | ||
886 | 877 | ||
887 | if (tmp) { | 878 | /* actual sedding */ |
888 | *tmp = '\0'; | 879 | switch (sed_cmd->cmd) { |
889 | sed_puts(pattern_space,1); | ||
890 | *tmp = '\n'; | ||
891 | break; | ||
892 | } | ||
893 | /* Fall Through */ | ||
894 | } | ||
895 | 880 | ||
896 | /* Write the current pattern space to output */ | 881 | /* Print line number */ |
897 | case 'p': | 882 | case '=': |
898 | sed_puts(pattern_space, last_char); | 883 | fprintf(bbg.nonstdout, "%d\n", linenum); |
884 | break; | ||
885 | |||
886 | /* Write the current pattern space up to the first newline */ | ||
887 | case 'P': | ||
888 | { | ||
889 | char *tmp = strchr(pattern_space, '\n'); | ||
890 | |||
891 | if (tmp) { | ||
892 | *tmp = '\0'; | ||
893 | sed_puts(pattern_space, 1); | ||
894 | *tmp = '\n'; | ||
899 | break; | 895 | break; |
900 | /* Delete up through first newline */ | ||
901 | case 'D': | ||
902 | { | ||
903 | char *tmp = strchr(pattern_space,'\n'); | ||
904 | |||
905 | if (tmp) { | ||
906 | tmp = xstrdup(tmp+1); | ||
907 | free(pattern_space); | ||
908 | pattern_space = tmp; | ||
909 | goto restart; | ||
910 | } | ||
911 | } | 896 | } |
912 | /* discard this line. */ | 897 | /* Fall Through */ |
913 | case 'd': | 898 | } |
914 | goto discard_line; | ||
915 | 899 | ||
916 | /* Substitute with regex */ | 900 | /* Write the current pattern space to output */ |
917 | case 's': | 901 | case 'p': |
918 | if (!do_subst_command(sed_cmd, &pattern_space)) | 902 | sed_puts(pattern_space, last_char); |
919 | break; | 903 | break; |
920 | substituted |= 1; | 904 | /* Delete up through first newline */ |
921 | 905 | case 'D': | |
922 | /* handle p option */ | 906 | { |
923 | if (sed_cmd->sub_p) | 907 | char *tmp = strchr(pattern_space, '\n'); |
924 | sed_puts(pattern_space, last_char); | ||
925 | /* handle w option */ | ||
926 | if (sed_cmd->file) | ||
927 | sed_cmd->last_char = puts_maybe_newline( | ||
928 | pattern_space, sed_cmd->file, | ||
929 | sed_cmd->last_char, last_char); | ||
930 | break; | ||
931 | 908 | ||
932 | /* Append line to linked list to be printed later */ | 909 | if (tmp) { |
933 | case 'a': | 910 | tmp = xstrdup(tmp+1); |
934 | append(sed_cmd->string); | 911 | free(pattern_space); |
935 | break; | 912 | pattern_space = tmp; |
913 | goto restart; | ||
914 | } | ||
915 | } | ||
916 | /* discard this line. */ | ||
917 | case 'd': | ||
918 | goto discard_line; | ||
936 | 919 | ||
937 | /* Insert text before this line */ | 920 | /* Substitute with regex */ |
938 | case 'i': | 921 | case 's': |
939 | sed_puts(sed_cmd->string,1); | 922 | if (!do_subst_command(sed_cmd, &pattern_space)) |
940 | break; | 923 | break; |
924 | substituted |= 1; | ||
941 | 925 | ||
942 | /* Cut and paste text (replace) */ | 926 | /* handle p option */ |
943 | case 'c': | 927 | if (sed_cmd->sub_p) |
944 | /* Only triggers on last line of a matching range. */ | 928 | sed_puts(pattern_space, last_char); |
945 | if (!sed_cmd->in_match) | 929 | /* handle w option */ |
946 | sed_puts(sed_cmd->string,0); | 930 | if (sed_cmd->file) |
947 | goto discard_line; | 931 | sed_cmd->last_char = puts_maybe_newline( |
948 | 932 | pattern_space, sed_cmd->file, | |
949 | /* Read file, append contents to output */ | 933 | sed_cmd->last_char, last_char); |
950 | case 'r': | 934 | break; |
951 | { | ||
952 | FILE *rfile; | ||
953 | 935 | ||
954 | rfile = fopen(sed_cmd->string, "r"); | 936 | /* Append line to linked list to be printed later */ |
955 | if (rfile) { | 937 | case 'a': |
956 | char *line; | 938 | append(sed_cmd->string); |
939 | break; | ||
957 | 940 | ||
958 | while ((line = xmalloc_getline(rfile)) | 941 | /* Insert text before this line */ |
959 | != NULL) | 942 | case 'i': |
960 | append(line); | 943 | sed_puts(sed_cmd->string, 1); |
961 | xprint_and_close_file(rfile); | 944 | break; |
962 | } | ||
963 | 945 | ||
964 | break; | 946 | /* Cut and paste text (replace) */ |
947 | case 'c': | ||
948 | /* Only triggers on last line of a matching range. */ | ||
949 | if (!sed_cmd->in_match) | ||
950 | sed_puts(sed_cmd->string, 0); | ||
951 | goto discard_line; | ||
952 | |||
953 | /* Read file, append contents to output */ | ||
954 | case 'r': | ||
955 | { | ||
956 | FILE *rfile; | ||
957 | |||
958 | rfile = fopen(sed_cmd->string, "r"); | ||
959 | if (rfile) { | ||
960 | char *line; | ||
961 | |||
962 | while ((line = xmalloc_getline(rfile)) | ||
963 | != NULL) | ||
964 | append(line); | ||
965 | xprint_and_close_file(rfile); | ||
965 | } | 966 | } |
966 | 967 | ||
967 | /* Write pattern space to file. */ | 968 | break; |
968 | case 'w': | 969 | } |
969 | sed_cmd->last_char = puts_maybe_newline( | ||
970 | pattern_space,sed_cmd->file, | ||
971 | sed_cmd->last_char, last_char); | ||
972 | break; | ||
973 | 970 | ||
974 | /* Read next line from input */ | 971 | /* Write pattern space to file. */ |
975 | case 'n': | 972 | case 'w': |
976 | if (!bbg.be_quiet) | 973 | sed_cmd->last_char = puts_maybe_newline( |
977 | sed_puts(pattern_space, last_char); | 974 | pattern_space, sed_cmd->file, |
978 | if (next_line) { | 975 | sed_cmd->last_char, last_char); |
979 | free(pattern_space); | 976 | break; |
980 | pattern_space = next_line; | ||
981 | last_char = next_last_char; | ||
982 | next_line = get_next_line(&next_last_char); | ||
983 | linenum++; | ||
984 | break; | ||
985 | } | ||
986 | /* fall through */ | ||
987 | 977 | ||
988 | /* Quit. End of script, end of input. */ | 978 | /* Read next line from input */ |
989 | case 'q': | 979 | case 'n': |
990 | /* Exit the outer while loop */ | 980 | if (!bbg.be_quiet) |
981 | sed_puts(pattern_space, last_char); | ||
982 | if (next_line) { | ||
983 | free(pattern_space); | ||
984 | pattern_space = next_line; | ||
985 | last_char = next_last_char; | ||
986 | next_line = get_next_line(&next_last_char); | ||
987 | linenum++; | ||
988 | break; | ||
989 | } | ||
990 | /* fall through */ | ||
991 | |||
992 | /* Quit. End of script, end of input. */ | ||
993 | case 'q': | ||
994 | /* Exit the outer while loop */ | ||
995 | free(next_line); | ||
996 | next_line = NULL; | ||
997 | goto discard_commands; | ||
998 | |||
999 | /* Append the next line to the current line */ | ||
1000 | case 'N': | ||
1001 | { | ||
1002 | int len; | ||
1003 | /* If no next line, jump to end of script and exit. */ | ||
1004 | if (next_line == NULL) { | ||
1005 | /* Jump to end of script and exit */ | ||
991 | free(next_line); | 1006 | free(next_line); |
992 | next_line = NULL; | 1007 | next_line = NULL; |
993 | goto discard_commands; | 1008 | goto discard_line; |
994 | 1009 | /* append next_line, read new next_line. */ | |
995 | /* Append the next line to the current line */ | ||
996 | case 'N': | ||
997 | { | ||
998 | /* If no next line, jump to end of script and exit. */ | ||
999 | if (next_line == NULL) { | ||
1000 | /* Jump to end of script and exit */ | ||
1001 | free(next_line); | ||
1002 | next_line = NULL; | ||
1003 | goto discard_line; | ||
1004 | /* append next_line, read new next_line. */ | ||
1005 | } else { | ||
1006 | int len = strlen(pattern_space); | ||
1007 | |||
1008 | pattern_space = realloc(pattern_space, len + strlen(next_line) + 2); | ||
1009 | pattern_space[len] = '\n'; | ||
1010 | strcpy(pattern_space + len+1, next_line); | ||
1011 | last_char = next_last_char; | ||
1012 | next_line = get_next_line(&next_last_char); | ||
1013 | linenum++; | ||
1014 | } | ||
1015 | break; | ||
1016 | } | 1010 | } |
1011 | len = strlen(pattern_space); | ||
1012 | pattern_space = realloc(pattern_space, len + strlen(next_line) + 2); | ||
1013 | pattern_space[len] = '\n'; | ||
1014 | strcpy(pattern_space + len+1, next_line); | ||
1015 | last_char = next_last_char; | ||
1016 | next_line = get_next_line(&next_last_char); | ||
1017 | linenum++; | ||
1018 | break; | ||
1019 | } | ||
1017 | 1020 | ||
1018 | /* Test/branch if substitution occurred */ | 1021 | /* Test/branch if substitution occurred */ |
1019 | case 't': | 1022 | case 't': |
1020 | if (!substituted) break; | 1023 | if (!substituted) break; |
1021 | substituted = 0; | 1024 | substituted = 0; |
1022 | /* Fall through */ | 1025 | /* Fall through */ |
1023 | /* Test/branch if substitution didn't occur */ | 1026 | /* Test/branch if substitution didn't occur */ |
1024 | case 'T': | 1027 | case 'T': |
1025 | if (substituted) break; | 1028 | if (substituted) break; |
1026 | /* Fall through */ | 1029 | /* Fall through */ |
1027 | /* Branch to label */ | 1030 | /* Branch to label */ |
1028 | case 'b': | 1031 | case 'b': |
1029 | if (!sed_cmd->string) goto discard_commands; | 1032 | if (!sed_cmd->string) goto discard_commands; |
1030 | else sed_cmd = branch_to(sed_cmd->string); | 1033 | else sed_cmd = branch_to(sed_cmd->string); |
1031 | break; | 1034 | break; |
1032 | /* Transliterate characters */ | 1035 | /* Transliterate characters */ |
1033 | case 'y': | 1036 | case 'y': |
1034 | { | 1037 | { |
1035 | int i; | 1038 | int i, j; |
1036 | 1039 | ||
1037 | for (i = 0; pattern_space[i]; i++) { | 1040 | for (i = 0; pattern_space[i]; i++) { |
1038 | int j; | 1041 | for (j = 0; sed_cmd->string[j]; j += 2) { |
1039 | 1042 | if (pattern_space[i] == sed_cmd->string[j]) { | |
1040 | for (j = 0; sed_cmd->string[j]; j += 2) { | 1043 | pattern_space[i] = sed_cmd->string[j + 1]; |
1041 | if (pattern_space[i] == sed_cmd->string[j]) { | 1044 | break; |
1042 | pattern_space[i] = sed_cmd->string[j + 1]; | ||
1043 | break; | ||
1044 | } | ||
1045 | } | 1045 | } |
1046 | } | 1046 | } |
1047 | |||
1048 | break; | ||
1049 | } | 1047 | } |
1050 | case 'g': /* Replace pattern space with hold space */ | ||
1051 | free(pattern_space); | ||
1052 | pattern_space = xstrdup(bbg.hold_space ? bbg.hold_space : ""); | ||
1053 | break; | ||
1054 | case 'G': /* Append newline and hold space to pattern space */ | ||
1055 | { | ||
1056 | int pattern_space_size = 2; | ||
1057 | int hold_space_size = 0; | ||
1058 | |||
1059 | if (pattern_space) | ||
1060 | pattern_space_size += strlen(pattern_space); | ||
1061 | if (bbg.hold_space) | ||
1062 | hold_space_size = strlen(bbg.hold_space); | ||
1063 | pattern_space = xrealloc(pattern_space, | ||
1064 | pattern_space_size + hold_space_size); | ||
1065 | if (pattern_space_size == 2) | ||
1066 | pattern_space[0] = 0; | ||
1067 | strcat(pattern_space, "\n"); | ||
1068 | if (bbg.hold_space) | ||
1069 | strcat(pattern_space, bbg.hold_space); | ||
1070 | last_char = '\n'; | ||
1071 | 1048 | ||
1072 | break; | 1049 | break; |
1073 | } | 1050 | } |
1074 | case 'h': /* Replace hold space with pattern space */ | 1051 | case 'g': /* Replace pattern space with hold space */ |
1075 | free(bbg.hold_space); | 1052 | free(pattern_space); |
1076 | bbg.hold_space = xstrdup(pattern_space); | 1053 | pattern_space = xstrdup(bbg.hold_space ? bbg.hold_space : ""); |
1077 | break; | 1054 | break; |
1078 | case 'H': /* Append newline and pattern space to hold space */ | 1055 | case 'G': /* Append newline and hold space to pattern space */ |
1079 | { | 1056 | { |
1080 | int hold_space_size = 2; | 1057 | int pattern_space_size = 2; |
1081 | int pattern_space_size = 0; | 1058 | int hold_space_size = 0; |
1082 | 1059 | ||
1083 | if (bbg.hold_space) | 1060 | if (pattern_space) |
1084 | hold_space_size += strlen(bbg.hold_space); | 1061 | pattern_space_size += strlen(pattern_space); |
1085 | if (pattern_space) | 1062 | if (bbg.hold_space) |
1086 | pattern_space_size = strlen(pattern_space); | 1063 | hold_space_size = strlen(bbg.hold_space); |
1087 | bbg.hold_space = xrealloc(bbg.hold_space, | 1064 | pattern_space = xrealloc(pattern_space, |
1088 | hold_space_size + pattern_space_size); | 1065 | pattern_space_size + hold_space_size); |
1089 | 1066 | if (pattern_space_size == 2) | |
1090 | if (hold_space_size == 2) | 1067 | pattern_space[0] = 0; |
1091 | *bbg.hold_space = 0; | 1068 | strcat(pattern_space, "\n"); |
1092 | strcat(bbg.hold_space, "\n"); | 1069 | if (bbg.hold_space) |
1093 | if (pattern_space) | 1070 | strcat(pattern_space, bbg.hold_space); |
1094 | strcat(bbg.hold_space, pattern_space); | 1071 | last_char = '\n'; |
1095 | 1072 | ||
1096 | break; | 1073 | break; |
1097 | } | 1074 | } |
1098 | case 'x': /* Exchange hold and pattern space */ | 1075 | case 'h': /* Replace hold space with pattern space */ |
1099 | { | 1076 | free(bbg.hold_space); |
1100 | char *tmp = pattern_space; | 1077 | bbg.hold_space = xstrdup(pattern_space); |
1101 | pattern_space = bbg.hold_space ? : xzalloc(1); | 1078 | break; |
1102 | last_char = '\n'; | 1079 | case 'H': /* Append newline and pattern space to hold space */ |
1103 | bbg.hold_space = tmp; | 1080 | { |
1104 | break; | 1081 | int hold_space_size = 2; |
1105 | } | 1082 | int pattern_space_size = 0; |
1106 | } | 1083 | |
1084 | if (bbg.hold_space) | ||
1085 | hold_space_size += strlen(bbg.hold_space); | ||
1086 | if (pattern_space) | ||
1087 | pattern_space_size = strlen(pattern_space); | ||
1088 | bbg.hold_space = xrealloc(bbg.hold_space, | ||
1089 | hold_space_size + pattern_space_size); | ||
1090 | |||
1091 | if (hold_space_size == 2) | ||
1092 | *bbg.hold_space = 0; | ||
1093 | strcat(bbg.hold_space, "\n"); | ||
1094 | if (pattern_space) | ||
1095 | strcat(bbg.hold_space, pattern_space); | ||
1096 | |||
1097 | break; | ||
1098 | } | ||
1099 | case 'x': /* Exchange hold and pattern space */ | ||
1100 | { | ||
1101 | char *tmp = pattern_space; | ||
1102 | pattern_space = bbg.hold_space ? : xzalloc(1); | ||
1103 | last_char = '\n'; | ||
1104 | bbg.hold_space = tmp; | ||
1105 | break; | ||
1106 | } | ||
1107 | } | 1107 | } |
1108 | } | 1108 | } |
1109 | } | ||
1109 | 1110 | ||
1110 | /* | 1111 | /* |
1111 | * exit point from sedding... | 1112 | * exit point from sedding... |
1112 | */ | 1113 | */ |
1113 | discard_commands: | 1114 | discard_commands: |
1114 | /* we will print the line unless we were told to be quiet ('-n') | 1115 | /* we will print the line unless we were told to be quiet ('-n') |
1115 | or if the line was suppressed (ala 'd'elete) */ | 1116 | or if the line was suppressed (ala 'd'elete) */ |
1116 | if (!bbg.be_quiet) sed_puts(pattern_space, last_char); | 1117 | if (!bbg.be_quiet) sed_puts(pattern_space, last_char); |
1117 | 1118 | ||
1118 | /* Delete and such jump here. */ | 1119 | /* Delete and such jump here. */ |
1119 | discard_line: | 1120 | discard_line: |
1120 | flush_append(); | 1121 | flush_append(); |
1121 | free(pattern_space); | 1122 | free(pattern_space); |
1122 | } | 1123 | |
1124 | goto again; | ||
1123 | } | 1125 | } |
1124 | 1126 | ||
1125 | /* It is possible to have a command line argument with embedded | 1127 | /* It is possible to have a command line argument with embedded |
@@ -1131,7 +1133,7 @@ static void add_cmd_block(char *cmdstr) | |||
1131 | char *temp = xstrdup(cmdstr), *temp2 = temp; | 1133 | char *temp = xstrdup(cmdstr), *temp2 = temp; |
1132 | 1134 | ||
1133 | while (go) { | 1135 | while (go) { |
1134 | int len = strcspn(temp2,"\n"); | 1136 | int len = strcspn(temp2, "\n"); |
1135 | if (!temp2[len]) go = 0; | 1137 | if (!temp2[len]) go = 0; |
1136 | else temp2[len] = 0; | 1138 | else temp2[len] = 0; |
1137 | add_cmd(temp2); | 1139 | add_cmd(temp2); |
@@ -1165,31 +1167,37 @@ static void add_files_link(llist_t *opt_f) | |||
1165 | 1167 | ||
1166 | int sed_main(int argc, char **argv) | 1168 | int sed_main(int argc, char **argv) |
1167 | { | 1169 | { |
1170 | enum { | ||
1171 | OPT_in_place = 1 << 0, | ||
1172 | }; | ||
1168 | unsigned opt; | 1173 | unsigned opt; |
1169 | llist_t *opt_e, *opt_f; | 1174 | llist_t *opt_e, *opt_f; |
1170 | int status = EXIT_SUCCESS; | 1175 | int status = EXIT_SUCCESS; |
1171 | 1176 | ||
1172 | bbg.sed_cmd_tail=&bbg.sed_cmd_head; | 1177 | bbg.sed_cmd_tail = &bbg.sed_cmd_head; |
1173 | 1178 | ||
1174 | /* destroy command strings on exit */ | 1179 | /* destroy command strings on exit */ |
1175 | if (ENABLE_FEATURE_CLEAN_UP) atexit(sed_free_and_close_stuff); | 1180 | if (ENABLE_FEATURE_CLEAN_UP) atexit(sed_free_and_close_stuff); |
1176 | 1181 | ||
1177 | /* Lie to autoconf when it starts asking stupid questions. */ | 1182 | /* Lie to autoconf when it starts asking stupid questions. */ |
1178 | if (argc==2 && !strcmp(argv[1],"--version")) { | 1183 | if (argc == 2 && !strcmp(argv[1], "--version")) { |
1179 | printf("This is not GNU sed version 4.0\n"); | 1184 | puts("This is not GNU sed version 4.0"); |
1180 | exit(0); | 1185 | return 0; |
1181 | } | 1186 | } |
1182 | 1187 | ||
1183 | /* do normal option parsing */ | 1188 | /* do normal option parsing */ |
1184 | opt_e = opt_f = NULL; | 1189 | opt_e = opt_f = NULL; |
1185 | opt_complementary = "e::f::"; /* can occur multiple times */ | 1190 | opt_complementary = "e::f::" /* can occur multiple times */ |
1186 | opt = getopt32(argc, argv, "irne:f:", &opt_e, &opt_f); | 1191 | "nn"; /* count -n */ |
1187 | if (opt & 0x1) { // -i | 1192 | opt = getopt32(argc, argv, "irne:f:", &opt_e, &opt_f, |
1188 | bbg.in_place++; | 1193 | &bbg.be_quiet); /* counter for -n */ |
1194 | argc -= optind; | ||
1195 | argv += optind; | ||
1196 | if (opt & OPT_in_place) { // -i | ||
1189 | atexit(cleanup_outname); | 1197 | atexit(cleanup_outname); |
1190 | } | 1198 | } |
1191 | if (opt & 0x2) bbg.regex_type|=REG_EXTENDED; // -r | 1199 | if (opt & 0x2) bbg.regex_type |= REG_EXTENDED; // -r |
1192 | if (opt & 0x4) bbg.be_quiet++; // -n | 1200 | //if (opt & 0x4) bbg.be_quiet++; // -n |
1193 | if (opt & 0x8) { // -e | 1201 | if (opt & 0x8) { // -e |
1194 | /* getopt32 reverses order of arguments, handle it */ | 1202 | /* getopt32 reverses order of arguments, handle it */ |
1195 | add_cmds_link(opt_e); | 1203 | add_cmds_link(opt_e); |
@@ -1198,12 +1206,12 @@ int sed_main(int argc, char **argv) | |||
1198 | /* getopt32 reverses order of arguments, handle it */ | 1206 | /* getopt32 reverses order of arguments, handle it */ |
1199 | add_files_link(opt_f); | 1207 | add_files_link(opt_f); |
1200 | } | 1208 | } |
1201 | /* if we didn't get a pattern from -e or -f, use argv[optind] */ | 1209 | /* if we didn't get a pattern from -e or -f, use argv[0] */ |
1202 | if (!(opt & 0x18)) { | 1210 | if (!(opt & 0x18)) { |
1203 | if (argv[optind] == NULL) | 1211 | if (!argc) |
1204 | bb_show_usage(); | 1212 | bb_show_usage(); |
1205 | else | 1213 | add_cmd_block(*argv++); |
1206 | add_cmd_block(argv[optind++]); | 1214 | argc--; |
1207 | } | 1215 | } |
1208 | /* Flush any unfinished commands. */ | 1216 | /* Flush any unfinished commands. */ |
1209 | add_cmd(""); | 1217 | add_cmd(""); |
@@ -1211,11 +1219,11 @@ int sed_main(int argc, char **argv) | |||
1211 | /* By default, we write to stdout */ | 1219 | /* By default, we write to stdout */ |
1212 | bbg.nonstdout = stdout; | 1220 | bbg.nonstdout = stdout; |
1213 | 1221 | ||
1214 | /* argv[(optind)..(argc-1)] should be names of file to process. If no | 1222 | /* argv[0..(argc-1)] should be names of file to process. If no |
1215 | * files were specified or '-' was specified, take input from stdin. | 1223 | * files were specified or '-' was specified, take input from stdin. |
1216 | * Otherwise, we process all the files specified. */ | 1224 | * Otherwise, we process all the files specified. */ |
1217 | if (argv[optind] == NULL) { | 1225 | if (argv[0] == NULL) { |
1218 | if (bbg.in_place) | 1226 | if (opt & OPT_in_place) |
1219 | bb_error_msg_and_die(bb_msg_requires_arg, "-i"); | 1227 | bb_error_msg_and_die(bb_msg_requires_arg, "-i"); |
1220 | add_input_file(stdin); | 1228 | add_input_file(stdin); |
1221 | process_files(); | 1229 | process_files(); |
@@ -1223,11 +1231,13 @@ int sed_main(int argc, char **argv) | |||
1223 | int i; | 1231 | int i; |
1224 | FILE *file; | 1232 | FILE *file; |
1225 | 1233 | ||
1226 | for (i = optind; i < argc; i++) { | 1234 | for (i = 0; i < argc; i++) { |
1227 | struct stat statbuf; | 1235 | struct stat statbuf; |
1228 | int nonstdoutfd; | 1236 | int nonstdoutfd; |
1229 | 1237 | ||
1230 | if (!strcmp(argv[i], "-") && !bbg.in_place) { | 1238 | if (argv[i][0] == '-' && !argv[i][1] |
1239 | && !(opt & OPT_in_place) | ||
1240 | ) { | ||
1231 | add_input_file(stdin); | 1241 | add_input_file(stdin); |
1232 | process_files(); | 1242 | process_files(); |
1233 | continue; | 1243 | continue; |
@@ -1237,7 +1247,7 @@ int sed_main(int argc, char **argv) | |||
1237 | status = EXIT_FAILURE; | 1247 | status = EXIT_FAILURE; |
1238 | continue; | 1248 | continue; |
1239 | } | 1249 | } |
1240 | if (!bbg.in_place) { | 1250 | if (!(opt & OPT_in_place)) { |
1241 | add_input_file(file); | 1251 | add_input_file(file); |
1242 | continue; | 1252 | continue; |
1243 | } | 1253 | } |
@@ -1246,12 +1256,12 @@ int sed_main(int argc, char **argv) | |||
1246 | nonstdoutfd = mkstemp(bbg.outname); | 1256 | nonstdoutfd = mkstemp(bbg.outname); |
1247 | if (-1 == nonstdoutfd) | 1257 | if (-1 == nonstdoutfd) |
1248 | bb_error_msg_and_die("no temp file"); | 1258 | bb_error_msg_and_die("no temp file"); |
1249 | bbg.nonstdout = fdopen(nonstdoutfd,"w"); | 1259 | bbg.nonstdout = fdopen(nonstdoutfd, "w"); |
1250 | 1260 | ||
1251 | /* Set permissions of output file */ | 1261 | /* Set permissions of output file */ |
1252 | 1262 | ||
1253 | fstat(fileno(file),&statbuf); | 1263 | fstat(fileno(file), &statbuf); |
1254 | fchmod(nonstdoutfd,statbuf.st_mode); | 1264 | fchmod(nonstdoutfd, statbuf.st_mode); |
1255 | add_input_file(file); | 1265 | add_input_file(file); |
1256 | process_files(); | 1266 | process_files(); |
1257 | fclose(bbg.nonstdout); | 1267 | fclose(bbg.nonstdout); |
@@ -1259,7 +1269,7 @@ int sed_main(int argc, char **argv) | |||
1259 | bbg.nonstdout = stdout; | 1269 | bbg.nonstdout = stdout; |
1260 | /* unlink(argv[i]); */ | 1270 | /* unlink(argv[i]); */ |
1261 | // FIXME: error check / message? | 1271 | // FIXME: error check / message? |
1262 | rename(bbg.outname,argv[i]); | 1272 | rename(bbg.outname, argv[i]); |
1263 | free(bbg.outname); | 1273 | free(bbg.outname); |
1264 | bbg.outname = 0; | 1274 | bbg.outname = 0; |
1265 | } | 1275 | } |