sed: deal with peculiar behavior of '2d;2,1p' in GNU sed
authorDenys Vlasenko <vda.linux@googlemail.com>
Fri, 10 Jul 2009 09:55:20 +0000 (11:55 +0200)
committerDenys Vlasenko <vda.linux@googlemail.com>
Fri, 10 Jul 2009 09:55:20 +0000 (11:55 +0200)
function                                             old     new   delta
process_files                                       2173    2120     -53

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
editors/sed.c
testsuite/sed.tests

index 2127301d59a3289d47f45da6a98a5e8d0784701d..ed12e43365244dc78ab912647e2f7d00f780ef88 100644 (file)
@@ -894,12 +894,13 @@ static void process_files(void)
                        || (!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
-                                                       /* "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)
-                                               )
+                       || (sed_cmd->beg_line > 0
+                           && (sed_cmd->beg_line == linenum
+                              /* GNU sed compat:
+                               * "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->beg_line < linenum && (sed_cmd->end_line > 0 || sed_cmd->end_match))
+                              )
                        )
                        /* Or does this line match our begin address regex? */
                        || (beg_match(sed_cmd, pattern_space))
@@ -928,12 +929,10 @@ static void process_files(void)
                                     && (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;
-                               }
+                       }
+                       if (n && sed_cmd->beg_line > 0) {
+                               /* once matched, "n,xxx" range is dead, disabling it */
+                               sed_cmd->beg_line = -2;
                        }
                        sed_cmd->in_match = !n;
                }
index 8af156ae9f18b6fd36eb8be01a64c3446cb3f0c3..677303be1fb6d94ec7bd3a660428895cb1dbd3c9 100755 (executable)
@@ -220,4 +220,9 @@ testing "sed d does not break n,regex matching #2" \
        "second2\nthird2\n" "" \
        "first\nsecond\nthird\nfourth\n""first2\nsecond2\nthird2\nfourth2\n"
 
+testing "sed 2d;2,1p (gnu compat)" \
+       "sed -n '2d;2,1p'" \
+       "third\n" "" \
+       "first\nsecond\nthird\nfourth\n"
+
 exit $FAILCOUNT