Experimental support for embeded newline. (im evil)
Fix segfault when using 'N' with an odd number of lines.
This commit is contained in:
parent
b5b5ac3237
commit
0c51832b60
@ -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
|
||||||
|
@ -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++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user