add to testsuite and fix yet another sed corner case
This commit is contained in:
		| @@ -724,6 +724,7 @@ static void add_input_file(FILE *file) | ||||
|  */ | ||||
| enum { | ||||
| 	NO_EOL_CHAR = 1, | ||||
| 	LAST_IS_NUL = 2, | ||||
| }; | ||||
| 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' */ | ||||
| 	gc = NO_EOL_CHAR; | ||||
| 	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, | ||||
| 		 * return malloc'ed char[]. length of the chunk read | ||||
| 		 * is stored in len. NULL if EOF/error */ | ||||
| 		temp = bb_get_chunk_from_file( | ||||
| 			bbg.input_file_list[bbg.current_input_file], &len); | ||||
| 		temp = bb_get_chunk_from_file(fp, &len); | ||||
| 		if (temp) { | ||||
| 			/* len > 0 here, it's ok to do temp[len-1] */ | ||||
| 			char c = temp[len-1]; | ||||
| 			if (c == '\n' || c == '\0') { | ||||
| 				temp[len-1] = '\0'; | ||||
| 				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 */ | ||||
| 			break; | ||||
| @@ -761,7 +769,8 @@ static char *get_next_line(char *gets_char) | ||||
| 		 * (note: *no* newline after "b bang"!) */ | ||||
| 		} | ||||
| 		/* 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; | ||||
| 	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; | ||||
|  | ||||
| 	/* Is this a first line from new file | ||||
| 	 * and old file didn't end with '\n' or '\0'? */ | ||||
| 	/* Need to insert a '\n' between two files because first file's | ||||
| 	 * last line wasn't terminated? */ | ||||
| 	if (lpc != '\n' && lpc != '\0') { | ||||
| 		fputc('\n', file); | ||||
| 		lpc = '\n'; | ||||
| 	} | ||||
| 	fputs(s, file); | ||||
|  | ||||
| 	/* 'x' - just something which is not '\n', '\0' or NO_EOL_CHAR */ | ||||
| 	if (s[0]) | ||||
| 		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); | ||||
| 		lpc = last_gets_char; | ||||
| 	} | ||||
|  | ||||
| 	if (ferror(file)) { | ||||
| 		xfunc_error_retval = 4;  /* It's what gnu sed exits with... */ | ||||
| 		bb_error_msg_and_die(bb_msg_write_error); | ||||
|   | ||||
| @@ -143,6 +143,9 @@ testing "sed subst+write" \ | ||||
| 	"sed -e 's/i/z/' -e 'woutputw' input -; echo -n X; cat outputw" \ | ||||
| 	"thzngy\nagaznXthzngy\nagazn" "thingy" "again" | ||||
| 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 | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user