aboutsummaryrefslogtreecommitdiff
path: root/editors/sed.c
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2006-12-02 20:12:12 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2006-12-02 20:12:12 +0000
commit1375bc7b678d143798823c719ebba55dce596585 (patch)
tree35ff0fbbe02e87bd8a638148172d972cb072555a /editors/sed.c
parent8b22b07bc599ca39d1b42cabef98189894b2162f (diff)
downloadbusybox-w32-1375bc7b678d143798823c719ebba55dce596585.tar.gz
busybox-w32-1375bc7b678d143798823c719ebba55dce596585.tar.bz2
busybox-w32-1375bc7b678d143798823c719ebba55dce596585.zip
sed: fix handling of files not ending in '\n'
Diffstat (limited to 'editors/sed.c')
-rw-r--r--editors/sed.c40
1 files changed, 30 insertions, 10 deletions
diff --git a/editors/sed.c b/editors/sed.c
index 630d6d792..94368aa68 100644
--- a/editors/sed.c
+++ b/editors/sed.c
@@ -81,6 +81,7 @@ typedef struct sed_cmd_s {
81 unsigned int invert:1; /* the '!' after the address */ 81 unsigned int invert:1; /* the '!' after the address */
82 unsigned int in_match:1; /* Next line also included in match? */ 82 unsigned int in_match:1; /* Next line also included in match? */
83 unsigned int sub_p:1; /* (s) print option */ 83 unsigned int sub_p:1; /* (s) print option */
84
84 int last_char; /* Last line written by (sw) had no '\n' */ 85 int last_char; /* Last line written by (sw) had no '\n' */
85 86
86 /* GENERAL FIELDS */ 87 /* GENERAL FIELDS */
@@ -715,12 +716,9 @@ static void add_input_file(FILE *file)
715static char *get_next_line(int *last_char) 716static char *get_next_line(int *last_char)
716{ 717{
717 char *temp = NULL; 718 char *temp = NULL;
718 int len; 719 int len, lc;
719
720 /* will be returned if last line in the file
721 * doesn't end with either '\n' or '\0' */
722 *last_char = 0x100;
723 720
721 lc = 0;
724 flush_append(); 722 flush_append();
725 while (bbg.current_input_file < bbg.input_file_count) { 723 while (bbg.current_input_file < bbg.input_file_count) {
726 temp = bb_get_chunk_from_file( 724 temp = bb_get_chunk_from_file(
@@ -730,18 +728,27 @@ static char *get_next_line(int *last_char)
730 char c = temp[len-1]; 728 char c = temp[len-1];
731 if (c == '\n' || c == '\0') { 729 if (c == '\n' || c == '\0') {
732 temp[len-1] = '\0'; 730 temp[len-1] = '\0';
733 *last_char = (unsigned char)c; 731 lc |= (unsigned char)c;
732 break;
734 } 733 }
734 /* will be returned if last line in the file
735 * doesn't end with either '\n' or '\0' */
736 lc |= 0x100;
735 break; 737 break;
736 } 738 }
737 /* Close this file and advance to next one */ 739 /* Close this file and advance to next one */
738 fclose(bbg.input_file_list[bbg.current_input_file++]); 740 fclose(bbg.input_file_list[bbg.current_input_file++]);
741 /* "this is the first line from new input file" */
742 lc |= 0x200;
739 } 743 }
744 *last_char = lc;
740 return temp; 745 return temp;
741} 746}
742 747
743/* Output line of text. */ 748/* Output line of text. */
744/* Note: 749/* Note:
750 * The tricks with 0x200 and last_puts_char are there to emulate gnu sed.
751 * Without them, we had this:
745 * echo -n thingy >z1 752 * echo -n thingy >z1
746 * echo -n again >z2 753 * echo -n again >z2
747 * >znull 754 * >znull
@@ -750,13 +757,26 @@ static char *get_next_line(int *last_char)
750 * 00000000 74 68 7a 6e 67 79 0a 61 67 61 7a 6e |thzngy.agazn| 757 * 00000000 74 68 7a 6e 67 79 0a 61 67 61 7a 6e |thzngy.agazn|
751 * bbox: 758 * bbox:
752 * 00000000 74 68 7a 6e 67 79 61 67 61 7a 6e |thzngyagazn| 759 * 00000000 74 68 7a 6e 67 79 61 67 61 7a 6e |thzngyagazn|
753 * I am not sure that bbox is wrong here...
754 */ 760 */
755 761
756static int puts_maybe_newline(char *s, FILE *file, int prev_last_char, int last_char) 762static int puts_maybe_newline(char *s, FILE *file, int prev_last_char, int last_char)
757{ 763{
764 static char last_puts_char;
765
766 /* Is this a first line from new file
767 * and old file didn't end with '\n'? */
768 if ((last_char & 0x200) && last_puts_char != '\n') {
769 fputc('\n', file);
770 last_puts_char = '\n';
771 }
758 fputs(s, file); 772 fputs(s, file);
759 if (last_char < 0x100) fputc(last_char, file); 773 /* 'x': we don't care what is it, but we know it isn't '\n' */
774 if (s[0]) last_puts_char = 'x';
775 if (!(last_char & 0x100)) { /* had trailing '\n' or '\0'? */
776 last_char &= 0xff;
777 fputc(last_char, file);
778 last_puts_char = last_char;
779 }
760 780
761 if (ferror(file)) { 781 if (ferror(file)) {
762 xfunc_error_retval = 4; /* It's what gnu sed exits with... */ 782 xfunc_error_retval = 4; /* It's what gnu sed exits with... */
@@ -1047,7 +1067,7 @@ restart:
1047 strcat(pattern_space, "\n"); 1067 strcat(pattern_space, "\n");
1048 if (bbg.hold_space) 1068 if (bbg.hold_space)
1049 strcat(pattern_space, bbg.hold_space); 1069 strcat(pattern_space, bbg.hold_space);
1050 last_char = 0x100; 1070 last_char = '\n';
1051 1071
1052 break; 1072 break;
1053 } 1073 }
@@ -1079,7 +1099,7 @@ restart:
1079 { 1099 {
1080 char *tmp = pattern_space; 1100 char *tmp = pattern_space;
1081 pattern_space = bbg.hold_space ? : xzalloc(1); 1101 pattern_space = bbg.hold_space ? : xzalloc(1);
1082 last_char = 0x100; 1102 last_char = '\n';
1083 bbg.hold_space = tmp; 1103 bbg.hold_space = tmp;
1084 break; 1104 break;
1085 } 1105 }