mirror of
https://github.com/sheumann/hush.git
synced 2024-12-27 01:32:08 +00:00
sed: fix handling of 1d;1,3p and 1d;1,REGEXp
function old new delta process_files 2084 2173 +89 Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
parent
f1fab09242
commit
8bca3e20b9
@ -865,63 +865,80 @@ static void process_files(void)
|
||||
/* Prime the pump */
|
||||
next_line = get_next_line(&next_gets_char);
|
||||
|
||||
/* go through every line in each file */
|
||||
/* Go through every line in each file */
|
||||
again:
|
||||
substituted = 0;
|
||||
|
||||
/* Advance to next line. Stop if out of lines. */
|
||||
pattern_space = next_line;
|
||||
if (!pattern_space) return;
|
||||
if (!pattern_space)
|
||||
return;
|
||||
last_gets_char = next_gets_char;
|
||||
|
||||
/* Read one line in advance so we can act on the last line,
|
||||
* the '$' address */
|
||||
next_line = get_next_line(&next_gets_char);
|
||||
linenum++;
|
||||
|
||||
/* For every line, go through all the commands */
|
||||
restart:
|
||||
/* for every line, go through all the commands */
|
||||
for (sed_cmd = G.sed_cmd_head.next; sed_cmd; sed_cmd = sed_cmd->next) {
|
||||
int old_matched, matched;
|
||||
|
||||
old_matched = sed_cmd->in_match;
|
||||
|
||||
/* Determine if this command matches this line: */
|
||||
|
||||
/* Are we continuing a previous multi-line match? */
|
||||
sed_cmd->in_match = sed_cmd->in_match
|
||||
/* Or is no range necessary? */
|
||||
|| (!sed_cmd->beg_line && !sed_cmd->end_line
|
||||
&& !sed_cmd->beg_match && !sed_cmd->end_match)
|
||||
/* Or did we match the start of a numerical range? */
|
||||
|| (sed_cmd->beg_line > 0 && (sed_cmd->beg_line == linenum))
|
||||
|| (sed_cmd->beg_line > 0 && (sed_cmd->beg_line == linenum
|
||||
/* "shadowed beginning" case: "1d;1,ENDp" - p still matches at line 2
|
||||
* even though 1d skipped line 1 which is a start line for p */
|
||||
|| (sed_cmd->end_line && sed_cmd->beg_line < linenum && sed_cmd->end_line >= linenum)
|
||||
|| (sed_cmd->end_match && sed_cmd->beg_line < linenum)
|
||||
)
|
||||
)
|
||||
/* Or does this line match our begin address regex? */
|
||||
|| (beg_match(sed_cmd, pattern_space))
|
||||
/* Or did we match last line of input? */
|
||||
|| (sed_cmd->beg_line == -1 && next_line == NULL);
|
||||
|
||||
/* Snapshot the value */
|
||||
|
||||
matched = sed_cmd->in_match;
|
||||
|
||||
/* Is this line the end of the current match? */
|
||||
//bb_error_msg("cmd:'%c' matched:%d beg_line:%d end_line:%d linenum:%d",
|
||||
//sed_cmd->cmd, matched, sed_cmd->beg_line, sed_cmd->end_line, linenum);
|
||||
|
||||
/* Is this line the end of the current match? */
|
||||
if (matched) {
|
||||
sed_cmd->in_match = !(
|
||||
int n = (
|
||||
/* has the ending line come, or is this a single address command? */
|
||||
(sed_cmd->end_line ?
|
||||
sed_cmd->end_line ?
|
||||
sed_cmd->end_line == -1 ?
|
||||
!next_line
|
||||
: (sed_cmd->end_line <= linenum)
|
||||
: !sed_cmd->end_match
|
||||
)
|
||||
/* or does this line matches our last address regex */
|
||||
|| (sed_cmd->end_match && old_matched
|
||||
&& (regexec(sed_cmd->end_match,
|
||||
pattern_space, 0, NULL, 0) == 0))
|
||||
);
|
||||
if (!n) {
|
||||
/* or does this line matches our last address regex */
|
||||
n = (sed_cmd->end_match
|
||||
&& old_matched
|
||||
&& (regexec(sed_cmd->end_match,
|
||||
pattern_space, 0, NULL, 0) == 0)
|
||||
);
|
||||
if (n && sed_cmd->beg_line > 0) {
|
||||
/* Once matched, "n,regex" range is dead, disabling it */
|
||||
regfree(sed_cmd->end_match);
|
||||
free(sed_cmd->end_match);
|
||||
sed_cmd->end_match = NULL;
|
||||
}
|
||||
}
|
||||
sed_cmd->in_match = !n;
|
||||
}
|
||||
|
||||
/* Skip blocks of commands we didn't match. */
|
||||
/* Skip blocks of commands we didn't match */
|
||||
if (sed_cmd->cmd == '{') {
|
||||
if (sed_cmd->invert ? matched : !matched) {
|
||||
while (sed_cmd->cmd != '}') {
|
||||
@ -934,7 +951,9 @@ static void process_files(void)
|
||||
}
|
||||
|
||||
/* Okay, so did this line match? */
|
||||
if (sed_cmd->invert ? !matched : matched) {
|
||||
if (sed_cmd->invert ? matched : !matched)
|
||||
continue; /* no */
|
||||
|
||||
/* Update last used regex in case a blank substitute BRE is found */
|
||||
if (sed_cmd->beg_match) {
|
||||
G.previous_regex_ptr = sed_cmd->beg_match;
|
||||
@ -1175,12 +1194,11 @@ static void process_files(void)
|
||||
G.hold_space = tmp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} /* switch */
|
||||
} /* for each cmd */
|
||||
|
||||
/*
|
||||
* exit point from sedding...
|
||||
* Exit point from sedding...
|
||||
*/
|
||||
discard_commands:
|
||||
/* we will print the line unless we were told to be quiet ('-n')
|
||||
|
@ -207,4 +207,17 @@ testing "sed n command must reset 'substituted' bit" \
|
||||
"sed 's/1/x/;T;n;: next;s/3/y/;t quit;n;b next;: quit;q'" \
|
||||
"0\nx\n2\ny\n" "" "0\n1\n2\n3\n"
|
||||
|
||||
testing "sed d does not break n,m matching" \
|
||||
"sed -n '1d;1,3p'" \
|
||||
"second\nthird\n" "" "first\nsecond\nthird\nfourth\n"
|
||||
|
||||
testing "sed d does not break n,regex matching" \
|
||||
"sed -n '1d;1,/hir/p'" \
|
||||
"second\nthird\n" "" "first\nsecond\nthird\nfourth\n"
|
||||
|
||||
testing "sed d does not break n,regex matching #2" \
|
||||
"sed -n '1,5d;1,/hir/p'" \
|
||||
"second2\nthird2\n" "" \
|
||||
"first\nsecond\nthird\nfourth\n""first2\nsecond2\nthird2\nfourth2\n"
|
||||
|
||||
exit $FAILCOUNT
|
||||
|
Loading…
Reference in New Issue
Block a user