diff options
author | vda <vda@69ca8d6d-28ef-0310-b511-8ec308f3f277> | 2007-01-29 17:10:19 +0000 |
---|---|---|
committer | vda <vda@69ca8d6d-28ef-0310-b511-8ec308f3f277> | 2007-01-29 17:10:19 +0000 |
commit | f8c312083a59153e627f3795581663bc1afe03fa (patch) | |
tree | 3ecbd8b554f6a4c82f9b03d29087914f3d8a9623 | |
parent | 531a4b43c3f7e390833d17a713fd4f8bd80109db (diff) | |
download | busybox-w32-f8c312083a59153e627f3795581663bc1afe03fa.tar.gz busybox-w32-f8c312083a59153e627f3795581663bc1afe03fa.tar.bz2 busybox-w32-f8c312083a59153e627f3795581663bc1afe03fa.zip |
add to testsuite and fix yet another sed corner case
git-svn-id: svn://busybox.net/trunk/busybox@17639 69ca8d6d-28ef-0310-b511-8ec308f3f277
-rw-r--r-- | editors/sed.c | 30 | ||||
-rwxr-xr-x | testsuite/sed.tests | 3 |
2 files changed, 27 insertions, 6 deletions
diff --git a/editors/sed.c b/editors/sed.c index bf40877e4..695e5e974 100644 --- a/editors/sed.c +++ b/editors/sed.c | |||
@@ -724,6 +724,7 @@ static void add_input_file(FILE *file) | |||
724 | */ | 724 | */ |
725 | enum { | 725 | enum { |
726 | NO_EOL_CHAR = 1, | 726 | NO_EOL_CHAR = 1, |
727 | LAST_IS_NUL = 2, | ||
727 | }; | 728 | }; |
728 | static char *get_next_line(char *gets_char) | 729 | static char *get_next_line(char *gets_char) |
729 | { | 730 | { |
@@ -737,17 +738,24 @@ static char *get_next_line(char *gets_char) | |||
737 | * doesn't end with either '\n' or '\0' */ | 738 | * doesn't end with either '\n' or '\0' */ |
738 | gc = NO_EOL_CHAR; | 739 | gc = NO_EOL_CHAR; |
739 | while (bbg.current_input_file < bbg.input_file_count) { | 740 | while (bbg.current_input_file < bbg.input_file_count) { |
741 | FILE *fp = bbg.input_file_list[bbg.current_input_file]; | ||
740 | /* Read line up to a newline or NUL byte, inclusive, | 742 | /* Read line up to a newline or NUL byte, inclusive, |
741 | * return malloc'ed char[]. length of the chunk read | 743 | * return malloc'ed char[]. length of the chunk read |
742 | * is stored in len. NULL if EOF/error */ | 744 | * is stored in len. NULL if EOF/error */ |
743 | temp = bb_get_chunk_from_file( | 745 | temp = bb_get_chunk_from_file(fp, &len); |
744 | bbg.input_file_list[bbg.current_input_file], &len); | ||
745 | if (temp) { | 746 | if (temp) { |
746 | /* len > 0 here, it's ok to do temp[len-1] */ | 747 | /* len > 0 here, it's ok to do temp[len-1] */ |
747 | char c = temp[len-1]; | 748 | char c = temp[len-1]; |
748 | if (c == '\n' || c == '\0') { | 749 | if (c == '\n' || c == '\0') { |
749 | temp[len-1] = '\0'; | 750 | temp[len-1] = '\0'; |
750 | gc = c; | 751 | gc = c; |
752 | if (c == '\0') { | ||
753 | int ch = fgetc(fp); | ||
754 | if (ch != EOF) | ||
755 | ungetc(ch, fp); | ||
756 | else | ||
757 | gc = LAST_IS_NUL; | ||
758 | } | ||
751 | } | 759 | } |
752 | /* else we put NO_EOL_CHAR into *gets_char */ | 760 | /* else we put NO_EOL_CHAR into *gets_char */ |
753 | break; | 761 | break; |
@@ -761,7 +769,8 @@ static char *get_next_line(char *gets_char) | |||
761 | * (note: *no* newline after "b bang"!) */ | 769 | * (note: *no* newline after "b bang"!) */ |
762 | } | 770 | } |
763 | /* Close this file and advance to next one */ | 771 | /* Close this file and advance to next one */ |
764 | fclose(bbg.input_file_list[bbg.current_input_file++]); | 772 | fclose(fp); |
773 | bbg.current_input_file++; | ||
765 | } | 774 | } |
766 | *gets_char = gc; | 775 | *gets_char = gc; |
767 | return temp; | 776 | return temp; |
@@ -785,20 +794,29 @@ static void puts_maybe_newline(char *s, FILE *file, char *last_puts_char, char l | |||
785 | { | 794 | { |
786 | char lpc = *last_puts_char; | 795 | char lpc = *last_puts_char; |
787 | 796 | ||
788 | /* Is this a first line from new file | 797 | /* Need to insert a '\n' between two files because first file's |
789 | * and old file didn't end with '\n' or '\0'? */ | 798 | * last line wasn't terminated? */ |
790 | if (lpc != '\n' && lpc != '\0') { | 799 | if (lpc != '\n' && lpc != '\0') { |
791 | fputc('\n', file); | 800 | fputc('\n', file); |
792 | lpc = '\n'; | 801 | lpc = '\n'; |
793 | } | 802 | } |
794 | fputs(s, file); | 803 | fputs(s, file); |
804 | |||
795 | /* 'x' - just something which is not '\n', '\0' or NO_EOL_CHAR */ | 805 | /* 'x' - just something which is not '\n', '\0' or NO_EOL_CHAR */ |
796 | if (s[0]) | 806 | if (s[0]) |
797 | lpc = 'x'; | 807 | lpc = 'x'; |
798 | if (last_gets_char != NO_EOL_CHAR) { /* had trailing '\n' or '\0'? */ | 808 | |
809 | /* had trailing '\0' and it was last char of file? */ | ||
810 | if (last_gets_char == LAST_IS_NUL) { | ||
811 | fputc('\0', file); | ||
812 | lpc = 'x'; /* */ | ||
813 | } else | ||
814 | /* had trailing '\n' or '\0'? */ | ||
815 | if (last_gets_char != NO_EOL_CHAR) { | ||
799 | fputc(last_gets_char, file); | 816 | fputc(last_gets_char, file); |
800 | lpc = last_gets_char; | 817 | lpc = last_gets_char; |
801 | } | 818 | } |
819 | |||
802 | if (ferror(file)) { | 820 | if (ferror(file)) { |
803 | xfunc_error_retval = 4; /* It's what gnu sed exits with... */ | 821 | xfunc_error_retval = 4; /* It's what gnu sed exits with... */ |
804 | bb_error_msg_and_die(bb_msg_write_error); | 822 | bb_error_msg_and_die(bb_msg_write_error); |
diff --git a/testsuite/sed.tests b/testsuite/sed.tests index cc200703d..9576b6c4b 100755 --- a/testsuite/sed.tests +++ b/testsuite/sed.tests | |||
@@ -143,6 +143,9 @@ testing "sed subst+write" \ | |||
143 | "sed -e 's/i/z/' -e 'woutputw' input -; echo -n X; cat outputw" \ | 143 | "sed -e 's/i/z/' -e 'woutputw' input -; echo -n X; cat outputw" \ |
144 | "thzngy\nagaznXthzngy\nagazn" "thingy" "again" | 144 | "thzngy\nagaznXthzngy\nagazn" "thingy" "again" |
145 | rm outputw | 145 | rm outputw |
146 | testing "sed trailing NUL" \ | ||
147 | "sed 's/i/z/' input -" \ | ||
148 | "a\0b\0\nc" "a\0b\0" "c" | ||
146 | 149 | ||
147 | # Test end-of-file matching behavior | 150 | # Test end-of-file matching behavior |
148 | 151 | ||