Fixed a couple of buglets:
authorMark Whitley <markw@lineo.com>
Fri, 14 Jul 2000 23:24:00 +0000 (23:24 -0000)
committerMark Whitley <markw@lineo.com>
Fri, 14 Jul 2000 23:24:00 +0000 (23:24 -0000)
 - add_cmd_str: segv's were being generated if there was a '# comment' line
   (and probably other kinds of lines, too) that was not followed by a
   semi-colon or whitespace
 - parse_edit_cmd: was returning a wrong number (too low) for the index; it
   was not accounting for backslashes eaten, for the fact that we start at the
   3rd index in the string, or for the fact that we add an extra newline.
 - parse_cmd_str: was returning a wrong number (again, too low) for the index
   in the case of single-letter commands (p,d). There was some
   over-compensation for this in the 'return' stmt at the end which also
   needed some help.
 - load_cmd_file: was not eating trailing newlines off the line read from the
   command file. This had the deleterious effect of printing an extra newlines
   after text displayed from edit (i,a,c) commands.

editors/sed.c
sed.c

index 40400fe3ae3a6cca94f6b2e5b328b01899e1d9cc..1f1e9069cc92fa6da36b5eab1d6a2288a92d1d4e 100644 (file)
@@ -307,6 +307,7 @@ out:
 static int parse_edit_cmd(struct sed_cmd *sed_cmd, const char *editstr)
 {
        int idx = 0;
+       int slashes_eaten = 0;
        char *ptr; /* shorthand */
 
        /*
@@ -346,19 +347,32 @@ static int parse_edit_cmd(struct sed_cmd *sed_cmd, const char *editstr)
                while (ptr[idx] != '\\' && (ptr[idx+1] != '\n' || ptr[idx+1] != '\r')) {
                        idx++;
                        if (!ptr[idx]) {
-                               ptr[idx] = '\n';
-                               ptr[idx+1] = 0;
-                               return idx;
+                               goto out;
                        }
                }
                /* move the newline over the '\' before it (effectively eats the '\') */
                memmove(&ptr[idx], &ptr[idx+1], strlen(&ptr[idx+1]));
                ptr[strlen(ptr)-1] = 0;
+               slashes_eaten++;
                /* substitue \r for \n if needed */
                if (ptr[idx] == '\r')
                        ptr[idx] = '\n';
        }
 
+out:
+       ptr[idx] = '\n';
+       ptr[idx+1] = 0;
+
+       /* this accounts for discrepancies between the modified string and the
+        * original string passed in to this function */
+       idx += slashes_eaten;
+
+       /* this accounts for the fact that A) we started at index 3, not at index
+        * 0  and B) that we added an extra '\n' at the end (if you think the next
+        * line should read 'idx += 4' remember, arrays are zero-based) */
+
+       idx += 3;
+
        return idx;
 }
 
@@ -398,9 +412,13 @@ static char *parse_cmd_str(struct sed_cmd *sed_cmd, const char *cmdstr)
                        fatalError("only a beginning address can be specified for edit commands\n");
                idx += parse_edit_cmd(sed_cmd, &cmdstr[idx]);
        }
+       /* if it was a single-letter command (such as 'p' or 'd') we need to
+        * increment the index past that command */
+       else
+               idx++;
 
        /* give back whatever's left over */
-       return (char *)&cmdstr[++idx];
+       return (char *)&cmdstr[idx];
 }
 
 static void add_cmd_str(const char *cmdstr)
@@ -412,7 +430,7 @@ static void add_cmd_str(const char *cmdstr)
                /* trim leading whitespace and semicolons */
                memmove(mystr, &mystr[strspn(mystr, "; \n\r\t\v")], strlen(mystr));
                /* if we ate the whole thing, that means there was just trailing
-                * whitespace or a final semicolon. either way, get out */
+                * whitespace or a final / no-op semicolon. either way, get out */
                if (strlen(mystr) == 0)
                        return;
                /* if this is a comment, jump past it and keep going */
@@ -427,7 +445,7 @@ static void add_cmd_str(const char *cmdstr)
                /* load command string into new array element, get remainder */
                mystr = parse_cmd_str(&sed_cmds[ncmds-1], mystr);
 
-       } while (mystr);
+       } while (mystr && strlen(mystr));
 }
 
 
@@ -447,7 +465,12 @@ static void load_cmd_file(char *filename)
                                (nextline = get_line_from_file(cmdfile)) != NULL) {
                        line = realloc(line, strlen(line) + strlen(nextline) + 1);
                        strcat(line, nextline);
+                       free(nextline);
                }
+               /* eat trailing newline (if any) --if I don't do this, edit commands
+                * (aic) will print an extra newline */
+               if (line[strlen(line)-1] == '\n')
+                       line[strlen(line)-1] = 0;
                add_cmd_str(line);
                free(line);
        }
diff --git a/sed.c b/sed.c
index 40400fe3ae3a6cca94f6b2e5b328b01899e1d9cc..1f1e9069cc92fa6da36b5eab1d6a2288a92d1d4e 100644 (file)
--- a/sed.c
+++ b/sed.c
@@ -307,6 +307,7 @@ out:
 static int parse_edit_cmd(struct sed_cmd *sed_cmd, const char *editstr)
 {
        int idx = 0;
+       int slashes_eaten = 0;
        char *ptr; /* shorthand */
 
        /*
@@ -346,19 +347,32 @@ static int parse_edit_cmd(struct sed_cmd *sed_cmd, const char *editstr)
                while (ptr[idx] != '\\' && (ptr[idx+1] != '\n' || ptr[idx+1] != '\r')) {
                        idx++;
                        if (!ptr[idx]) {
-                               ptr[idx] = '\n';
-                               ptr[idx+1] = 0;
-                               return idx;
+                               goto out;
                        }
                }
                /* move the newline over the '\' before it (effectively eats the '\') */
                memmove(&ptr[idx], &ptr[idx+1], strlen(&ptr[idx+1]));
                ptr[strlen(ptr)-1] = 0;
+               slashes_eaten++;
                /* substitue \r for \n if needed */
                if (ptr[idx] == '\r')
                        ptr[idx] = '\n';
        }
 
+out:
+       ptr[idx] = '\n';
+       ptr[idx+1] = 0;
+
+       /* this accounts for discrepancies between the modified string and the
+        * original string passed in to this function */
+       idx += slashes_eaten;
+
+       /* this accounts for the fact that A) we started at index 3, not at index
+        * 0  and B) that we added an extra '\n' at the end (if you think the next
+        * line should read 'idx += 4' remember, arrays are zero-based) */
+
+       idx += 3;
+
        return idx;
 }
 
@@ -398,9 +412,13 @@ static char *parse_cmd_str(struct sed_cmd *sed_cmd, const char *cmdstr)
                        fatalError("only a beginning address can be specified for edit commands\n");
                idx += parse_edit_cmd(sed_cmd, &cmdstr[idx]);
        }
+       /* if it was a single-letter command (such as 'p' or 'd') we need to
+        * increment the index past that command */
+       else
+               idx++;
 
        /* give back whatever's left over */
-       return (char *)&cmdstr[++idx];
+       return (char *)&cmdstr[idx];
 }
 
 static void add_cmd_str(const char *cmdstr)
@@ -412,7 +430,7 @@ static void add_cmd_str(const char *cmdstr)
                /* trim leading whitespace and semicolons */
                memmove(mystr, &mystr[strspn(mystr, "; \n\r\t\v")], strlen(mystr));
                /* if we ate the whole thing, that means there was just trailing
-                * whitespace or a final semicolon. either way, get out */
+                * whitespace or a final / no-op semicolon. either way, get out */
                if (strlen(mystr) == 0)
                        return;
                /* if this is a comment, jump past it and keep going */
@@ -427,7 +445,7 @@ static void add_cmd_str(const char *cmdstr)
                /* load command string into new array element, get remainder */
                mystr = parse_cmd_str(&sed_cmds[ncmds-1], mystr);
 
-       } while (mystr);
+       } while (mystr && strlen(mystr));
 }
 
 
@@ -447,7 +465,12 @@ static void load_cmd_file(char *filename)
                                (nextline = get_line_from_file(cmdfile)) != NULL) {
                        line = realloc(line, strlen(line) + strlen(nextline) + 1);
                        strcat(line, nextline);
+                       free(nextline);
                }
+               /* eat trailing newline (if any) --if I don't do this, edit commands
+                * (aic) will print an extra newline */
+               if (line[strlen(line)-1] == '\n')
+                       line[strlen(line)-1] = 0;
                add_cmd_str(line);
                free(line);
        }