@@ -851,37 +851,79 @@ static void append(char *s)
851851 llist_add_to_end (& G .append_head , s );
852852}
853853
854- static void flush_append (void )
854+ /* Output line of text. */
855+ /* Note:
856+ * The tricks with NO_EOL_CHAR and last_puts_char are there to emulate gnu sed.
857+ * Without them, we had this:
858+ * echo -n thingy >z1
859+ * echo -n again >z2
860+ * >znull
861+ * sed "s/i/z/" z1 z2 znull | hexdump -vC
862+ * output:
863+ * gnu sed 4.1.5:
864+ * 00000000 74 68 7a 6e 67 79 0a 61 67 61 7a 6e |thzngy.agazn|
865+ * bbox:
866+ * 00000000 74 68 7a 6e 67 79 61 67 61 7a 6e |thzngyagazn|
867+ */
868+ enum {
869+ NO_EOL_CHAR = 1 ,
870+ LAST_IS_NUL = 2 ,
871+ };
872+ static void puts_maybe_newline (char * s , FILE * file , char * last_puts_char , char last_gets_char )
873+ {
874+ char lpc = * last_puts_char ;
875+
876+ /* Need to insert a '\n' between two files because first file's
877+ * last line wasn't terminated? */
878+ if (lpc != '\n' && lpc != '\0' ) {
879+ fputc ('\n' , file );
880+ lpc = '\n' ;
881+ }
882+ fputs (s , file );
883+
884+ /* 'x' - just something which is not '\n', '\0' or NO_EOL_CHAR */
885+ if (s [0 ])
886+ lpc = 'x' ;
887+
888+ /* had trailing '\0' and it was last char of file? */
889+ if (last_gets_char == LAST_IS_NUL ) {
890+ fputc ('\0' , file );
891+ lpc = 'x' ; /* */
892+ } else
893+ /* had trailing '\n' or '\0'? */
894+ if (last_gets_char != NO_EOL_CHAR ) {
895+ fputc (last_gets_char , file );
896+ lpc = last_gets_char ;
897+ }
898+
899+ if (ferror (file )) {
900+ xfunc_error_retval = 4 ; /* It's what gnu sed exits with... */
901+ bb_error_msg_and_die (bb_msg_write_error );
902+ }
903+ * last_puts_char = lpc ;
904+ }
905+
906+ static void flush_append (char * last_puts_char , char last_gets_char )
855907{
856908 char * data ;
857909
858910 /* Output appended lines. */
859911 while ((data = (char * )llist_pop (& G .append_head ))) {
860- fprintf ( G .nonstdout , "%s\n" , data );
912+ puts_maybe_newline ( data , G .nonstdout , last_puts_char , last_gets_char );
861913 free (data );
862914 }
863915}
864916
865- static void add_input_file (FILE * file )
866- {
867- G .input_file_list = xrealloc_vector (G .input_file_list , 2 , G .input_file_count );
868- G .input_file_list [G .input_file_count ++ ] = file ;
869- }
870-
871917/* Get next line of input from G.input_file_list, flushing append buffer and
872918 * noting if we ran out of files without a newline on the last line we read.
873919 */
874- enum {
875- NO_EOL_CHAR = 1 ,
876- LAST_IS_NUL = 2 ,
877- };
878- static char * get_next_line (char * gets_char )
920+ static char * get_next_line (char * gets_char , char * last_puts_char , char last_gets_char )
879921{
880922 char * temp = NULL ;
881923 int len ;
882924 char gc ;
883925
884- flush_append ();
926+ flush_append (last_puts_char , last_gets_char );
885927
886928 /* will be returned if last line in the file
887929 * doesn't end with either '\n' or '\0' */
@@ -925,54 +967,6 @@ static char *get_next_line(char *gets_char)
925967 return temp ;
926968}
927969
928- /* Output line of text. */
929- /* Note:
930- * The tricks with NO_EOL_CHAR and last_puts_char are there to emulate gnu sed.
931- * Without them, we had this:
932- * echo -n thingy >z1
933- * echo -n again >z2
934- * >znull
935- * sed "s/i/z/" z1 z2 znull | hexdump -vC
936- * output:
937- * gnu sed 4.1.5:
938- * 00000000 74 68 7a 6e 67 79 0a 61 67 61 7a 6e |thzngy.agazn|
939- * bbox:
940- * 00000000 74 68 7a 6e 67 79 61 67 61 7a 6e |thzngyagazn|
941- */
942- static void puts_maybe_newline (char * s , FILE * file , char * last_puts_char , char last_gets_char )
943- {
944- char lpc = * last_puts_char ;
945-
946- /* Need to insert a '\n' between two files because first file's
947- * last line wasn't terminated? */
948- if (lpc != '\n' && lpc != '\0' ) {
949- fputc ('\n' , file );
950- lpc = '\n' ;
951- }
952- fputs (s , file );
953-
954- /* 'x' - just something which is not '\n', '\0' or NO_EOL_CHAR */
955- if (s [0 ])
956- lpc = 'x' ;
957-
958- /* had trailing '\0' and it was last char of file? */
959- if (last_gets_char == LAST_IS_NUL ) {
960- fputc ('\0' , file );
961- lpc = 'x' ; /* */
962- } else
963- /* had trailing '\n' or '\0'? */
964- if (last_gets_char != NO_EOL_CHAR ) {
965- fputc (last_gets_char , file );
966- lpc = last_gets_char ;
967- }
968-
969- if (ferror (file )) {
970- xfunc_error_retval = 4 ; /* It's what gnu sed exits with... */
971- bb_error_msg_and_die (bb_msg_write_error );
972- }
973- * last_puts_char = lpc ;
974- }
975-
976970#define sed_puts (s , n ) (puts_maybe_newline(s, G.nonstdout, &last_puts_char, n))
977971
978972static int beg_match (sed_cmd_t * sed_cmd , const char * pattern_space )
@@ -995,7 +989,7 @@ static void process_files(void)
995989 int substituted ;
996990
997991 /* Prime the pump */
998- next_line = get_next_line (& next_gets_char );
992+ next_line = get_next_line (& next_gets_char , & last_puts_char , '\n' /*last_gets_char*/ );
999993
1000994 /* Go through every line in each file */
1001995 again :
@@ -1009,7 +1003,7 @@ static void process_files(void)
10091003
10101004 /* Read one line in advance so we can act on the last line,
10111005 * the '$' address */
1012- next_line = get_next_line (& next_gets_char );
1006+ next_line = get_next_line (& next_gets_char , & last_puts_char , last_gets_char );
10131007 linenum ++ ;
10141008
10151009 /* For every line, go through all the commands */
@@ -1227,7 +1221,7 @@ static void process_files(void)
12271221 free (pattern_space );
12281222 pattern_space = next_line ;
12291223 last_gets_char = next_gets_char ;
1230- next_line = get_next_line (& next_gets_char );
1224+ next_line = get_next_line (& next_gets_char , & last_puts_char , last_gets_char );
12311225 substituted = 0 ;
12321226 linenum ++ ;
12331227 break ;
@@ -1263,7 +1257,7 @@ static void process_files(void)
12631257 pattern_space [len ] = '\n' ;
12641258 strcpy (pattern_space + len + 1 , next_line );
12651259 last_gets_char = next_gets_char ;
1266- next_line = get_next_line (& next_gets_char );
1260+ next_line = get_next_line (& next_gets_char , & last_puts_char , last_gets_char );
12671261 linenum ++ ;
12681262 break ;
12691263 }
@@ -1367,7 +1361,7 @@ static void process_files(void)
13671361
13681362 /* Delete and such jump here. */
13691363 discard_line :
1370- flush_append ();
1364+ flush_append (& last_puts_char , last_gets_char );
13711365 free (pattern_space );
13721366
13731367 goto again ;
@@ -1394,6 +1388,12 @@ static void add_cmd_block(char *cmdstr)
13941388 free (sv );
13951389}
13961390
1391+ static void add_input_file (FILE * file )
1392+ {
1393+ G .input_file_list = xrealloc_vector (G .input_file_list , 2 , G .input_file_count );
1394+ G .input_file_list [G .input_file_count ++ ] = file ;
1395+ }
1396+
13971397int sed_main (int argc , char * * argv ) MAIN_EXTERNALLY_VISIBLE ;
13981398int sed_main (int argc UNUSED_PARAM , char * * argv )
13991399{
0 commit comments