[prev in list] [next in list] [prev in thread] [next in thread] 

List:       busybox
Subject:    Re: Sigh...  Bumping the sed nul fix to 1.1.2.
From:       "Roberto A. Foglietta" <me () roberto ! foglietta ! name>
Date:       2006-02-28 11:04:56
Message-ID: 44042E58.2010300 () roberto ! foglietta ! name
[Download RAW message or body]

Martijn de Gouw wrote:
> 
> Why don't post two patches,
> 1) bug fix
> 2) name changes
> 

  Yes you are right, probably I am lazy... but I supposed that divide 
renameing from patch was pretty simple (using sed on the patch itself):

svn co ...
cp -af busybox busybox.orig

cat sed_4-svn14360.patch | \
sed -e "s/lastchar/no_newline/g" >sed_4-svn14360_tmp.patch

patch -p0 <sed_3-svn14360_tmp.patch
mv busybox busybox_sed4
cp -a busybox.orig busybox
diff -pru busybox busybox_sed4 >sed_4-svn14360_norename.patch

  In this way the patch size is resized to an half than before but a lot 
of that patch is someting like that

   -sed_puts(sed_cmd->string,0);
   +sed_puts(sed_cmd->string,'\n');

    -sed_puts(sed_cmd->string,1);
   +sed_puts(sed_cmd->string,NONE);

  Which is pretty simple to understand but could not stripped away by 
sed in order to reduce patch. The patch concept is pretty simple: in 
reading I save at the end of buffer, after ending \0 the "lastchar" and 
depending of the nature of this "lastchar" I will put in the destination 
file or ignore it. Obviously the reading/buffer are modified a little 
bit to read and contain that "lastchar"

  I found also that patch does not apply at svn so I attached new one at 
the end of this mail. To test them:

dd if=/dev/zero bs=1k count=1 >/tmp/test
echo ciao>>/tmp/test
dd if=/dev/zero bs=1k count=1 >>/tmp/test
cat /tmp/test | ./busybox sed -e "s/ciao/miao/g" >/tmp/test2
wc -l /tmp/test*
du -b /tmp/test*

  I am going to put them in the bugs system.


  Cheers,
-- 
Roberto A. Foglietta
http://roberto.foglietta.name
http://lugge.net

["sed_4-svn14360.patch" (text/x-patch)]

diff -pru busybox/editors/sed.c busybox.14360_sed4a/editors/sed.c
--- busybox/editors/sed.c	2006-02-28 09:51:07.000000000 +0100
+++ busybox.14360_sed4a/editors/sed.c	2006-02-28 11:34:18.000000000 +0100
@@ -67,6 +67,8 @@
 #include "busybox.h"
 #include "xregex.h"
 
+#define NONE EOF
+#define sed_cmd_t_null {0,0,0, 0,0, 0,0, 0, 0,0,EOF,0, 0,0}
 typedef struct sed_cmd_s {
     /* Ordered by alignment requirements: currently 36 bytes on x86 */
 
@@ -85,7 +87,7 @@ typedef struct sed_cmd_s {
     /* Bitfields (gcc won't group them if we don't) */
     unsigned int invert:1;			/* the '!' after the address */
     unsigned int in_match:1;		/* Next line also included in match? */
-    unsigned int no_newline:1;		/* Last line written by (sw) had no '\n' */
+    unsigned int lastchar:1;		/* Last line written by (sw) had no '\n' */
     unsigned int sub_p:1;			/* (s) print option */
 
 
@@ -112,7 +114,7 @@ static regmatch_t regmatch[10];
 static regex_t *previous_regex_ptr;
 
 /* linked list of sed commands */
-static sed_cmd_t sed_cmd_head;
+static sed_cmd_t sed_cmd_head = sed_cmd_t_null;
 static sed_cmd_t *sed_cmd_tail = &sed_cmd_head;
 
 /* Linked list of append lines */
@@ -726,20 +728,23 @@ static void add_input_file(FILE *file)
 /* Get next line of input from input_file_list, flushing append buffer and
  * noting if we ran out of files without a newline on the last line we read.
  */
-static char *get_next_line(int *no_newline)
+static char *get_next_line(int *lastchar)
 {
 	char *temp=NULL;
 	int len;
 
 	flush_append();
 	while (current_input_file<input_file_count) {
-		temp = bb_get_chunk_from_file(input_file_list[current_input_file],&len);
+		temp = bb_get_chunk_from_file(input_file_list[current_input_file],NULL);
 		if (temp) {
-			*no_newline = !(len && temp[len-1]=='\n');
-			if (!*no_newline) temp[len-1] = 0;
+			len = 0; while(temp[len]) len++;
+			*lastchar = *(int *)&temp[len+1];
 			break;
 		// Close this file and advance to next one
-		} else fclose(input_file_list[current_input_file++]);
+		} else {
+			fclose(input_file_list[current_input_file++]);
+			*lastchar=NONE;
+		}
 	}
 
 	return temp;
@@ -749,18 +754,18 @@ static char *get_next_line(int *no_newli
    end with a newline.  no_newline means this line does not end with a
    newline. */
 
-static int puts_maybe_newline(char *s, FILE *file, int missing_newline, int \
no_newline) +static int puts_maybe_newline(char *s, FILE *file, int missing, int \
lastchar)  {
-	if(missing_newline) fputc('\n',file);
-	fputs(s,file);
-	if(!no_newline) fputc('\n',file);
 
-    if(ferror(file)) {
-		fprintf(stderr,"Write failed.\n");
-		exit(4);  /* It's what gnu sed exits with... */
-	}
+	if(missing==NONE)	//missing to do not miss the '\n' between two streams!
+		fputc('\n',file);
+	fputs(s,file);
+	if(lastchar!=NONE) 
+		fputc(lastchar,file);
+	if(ferror(file))
+		bb_perror_msg_and_die("Write failed");
 
-	return no_newline;
+	return lastchar;
 }
 
 #define sed_puts(s,n) \
missing_newline=puts_maybe_newline(s,nonstdout,missing_newline,n) @@ -771,10 +776,10 \
@@ static void process_files(void)  {
 	char *pattern_space, *next_line;
 	int linenum = 0, missing_newline=0;
-	int no_newline,next_no_newline=0;
+	int next_lastchar=NONE, lastchar=NONE;
 
 	/* Prime the pump */
-	next_line = get_next_line(&next_no_newline);
+	next_line = get_next_line(&next_lastchar);
 
 	/* go through every line in each file */
 	for(;;) {
@@ -783,11 +788,11 @@ static void process_files(void)
 
 		/* Advance to next line.  Stop if out of lines. */
 		if(!(pattern_space=next_line)) break;
-		no_newline=next_no_newline;
+		lastchar=next_lastchar;
 
 		/* Read one line in advance so we can act on the last line,
 		 * the '$' address */
-		next_line = get_next_line(&next_no_newline);
+		next_line = get_next_line(&next_lastchar);
 		linenum++;
 restart:
 		/* for every line, go through all the commands */
@@ -865,7 +870,7 @@ restart:
 
 						if (tmp) {
 							*tmp = '\0';
-							sed_puts(pattern_space,1);
+							sed_puts(pattern_space,NONE);
 							*tmp = '\n';
 							break;
 						}
@@ -874,7 +879,7 @@ restart:
 
 					/* Write the current pattern space to output */
 					case 'p':
-						sed_puts(pattern_space,no_newline);
+						sed_puts(pattern_space,lastchar);
 						break;
 					/* Delete up through first newline */
 					case 'D':
@@ -899,11 +904,10 @@ restart:
 
 							/* handle p option */
 							if(sed_cmd->sub_p)
-								sed_puts(pattern_space,no_newline);
+								sed_puts(pattern_space,lastchar);
 							/* handle w option */
 							if(sed_cmd->file)
-								sed_cmd->no_newline=puts_maybe_newline(pattern_space, sed_cmd->file, \
                sed_cmd->no_newline, no_newline);
-
+								sed_cmd->lastchar=puts_maybe_newline(pattern_space, sed_cmd->file, \
sed_cmd->lastchar, lastchar);  }
 						break;
 
@@ -916,13 +920,13 @@ restart:
 
 					/* Insert text before this line */
 					case 'i':
-						sed_puts(sed_cmd->string,1);
+						sed_puts(sed_cmd->string,NONE);
 						break;
 
 					/* Cut and paste text (replace) */
 					case 'c':
 						/* Only triggers on last line of a matching range. */
-						if (!sed_cmd->in_match) sed_puts(sed_cmd->string,0);
+						if (!sed_cmd->in_match) sed_puts(sed_cmd->string,'\n');
 						goto discard_line;
 
 					/* Read file, append contents to output */
@@ -945,18 +949,18 @@ restart:
 
 					/* Write pattern space to file. */
 					case 'w':
-						sed_cmd->no_newline=puts_maybe_newline(pattern_space,sed_cmd->file, \
sed_cmd->no_newline,no_newline); \
+						sed_cmd->lastchar=puts_maybe_newline(pattern_space,sed_cmd->file, \
sed_cmd->lastchar,lastchar);  break;
 
 					/* Read next line from input */
 					case 'n':
 						if (!be_quiet)
-							sed_puts(pattern_space,no_newline);
+							sed_puts(pattern_space,lastchar);
 						if (next_line) {
 							free(pattern_space);
 							pattern_space = next_line;
-							no_newline=next_no_newline;
-							next_line = get_next_line(&next_no_newline);
+							lastchar=next_lastchar;
+							next_line = get_next_line(&next_lastchar);
 							linenum++;
 							break;
 						}
@@ -985,8 +989,8 @@ restart:
 							pattern_space = realloc(pattern_space, len + strlen(next_line) + 2);
 							pattern_space[len]='\n';
 							strcpy(pattern_space+len+1, next_line);
-							no_newline=next_no_newline;
-							next_line = get_next_line(&next_no_newline);
+							lastchar=next_lastchar;
+							next_line = get_next_line(&next_lastchar);
 							linenum++;
 						}
 						break;
@@ -1040,8 +1044,7 @@ restart:
 						if (pattern_space_size == 2) pattern_space[0]=0;
 						strcat(pattern_space, "\n");
 						if (hold_space) strcat(pattern_space, hold_space);
-						no_newline=0;
-
+						lastchar='\n';
 						break;
 					}
 					case 'h':	/* Replace hold space with pattern space */
@@ -1069,7 +1072,7 @@ restart:
 					{
 						char *tmp = pattern_space;
 						pattern_space = hold_space;
-						no_newline=0;
+						lastchar='\n';
 						hold_space = tmp;
 						break;
 					}
@@ -1083,7 +1086,7 @@ restart:
 discard_commands:
 		/* we will print the line unless we were told to be quiet ('-n')
 		   or if the line was suppressed (ala 'd'elete) */
-		if (!be_quiet) sed_puts(pattern_space,no_newline);
+		if (!be_quiet) sed_puts(pattern_space,lastchar);
 
 		/* Delete and such jump here. */
 discard_line:
diff -pru busybox/libbb/get_line_from_file.c \
                busybox.14360_sed4a/libbb/get_line_from_file.c
--- busybox/libbb/get_line_from_file.c	2006-02-28 09:50:35.000000000 +0100
+++ busybox.14360_sed4a/libbb/get_line_from_file.c	2006-02-28 11:30:42.000000000 \
+0100 @@ -16,7 +16,7 @@
 /* get_line_from_file() - This function reads an entire line from a text file,
  * up to a newline or NUL byte.  It returns a malloc'ed char * which must be
  * stored and free'ed  by the caller.  If end is null '\n' isn't considered
- * and of line.  If end isn't null, length of the chunk read is stored in it. */
+ * end of line.  If end isn't null, length of the chunk read is stored in it. */
 
 char *bb_get_chunk_from_file(FILE *file, int *end)
 {
@@ -27,11 +27,15 @@ char *bb_get_chunk_from_file(FILE *file,
 
 	while ((ch = getc(file)) != EOF) {
 		/* grow the line buffer as necessary */
-		if (idx > linebufsz - 2) {
+		if (idx > linebufsz - 6) {
 			linebuf = xrealloc(linebuf, linebufsz += 80);
 		}
+		if(!ch) break;
 		linebuf[idx++] = (char)ch;
-		if (!ch || (end && ch == '\n')) break;
+		if (ch == '\n') {
+			if(!end) --idx;
+			break;
+		}
 	}
 	if (end) *end = idx;
 	if (linebuf) {
@@ -39,7 +43,8 @@ char *bb_get_chunk_from_file(FILE *file,
 			free(linebuf);
 			return NULL;
 		}
-		linebuf[idx] = 0;
+		linebuf[idx++] = 0;
+		*(int *)&linebuf[idx] = ch;
 	}
 	return linebuf;
 }
@@ -54,9 +59,5 @@ extern char *bb_get_line_from_file(FILE 
 /* Get line.  Remove trailing /n */
 extern char *bb_get_chomped_line_from_file(FILE *file)
 {
-	int i;
-	char *c=bb_get_chunk_from_file(file, &i);
-	if(i) c[--i]=0;
-	
-	return c;
+	return bb_get_chunk_from_file(file, NULL);
 }


["sed_4-svn14360_norename.patch" (text/x-patch)]

diff -pru busybox/editors/sed.c busybox_sed4/editors/sed.c
--- busybox/editors/sed.c	2006-02-28 09:51:07.000000000 +0100
+++ busybox_sed4/editors/sed.c	2006-02-28 11:59:43.000000000 +0100
@@ -67,6 +67,8 @@
 #include "busybox.h"
 #include "xregex.h"
 
+#define NONE EOF
+#define sed_cmd_t_null {0,0,0, 0,0, 0,0, 0, 0,0,EOF,0, 0,0}
 typedef struct sed_cmd_s {
     /* Ordered by alignment requirements: currently 36 bytes on x86 */
 
@@ -112,7 +114,7 @@ static regmatch_t regmatch[10];
 static regex_t *previous_regex_ptr;
 
 /* linked list of sed commands */
-static sed_cmd_t sed_cmd_head;
+static sed_cmd_t sed_cmd_head = sed_cmd_t_null;
 static sed_cmd_t *sed_cmd_tail = &sed_cmd_head;
 
 /* Linked list of append lines */
@@ -733,13 +735,16 @@ static char *get_next_line(int *no_newli
 
 	flush_append();
 	while (current_input_file<input_file_count) {
-		temp = bb_get_chunk_from_file(input_file_list[current_input_file],&len);
+		temp = bb_get_chunk_from_file(input_file_list[current_input_file],NULL);
 		if (temp) {
-			*no_newline = !(len && temp[len-1]=='\n');
-			if (!*no_newline) temp[len-1] = 0;
+			len = 0; while(temp[len]) len++;
+			*no_newline = *(int *)&temp[len+1];
 			break;
 		// Close this file and advance to next one
-		} else fclose(input_file_list[current_input_file++]);
+		} else {
+			fclose(input_file_list[current_input_file++]);
+			*no_newline=NONE;
+		}
 	}
 
 	return temp;
@@ -749,16 +754,16 @@ static char *get_next_line(int *no_newli
    end with a newline.  no_newline means this line does not end with a
    newline. */
 
-static int puts_maybe_newline(char *s, FILE *file, int missing_newline, int \
no_newline) +static int puts_maybe_newline(char *s, FILE *file, int missing, int \
no_newline)  {
-	if(missing_newline) fputc('\n',file);
-	fputs(s,file);
-	if(!no_newline) fputc('\n',file);
 
-    if(ferror(file)) {
-		fprintf(stderr,"Write failed.\n");
-		exit(4);  /* It's what gnu sed exits with... */
-	}
+	if(missing==NONE)	//missing to do not miss the '\n' between two streams!
+		fputc('\n',file);
+	fputs(s,file);
+	if(no_newline!=NONE) 
+		fputc(no_newline,file);
+	if(ferror(file))
+		bb_perror_msg_and_die("Write failed");
 
 	return no_newline;
 }
@@ -771,7 +776,7 @@ static void process_files(void)
 {
 	char *pattern_space, *next_line;
 	int linenum = 0, missing_newline=0;
-	int no_newline,next_no_newline=0;
+	int next_no_newline=NONE, no_newline=NONE;
 
 	/* Prime the pump */
 	next_line = get_next_line(&next_no_newline);
@@ -865,7 +870,7 @@ restart:
 
 						if (tmp) {
 							*tmp = '\0';
-							sed_puts(pattern_space,1);
+							sed_puts(pattern_space,NONE);
 							*tmp = '\n';
 							break;
 						}
@@ -903,7 +908,6 @@ restart:
 							/* handle w option */
 							if(sed_cmd->file)
 								sed_cmd->no_newline=puts_maybe_newline(pattern_space, sed_cmd->file, \
                sed_cmd->no_newline, no_newline);
-
 						}
 						break;
 
@@ -916,13 +920,13 @@ restart:
 
 					/* Insert text before this line */
 					case 'i':
-						sed_puts(sed_cmd->string,1);
+						sed_puts(sed_cmd->string,NONE);
 						break;
 
 					/* Cut and paste text (replace) */
 					case 'c':
 						/* Only triggers on last line of a matching range. */
-						if (!sed_cmd->in_match) sed_puts(sed_cmd->string,0);
+						if (!sed_cmd->in_match) sed_puts(sed_cmd->string,'\n');
 						goto discard_line;
 
 					/* Read file, append contents to output */
@@ -1040,8 +1044,7 @@ restart:
 						if (pattern_space_size == 2) pattern_space[0]=0;
 						strcat(pattern_space, "\n");
 						if (hold_space) strcat(pattern_space, hold_space);
-						no_newline=0;
-
+						no_newline='\n';
 						break;
 					}
 					case 'h':	/* Replace hold space with pattern space */
@@ -1069,7 +1072,7 @@ restart:
 					{
 						char *tmp = pattern_space;
 						pattern_space = hold_space;
-						no_newline=0;
+						no_newline='\n';
 						hold_space = tmp;
 						break;
 					}
diff -pru busybox/libbb/get_line_from_file.c busybox_sed4/libbb/get_line_from_file.c
--- busybox/libbb/get_line_from_file.c	2006-02-28 09:50:35.000000000 +0100
+++ busybox_sed4/libbb/get_line_from_file.c	2006-02-28 11:59:43.000000000 +0100
@@ -16,7 +16,7 @@
 /* get_line_from_file() - This function reads an entire line from a text file,
  * up to a newline or NUL byte.  It returns a malloc'ed char * which must be
  * stored and free'ed  by the caller.  If end is null '\n' isn't considered
- * and of line.  If end isn't null, length of the chunk read is stored in it. */
+ * end of line.  If end isn't null, length of the chunk read is stored in it. */
 
 char *bb_get_chunk_from_file(FILE *file, int *end)
 {
@@ -27,11 +27,15 @@ char *bb_get_chunk_from_file(FILE *file,
 
 	while ((ch = getc(file)) != EOF) {
 		/* grow the line buffer as necessary */
-		if (idx > linebufsz - 2) {
+		if (idx > linebufsz - 6) {
 			linebuf = xrealloc(linebuf, linebufsz += 80);
 		}
+		if(!ch) break;
 		linebuf[idx++] = (char)ch;
-		if (!ch || (end && ch == '\n')) break;
+		if (ch == '\n') {
+			if(!end) --idx;
+			break;
+		}
 	}
 	if (end) *end = idx;
 	if (linebuf) {
@@ -39,7 +43,8 @@ char *bb_get_chunk_from_file(FILE *file,
 			free(linebuf);
 			return NULL;
 		}
-		linebuf[idx] = 0;
+		linebuf[idx++] = 0;
+		*(int *)&linebuf[idx] = ch;
 	}
 	return linebuf;
 }
@@ -54,9 +59,5 @@ extern char *bb_get_line_from_file(FILE 
 /* Get line.  Remove trailing /n */
 extern char *bb_get_chomped_line_from_file(FILE *file)
 {
-	int i;
-	char *c=bb_get_chunk_from_file(file, &i);
-	if(i) c[--i]=0;
-	
-	return c;
+	return bb_get_chunk_from_file(file, NULL);
 }



_______________________________________________
busybox mailing list
busybox@busybox.net
http://busybox.net/cgi-bin/mailman/listinfo/busybox

[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic