diff options
-rw-r--r-- | editors/sed.c | 67 |
1 files changed, 25 insertions, 42 deletions
diff --git a/editors/sed.c b/editors/sed.c index d90d63e43..bda359219 100644 --- a/editors/sed.c +++ b/editors/sed.c @@ -68,6 +68,13 @@ typedef struct sed_cmd_s { regex_t *beg_match; /* sed -e '/match/cmd' */ regex_t *end_match; /* sed -e '/match/,/end_match/cmd' */ + int beg_line; /* 'sed 1p' 0 == no begining line, apply commands to all lines */ + int end_line; /* 'sed 1,3p' 0 == no end line, use only beginning. -1 == $ */ + + /* inversion flag */ + int invert; /* the '!' after the address */ +// int block_cmd; /* This command is part of a group that has a command address */ + /* SUBSTITUTION COMMAND SPECIFIC FIELDS */ /* sed -e 's/sub_match/replace/' */ @@ -80,9 +87,6 @@ typedef struct sed_cmd_s { /* FILE COMMAND (r) SPECIFIC FIELDS */ char *filename; - /* address storage */ - int beg_line; /* 'sed 1p' 0 == no begining line, apply commands to all lines */ - int end_line; /* 'sed 1,3p' 0 == no end line, use only beginning. -1 == $ */ /* SUBSTITUTION COMMAND SPECIFIC FIELDS */ unsigned int num_backrefs:4; /* how many back references (\1..\9) */ @@ -98,9 +102,6 @@ typedef struct sed_cmd_s { /* the command */ char cmd; /* p,d,s (add more at your leisure :-) */ - /* inversion flag */ - int invert; /* the '!' after the address */ - /* Branch commands */ char *label; @@ -124,9 +125,7 @@ static const char bad_format_in_subst[] = /* 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; @@ -484,7 +483,7 @@ static char *parse_cmd_str(sed_cmd_t * sed_cmd, char *cmdstr) /* if it wasnt a single-letter command that takes no arguments * then it must be an invalid command. */ - else if (strchr("dghnNpPqx=", sed_cmd->cmd) == 0) { + else if (strchr("dghnNpPqx={}", sed_cmd->cmd) == 0) { bb_error_msg_and_die("Unsupported command %c", sed_cmd->cmd); } @@ -512,13 +511,6 @@ static char *add_cmd(sed_cmd_t * sed_cmd, char *cmdstr) 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 * |----||-----||-| @@ -571,28 +563,9 @@ 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 (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 */ @@ -828,12 +801,14 @@ static void process_file(FILE * file) if (pattern_space == NULL) { return; } - + /* go through every line in the file */ do { char *next_line; sed_cmd_t *sed_cmd; int substituted = 0; + /* This enables whole blocks of commands to be mask'ed out if the lead address doesnt match */ + int block_mask = 1; /* Read one line in advance so we can act on the last line, the '$' address */ next_line = bb_get_chomped_line_from_file(file); @@ -855,7 +830,7 @@ static void process_file(FILE * file) && sed_cmd->beg_match == NULL && sed_cmd->end_match == NULL) || /* this line number is the first address we're looking for */ - (sed_cmd->beg_line && (sed_cmd->beg_line == linenum)) || + (sed_cmd->beg_line > 0 && (sed_cmd->beg_line == linenum)) || /* this line matches our first address regex */ (sed_cmd->beg_match && (regexec(sed_cmd->beg_match, pattern_space, 0, NULL, @@ -865,7 +840,12 @@ static void process_file(FILE * file) && (next_line == NULL)) ); - if (sed_cmd->invert ^ matched) { + if (sed_cmd->cmd == '{') { + block_mask = block_mask & matched; + } +// matched &= block_mask; + + if (sed_cmd->invert ^ (matched & block_mask)) { /* Update last used regex incase a blank substitute BRE is found */ if (sed_cmd->beg_match) { previous_regex_ptr = sed_cmd->beg_match; @@ -1060,11 +1040,10 @@ static void process_file(FILE * file) break; case 'x':{ /* Swap hold and pattern space */ - char *tmp; - - tmp = pattern_space; + char *tmp = pattern_space; pattern_space = hold_space; hold_space = tmp; + break; } } } @@ -1081,7 +1060,7 @@ static void process_file(FILE * file) * isn't the first time through) and.. */ || ((still_in_range == 1) /* this line number is the last address we're looking for or... */ - && ((sed_cmd->end_line + && ((sed_cmd->end_line > 0 && (sed_cmd->end_line == linenum)) /* this line matches our last address regex */ || (sed_cmd->end_match @@ -1095,6 +1074,10 @@ static void process_file(FILE * file) } } + if (sed_cmd->cmd == '}') { + block_mask = 1; + } + if (deleted) break; } |