Fixes block commands to correctly identify end of block, recognise the #n directive, fix substitue command when regex isnt specified

This commit is contained in:
Glenn L McGrath 2003-04-08 06:42:45 +00:00
parent 7ce9e247f0
commit c1d95076f0

View File

@ -119,8 +119,11 @@ typedef struct sed_cmd_s {
/* linked list of sed commands */
static sed_cmd_t sed_cmd_head;
static sed_cmd_t *sed_cmd_tail = &sed_cmd_head;
static sed_cmd_t *block_cmd;
static int in_block = 0;
const char * const semicolon_whitespace = "; \n\r\t\v\0";
static regex_t *previous_regex_ptr = NULL;
#ifdef CONFIG_FEATURE_CLEAN_UP
static void destroy_cmd_strs(void)
@ -245,6 +248,7 @@ static int get_address(char *my_str, int *linenum, regex_t **regex)
bb_error_msg_and_die("unterminated match expression");
}
my_str[idx] = '\0';
*regex = (regex_t *)xmalloc(sizeof(regex_t));
xregcomp(*regex, my_str+idx_start, REG_NEWLINE);
idx++; /* so it points to the next character after the last '/' */
@ -305,8 +309,11 @@ static int parse_subst_cmd(sed_cmd_t * const sed_cmd, const char *substr)
out:
/* compile the match string into a regex */
sed_cmd->sub_match = (regex_t *)xmalloc(sizeof(regex_t));
xregcomp(sed_cmd->sub_match, match, cflags);
if (*match != '\0') {
/* If match is empty, we use last regex used at runtime */
sed_cmd->sub_match = (regex_t *)xmalloc(sizeof(regex_t));
xregcomp(sed_cmd->sub_match, match, cflags);
}
free(match);
return idx;
@ -493,8 +500,19 @@ static char *add_cmd(sed_cmd_t *sed_cmd, char *cmdstr)
/* if this is a comment, jump past it and keep going */
if (*cmdstr == '#') {
/* "#n" is the same as using -n on the command line */
if (cmdstr[1] == 'n') {
be_quiet++;
}
return(strpbrk(cmdstr, "\n\r"));
}
/* Test for end of block */
if (*cmdstr == '}') {
in_block = 0;
cmdstr++;
return(cmdstr);
}
/* parse the command
* format is: [addr][,addr]cmd
@ -548,32 +566,34 @@ static char *add_cmd(sed_cmd_t *sed_cmd, char *cmdstr)
if (*cmdstr == '\0')
bb_error_msg_and_die("missing command");
/* This is the start of a block of commands */
if (*cmdstr == '{') {
if (in_block != 0) {
bb_error_msg_and_die("cant handle sub-blocks");
}
in_block = 1;
block_cmd = sed_cmd;
return(cmdstr + 1);
}
sed_cmd->cmd = *cmdstr;
cmdstr++;
if (sed_cmd->cmd == '{') {
do {
sed_cmd_t *sed_cmd_new;
char *end_ptr = strpbrk(cmdstr, ";}");
*end_ptr = '\0';
sed_cmd_new = xcalloc(1, sizeof(sed_cmd_t));
sed_cmd_new->beg_match = sed_cmd->beg_match;
sed_cmd_new->end_match = sed_cmd->end_match;
sed_cmd_new->beg_line = sed_cmd->beg_line;
sed_cmd_new->end_line = sed_cmd->end_line;
sed_cmd_new->invert = sed_cmd->invert;
add_cmd(sed_cmd_new, cmdstr);
cmdstr = end_ptr + 1;
} while (*cmdstr != '\0');
} else {
cmdstr = parse_cmd_str(sed_cmd, cmdstr);
/* Add the command to the command array */
sed_cmd_tail->linear = sed_cmd;
sed_cmd_tail = sed_cmd_tail->linear;
if (in_block == 1) {
sed_cmd->beg_match = block_cmd->beg_match;
sed_cmd->end_match = block_cmd->end_match;
sed_cmd->beg_line = block_cmd->beg_line;
sed_cmd->end_line = block_cmd->end_line;
sed_cmd->invert = block_cmd->invert;
}
cmdstr = parse_cmd_str(sed_cmd, cmdstr);
/* Add the command to the command array */
sed_cmd_tail->linear = sed_cmd;
sed_cmd_tail = sed_cmd_tail->linear;
return(cmdstr);
}
@ -700,17 +720,27 @@ static void print_subst_w_backrefs(const char *line, const char *replace,
}
}
static int do_subst_command(const sed_cmd_t *sed_cmd, char **line)
static int do_subst_command(sed_cmd_t *sed_cmd, char **line)
{
char *hackline = *line;
struct pipeline thepipe = { NULL, 0 , 0};
struct pipeline *const pipeline = &thepipe;
int altered = 0;
int result;
regmatch_t *regmatch = NULL;
regex_t *current_regex;
if (sed_cmd->sub_match == NULL) {
current_regex = previous_regex_ptr;
} else {
previous_regex_ptr = current_regex = sed_cmd->sub_match;
}
result = regexec(current_regex, hackline, 0, NULL, 0);
/* we only proceed if the substitution 'search' expression matches */
if (regexec(sed_cmd->sub_match, hackline, 0, NULL, 0) == REG_NOMATCH)
if (result == REG_NOMATCH) {
return 0;
}
/* whaddaya know, it matched. get the number of back references */
regmatch = xmalloc(sizeof(regmatch_t) * (sed_cmd->num_backrefs+1));
@ -724,7 +754,7 @@ static int do_subst_command(const sed_cmd_t *sed_cmd, char **line)
/* and now, as long as we've got a line to try matching and if we can match
* the search string, we make substitutions */
while ((*hackline || !altered) && (regexec(sed_cmd->sub_match, hackline,
while ((*hackline || !altered) && (regexec(current_regex, hackline,
sed_cmd->num_backrefs+1, regmatch, 0) != REG_NOMATCH) ) {
int i;
@ -818,6 +848,10 @@ static void process_file(FILE *file)
);
if (sed_cmd->invert ^ matched) {
/* Update last used regex incase a blank substitute BRE is found */
if (sed_cmd->beg_match) {
previous_regex_ptr = sed_cmd->beg_match;
}
/*
* actual sedding
@ -999,6 +1033,8 @@ static void process_file(FILE *file)
if (
/* this is a single-address command or... */
(sed_cmd->end_line == 0 && sed_cmd->end_match == NULL) || (
/* If only one address */
/* we were in the middle of our address range (this
* isn't the first time through) and.. */
(still_in_range == 1) && (