add to testsuite and fix yet another sed corner case

This commit is contained in:
Denis Vlasenko 2007-01-29 17:10:19 +00:00
parent c562bb7487
commit 86811803e3
2 changed files with 27 additions and 6 deletions

View File

@ -724,6 +724,7 @@ static void add_input_file(FILE *file)
*/ */
enum { enum {
NO_EOL_CHAR = 1, NO_EOL_CHAR = 1,
LAST_IS_NUL = 2,
}; };
static char *get_next_line(char *gets_char) static char *get_next_line(char *gets_char)
{ {
@ -737,17 +738,24 @@ static char *get_next_line(char *gets_char)
* doesn't end with either '\n' or '\0' */ * doesn't end with either '\n' or '\0' */
gc = NO_EOL_CHAR; gc = NO_EOL_CHAR;
while (bbg.current_input_file < bbg.input_file_count) { while (bbg.current_input_file < bbg.input_file_count) {
FILE *fp = bbg.input_file_list[bbg.current_input_file];
/* Read line up to a newline or NUL byte, inclusive, /* Read line up to a newline or NUL byte, inclusive,
* return malloc'ed char[]. length of the chunk read * return malloc'ed char[]. length of the chunk read
* is stored in len. NULL if EOF/error */ * is stored in len. NULL if EOF/error */
temp = bb_get_chunk_from_file( temp = bb_get_chunk_from_file(fp, &len);
bbg.input_file_list[bbg.current_input_file], &len);
if (temp) { if (temp) {
/* len > 0 here, it's ok to do temp[len-1] */ /* len > 0 here, it's ok to do temp[len-1] */
char c = temp[len-1]; char c = temp[len-1];
if (c == '\n' || c == '\0') { if (c == '\n' || c == '\0') {
temp[len-1] = '\0'; temp[len-1] = '\0';
gc = c; gc = c;
if (c == '\0') {
int ch = fgetc(fp);
if (ch != EOF)
ungetc(ch, fp);
else
gc = LAST_IS_NUL;
}
} }
/* else we put NO_EOL_CHAR into *gets_char */ /* else we put NO_EOL_CHAR into *gets_char */
break; break;
@ -761,7 +769,8 @@ static char *get_next_line(char *gets_char)
* (note: *no* newline after "b bang"!) */ * (note: *no* newline after "b bang"!) */
} }
/* Close this file and advance to next one */ /* Close this file and advance to next one */
fclose(bbg.input_file_list[bbg.current_input_file++]); fclose(fp);
bbg.current_input_file++;
} }
*gets_char = gc; *gets_char = gc;
return temp; return temp;
@ -785,20 +794,29 @@ static void puts_maybe_newline(char *s, FILE *file, char *last_puts_char, char l
{ {
char lpc = *last_puts_char; char lpc = *last_puts_char;
/* Is this a first line from new file /* Need to insert a '\n' between two files because first file's
* and old file didn't end with '\n' or '\0'? */ * last line wasn't terminated? */
if (lpc != '\n' && lpc != '\0') { if (lpc != '\n' && lpc != '\0') {
fputc('\n', file); fputc('\n', file);
lpc = '\n'; lpc = '\n';
} }
fputs(s, file); fputs(s, file);
/* 'x' - just something which is not '\n', '\0' or NO_EOL_CHAR */ /* 'x' - just something which is not '\n', '\0' or NO_EOL_CHAR */
if (s[0]) if (s[0])
lpc = 'x'; lpc = 'x';
if (last_gets_char != NO_EOL_CHAR) { /* had trailing '\n' or '\0'? */
/* had trailing '\0' and it was last char of file? */
if (last_gets_char == LAST_IS_NUL) {
fputc('\0', file);
lpc = 'x'; /* */
} else
/* had trailing '\n' or '\0'? */
if (last_gets_char != NO_EOL_CHAR) {
fputc(last_gets_char, file); fputc(last_gets_char, file);
lpc = last_gets_char; lpc = last_gets_char;
} }
if (ferror(file)) { if (ferror(file)) {
xfunc_error_retval = 4; /* It's what gnu sed exits with... */ xfunc_error_retval = 4; /* It's what gnu sed exits with... */
bb_error_msg_and_die(bb_msg_write_error); bb_error_msg_and_die(bb_msg_write_error);

View File

@ -143,6 +143,9 @@ testing "sed subst+write" \
"sed -e 's/i/z/' -e 'woutputw' input -; echo -n X; cat outputw" \ "sed -e 's/i/z/' -e 'woutputw' input -; echo -n X; cat outputw" \
"thzngy\nagaznXthzngy\nagazn" "thingy" "again" "thzngy\nagaznXthzngy\nagazn" "thingy" "again"
rm outputw rm outputw
testing "sed trailing NUL" \
"sed 's/i/z/' input -" \
"a\0b\0\nc" "a\0b\0" "c"
# Test end-of-file matching behavior # Test end-of-file matching behavior