Fixed a couple of buglets:

- 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.
This commit is contained in:
Mark Whitley 2000-07-14 23:24:00 +00:00
parent 70705d7c96
commit 464c5de00d
2 changed files with 58 additions and 12 deletions

View File

@ -307,6 +307,7 @@ out:
static int parse_edit_cmd(struct sed_cmd *sed_cmd, const char *editstr) static int parse_edit_cmd(struct sed_cmd *sed_cmd, const char *editstr)
{ {
int idx = 0; int idx = 0;
int slashes_eaten = 0;
char *ptr; /* shorthand */ 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')) { while (ptr[idx] != '\\' && (ptr[idx+1] != '\n' || ptr[idx+1] != '\r')) {
idx++; idx++;
if (!ptr[idx]) { if (!ptr[idx]) {
ptr[idx] = '\n'; goto out;
ptr[idx+1] = 0;
return idx;
} }
} }
/* move the newline over the '\' before it (effectively eats the '\') */ /* move the newline over the '\' before it (effectively eats the '\') */
memmove(&ptr[idx], &ptr[idx+1], strlen(&ptr[idx+1])); memmove(&ptr[idx], &ptr[idx+1], strlen(&ptr[idx+1]));
ptr[strlen(ptr)-1] = 0; ptr[strlen(ptr)-1] = 0;
slashes_eaten++;
/* substitue \r for \n if needed */ /* substitue \r for \n if needed */
if (ptr[idx] == '\r') if (ptr[idx] == '\r')
ptr[idx] = '\n'; 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; 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"); fatalError("only a beginning address can be specified for edit commands\n");
idx += parse_edit_cmd(sed_cmd, &cmdstr[idx]); 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 */ /* give back whatever's left over */
return (char *)&cmdstr[++idx]; return (char *)&cmdstr[idx];
} }
static void add_cmd_str(const char *cmdstr) 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 */ /* trim leading whitespace and semicolons */
memmove(mystr, &mystr[strspn(mystr, "; \n\r\t\v")], strlen(mystr)); memmove(mystr, &mystr[strspn(mystr, "; \n\r\t\v")], strlen(mystr));
/* if we ate the whole thing, that means there was just trailing /* 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) if (strlen(mystr) == 0)
return; return;
/* if this is a comment, jump past it and keep going */ /* 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 */ /* load command string into new array element, get remainder */
mystr = parse_cmd_str(&sed_cmds[ncmds-1], mystr); 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) { (nextline = get_line_from_file(cmdfile)) != NULL) {
line = realloc(line, strlen(line) + strlen(nextline) + 1); line = realloc(line, strlen(line) + strlen(nextline) + 1);
strcat(line, nextline); 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); add_cmd_str(line);
free(line); free(line);
} }

35
sed.c
View File

@ -307,6 +307,7 @@ out:
static int parse_edit_cmd(struct sed_cmd *sed_cmd, const char *editstr) static int parse_edit_cmd(struct sed_cmd *sed_cmd, const char *editstr)
{ {
int idx = 0; int idx = 0;
int slashes_eaten = 0;
char *ptr; /* shorthand */ 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')) { while (ptr[idx] != '\\' && (ptr[idx+1] != '\n' || ptr[idx+1] != '\r')) {
idx++; idx++;
if (!ptr[idx]) { if (!ptr[idx]) {
ptr[idx] = '\n'; goto out;
ptr[idx+1] = 0;
return idx;
} }
} }
/* move the newline over the '\' before it (effectively eats the '\') */ /* move the newline over the '\' before it (effectively eats the '\') */
memmove(&ptr[idx], &ptr[idx+1], strlen(&ptr[idx+1])); memmove(&ptr[idx], &ptr[idx+1], strlen(&ptr[idx+1]));
ptr[strlen(ptr)-1] = 0; ptr[strlen(ptr)-1] = 0;
slashes_eaten++;
/* substitue \r for \n if needed */ /* substitue \r for \n if needed */
if (ptr[idx] == '\r') if (ptr[idx] == '\r')
ptr[idx] = '\n'; 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; 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"); fatalError("only a beginning address can be specified for edit commands\n");
idx += parse_edit_cmd(sed_cmd, &cmdstr[idx]); 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 */ /* give back whatever's left over */
return (char *)&cmdstr[++idx]; return (char *)&cmdstr[idx];
} }
static void add_cmd_str(const char *cmdstr) 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 */ /* trim leading whitespace and semicolons */
memmove(mystr, &mystr[strspn(mystr, "; \n\r\t\v")], strlen(mystr)); memmove(mystr, &mystr[strspn(mystr, "; \n\r\t\v")], strlen(mystr));
/* if we ate the whole thing, that means there was just trailing /* 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) if (strlen(mystr) == 0)
return; return;
/* if this is a comment, jump past it and keep going */ /* 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 */ /* load command string into new array element, get remainder */
mystr = parse_cmd_str(&sed_cmds[ncmds-1], mystr); 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) { (nextline = get_line_from_file(cmdfile)) != NULL) {
line = realloc(line, strlen(line) + strlen(nextline) + 1); line = realloc(line, strlen(line) + strlen(nextline) + 1);
strcat(line, nextline); 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); add_cmd_str(line);
free(line); free(line);
} }