Experimental support for embeded newline. (im evil)

Fix segfault when using 'N' with an odd number of lines.
This commit is contained in:
Glenn L McGrath 2003-03-30 03:41:53 +00:00
parent b5b5ac3237
commit 0c51832b60
2 changed files with 64 additions and 10 deletions

View File

@ -24,6 +24,15 @@ config CONFIG_SED
help help
Please submit a patch to add help text for this item. Please submit a patch to add help text for this item.
config CONFIG_FEATURE_SED_EMBEDED_NEWLINE
bool " Embeded newline (EXPERIMENTAL)"
default n
depends on CONFIG_SED
help
This is a hack to allow matching of '\n' in regular expressions.
It works by translating '\n' to "\n" and back.
It may introduce unexpected results if you use "\n" in your text.
config CONFIG_VI config CONFIG_VI
bool "vi" bool "vi"
default n default n

View File

@ -430,7 +430,7 @@ static char *parse_cmd_str(sed_cmd_t * const sed_cmd, char *cmdstr)
static char *add_cmd(sed_cmd_t *sed_cmd, char *cmdstr) static char *add_cmd(sed_cmd_t *sed_cmd, char *cmdstr)
{ {
/* Skip over leading whitespace and semicolons */ /* Skip over leading whitespace and semicolons */
cmdstr += strspn(cmdstr, semicolon_whitespace); cmdstr += strspn(cmdstr, semicolon_whitespace);
@ -491,7 +491,6 @@ static char *add_cmd(sed_cmd_t *sed_cmd, char *cmdstr)
cmdstr++; cmdstr++;
} }
#endif #endif
} }
/* last part (mandatory) will be a command */ /* last part (mandatory) will be a command */
@ -529,6 +528,18 @@ static char *add_cmd(sed_cmd_t *sed_cmd, char *cmdstr)
static void add_cmd_str(char *cmdstr) static void add_cmd_str(char *cmdstr)
{ {
#ifdef CONFIG_FEATURE_SED_EMBEDED_NEWLINE
char *cmdstr_ptr = cmdstr;
/* HACK: convert "\n" to match tranlated '\n' string */
while((cmdstr_ptr = strstr(cmdstr_ptr, "\\n")) != NULL) {
cmdstr = xrealloc(cmdstr, strlen(cmdstr) + 2);
cmdstr_ptr = strstr(cmdstr, "\\n");
memmove(cmdstr_ptr + 1, cmdstr_ptr, strlen(cmdstr_ptr) + 1);
cmdstr_ptr[0] = '\\';
cmdstr_ptr += 3;
}
#endif
do { do {
sed_cmd_t *sed_cmd; sed_cmd_t *sed_cmd;
sed_cmd = xcalloc(1, sizeof(sed_cmd_t)); sed_cmd = xcalloc(1, sizeof(sed_cmd_t));
@ -795,8 +806,35 @@ static void process_file(FILE *file)
* flag exists in the first place. * flag exists in the first place.
*/ */
#ifdef CONFIG_FEATURE_SED_EMBEDED_NEWLINE
/* HACK: escape newlines twice so regex can match them */
{
int offset = 0;
while(strchr(line + offset, '\n') != NULL) {
char *tmp;
line = xrealloc(line, strlen(line) + 2);
tmp = strchr(line + offset, '\n');
memmove(tmp + 1, tmp, strlen(tmp) + 1);
tmp[0] = '\\';
tmp[1] = 'n';
offset = tmp - line + 2;
}
}
#endif
/* we print the line once, unless we were told to be quiet */ /* we print the line once, unless we were told to be quiet */
substituted = do_subst_command(sed_cmd, &line); substituted = do_subst_command(sed_cmd, &line);
#ifdef CONFIG_FEATURE_SED_EMBEDED_NEWLINE
/* undo HACK: escape newlines twice so regex can match them */
{
char *tmp = line;
while((tmp = strstr(tmp, "\\n")) != NULL) {
memmove(tmp, tmp + 1, strlen(tmp + 1) + 1);
tmp[0] = '\n';
}
}
#endif
altered |= substituted; altered |= substituted;
if (!be_quiet && altered && ((sed_cmd->linear == NULL) || (sed_cmd->linear->cmd != 's'))) { if (!be_quiet && altered && ((sed_cmd->linear == NULL) || (sed_cmd->linear->cmd != 's'))) {
force_print = 1; force_print = 1;
@ -857,11 +895,13 @@ static void process_file(FILE *file)
linenum++; linenum++;
break; break;
case 'N': /* Append the next line to the current line */ case 'N': /* Append the next line to the current line */
line = realloc(line, strlen(line) + strlen(next_line) + 2); if (next_line) {
strcat(line, "\n"); line = realloc(line, strlen(line) + strlen(next_line) + 2);
strcat(line, next_line); strcat(line, "\n");
next_line = bb_get_chomped_line_from_file(file); strcat(line, next_line);
linenum++; next_line = bb_get_chomped_line_from_file(file);
linenum++;
}
break; break;
case 'b': case 'b':
sed_cmd = branch_to(sed_cmd->label); sed_cmd = branch_to(sed_cmd->label);
@ -934,9 +974,12 @@ extern int sed_main(int argc, char **argv)
case 'n': case 'n':
be_quiet++; be_quiet++;
break; break;
case 'e': case 'e': {
add_cmd_str(optarg); char *str_cmd = strdup(optarg);
add_cmd_str(str_cmd);
free(str_cmd);
break; break;
}
case 'f': case 'f':
load_cmd_file(optarg); load_cmd_file(optarg);
break; break;
@ -951,7 +994,9 @@ extern int sed_main(int argc, char **argv)
if (argv[optind] == NULL) if (argv[optind] == NULL)
bb_show_usage(); bb_show_usage();
else { else {
add_cmd_str(argv[optind]); char *str_cmd = strdup(argv[optind]);
add_cmd_str(strdup(str_cmd));
free(str_cmd);
optind++; optind++;
} }
} }