sed: fix very obscure case of escaped newline in sed command
authorDenis Vlasenko <vda.linux@googlemail.com>
Fri, 16 Mar 2007 23:36:58 +0000 (23:36 -0000)
committerDenis Vlasenko <vda.linux@googlemail.com>
Fri, 16 Mar 2007 23:36:58 +0000 (23:36 -0000)
(needed for uclibc build, btw). Add testcase for it.

editors/sed.c
testsuite/sed.tests

index c434eee1bf8f641229cb893565802164be76ac02..f7f22f750c36929135553c888f4dca0ecd8ff3d6 100644 (file)
@@ -1175,21 +1175,38 @@ restart:
 }
 
 /* It is possible to have a command line argument with embedded
-   newlines.  This counts as multiple command lines. */
+ * newlines.  This counts as multiple command lines.
+ * However, newline can be escaped: 's/e/z\<newline>z/'
+ * We check for this.
+ */
 
 static void add_cmd_block(char *cmdstr)
 {
-       int go = 1;
-       char *temp = xstrdup(cmdstr), *temp2 = temp;
-
-       while (go) {
-               int len = strcspn(temp2, "\n");
-               if (!temp2[len]) go = 0;
-               else temp2[len] = 0;
-               add_cmd(temp2);
-               temp2 += len+1;
-       }
-       free(temp);
+       char *sv, *eol;
+
+       cmdstr = sv = xstrdup(cmdstr);
+       do {
+               eol = strchr(cmdstr, '\n');
+ next:
+               if (eol) {
+                       /* Count preceding slashes */
+                       int slashes = 0;
+                       char *sl = eol;
+
+                       while (sl != cmdstr && *--sl == '\\')
+                               slashes++;
+                       /* Odd number of preceding slashes - newline is escaped */
+                       if (slashes & 1) {
+                               strcpy(eol-1, eol);
+                               eol = strchr(eol, '\n');
+                               goto next;
+                       }
+                       *eol = '\0';
+               }
+               add_cmd(cmdstr);
+               cmdstr = eol + 1;
+       } while (eol);
+       free(sv);
 }
 
 static void add_cmds_link(llist_t *opt_e)
index 9576b6c4babbf87844aef99ec5108bfadd767dc3..a054de6d7f1d8557d464215e4c5bf3562d9242d7 100755 (executable)
@@ -146,6 +146,10 @@ rm outputw
 testing "sed trailing NUL" \
        "sed 's/i/z/' input -" \
        "a\0b\0\nc" "a\0b\0" "c"
+testing "sed escaped newline in command" \
+       "sed 's/a/z\\
+z/' input" \
+       "z\nz" "a" ""
 
 # Test end-of-file matching behavior