aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2006-12-10 02:09:12 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2006-12-10 02:09:12 +0000
commit2f8f71b20dbce1328a5175bb75ae15564f7e9489 (patch)
treeb806ee9d337d89ec3bc4f57eaaed1626560b68c8
parentb15b7f7a4a06733fde996737110524d119b69106 (diff)
downloadbusybox-w32-2f8f71b20dbce1328a5175bb75ae15564f7e9489.tar.gz
busybox-w32-2f8f71b20dbce1328a5175bb75ae15564f7e9489.tar.bz2
busybox-w32-2f8f71b20dbce1328a5175bb75ae15564f7e9489.zip
sed: style fixes
-rw-r--r--editors/sed.c666
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
92static const char *const semicolon_whitespace = "; \n\r\t\v"; 92static const char *const semicolon_whitespace = "; \n\r\t\v";
93 93
94struct sed_globals 94struct 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
124void sed_free_and_close_stuff(void); 123void sed_free_and_close_stuff(void);
125#if ENABLE_FEATURE_CLEAN_UP 124#if ENABLE_FEATURE_CLEAN_UP
126void sed_free_and_close_stuff(void) 125static 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
188static char *copy_parsing_escapes(char *string, int len) 187static 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 (;;) { 804again:
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++;
817restart:
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++;
818restart:
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 */
1113discard_commands: 1114discard_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. */
1119discard_line: 1120discard_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
1166int sed_main(int argc, char **argv) 1168int 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 }