changeset 1620:6f7ed6316d90 draft

Another sed bug. (The e2fsprogs build uses multiple line continuations on the same command.)
author Rob Landley <rob@landley.net>
date Sun, 21 Dec 2014 23:17:06 -0600
parents a7e4dc024bbb
children 53bfe8ac762b
files tests/sed.test toys/posix/sed.c
diffstat 2 files changed, 13 insertions(+), 13 deletions(-) [+]
line wrap: on
line diff
--- a/tests/sed.test	Sun Dec 21 01:54:54 2014 -0600
+++ b/tests/sed.test	Sun Dec 21 23:17:06 2014 -0600
@@ -75,6 +75,8 @@
 testing "sed c {range}" "sed -e '2,4{c blah' -e '}'" \
 	"one\nblah\nblah\nblah\nfive\nsix" \
         "" "one\ntwo\nthree\nfour\nfive\nsix"
+testing "sed c multiple continuation" \
+	"sed -e 'c\\' -e 'two\\' -e ''" "two\n\n" "" "hello"
 testing "sed D further processing depends on whether line is blank" \
 	"sed -e '/one/,/three/{' -e 'i meep' -e'N;2D;}'" \
 	"meep\nmeep\ntwo\nthree\n" "" "one\ntwo\nthree\n"
--- a/toys/posix/sed.c	Sun Dec 21 01:54:54 2014 -0600
+++ b/toys/posix/sed.c	Sun Dec 21 23:17:06 2014 -0600
@@ -753,6 +753,7 @@
   int i;
 
   // Append additional line to pattern argument string?
+  // We temporarily repurpose "hit" to indicate line continuations
   if (corwin && corwin->prev->hit) {
     // Remove half-finished entry from list so remalloc() doesn't confuse it
     TT.pattern = TT.pattern->prev;
@@ -917,33 +918,30 @@
       reg = extend_string((void *)&corwin, s, reg-(char*)corwin, len);
       free(s);
     } else if (strchr("abcirtTw:", c)) {
-      int end, class;
+      int end;
 
       // Trim whitespace from "b ;" and ": blah " but only first space in "w x "
 
-      while (isspace(*line)) {
-        if (!strchr("btT", c) || *line != '\n') line++;
-        else break;
-      }
+      while (isspace(*line) && *line != '\n') line++;
 append:
-      class = !strchr("btT:", c);
-      end = strcspn(line, class ? "\n" : "; \t\r\n\v\f");
-
-      if (!end) {
-        if (!strchr("btT", c)) break;
-        continue;
+      if (!(end = strcspn(line, strchr("btT:", c) ? "; \t\r\n\v\f" : "\n"))) {
+        if (strchr("btT", c)) continue;
+        else if (!corwin->arg1) break;
       }
 
       // Extend allocation to include new string. We use offsets instead of
       // pointers so realloc() moving stuff doesn't break things. Do it
       // here instead of toybuf so there's no maximum size.
       if (!corwin->arg1) corwin->arg1 = reg - (char*)corwin;
-      reg = extend_string((void *)&corwin, line, reg - (char *)corwin, end); 
+      else if ((corwin+1) != (void *)reg) *(reg++) = '\n';
+      reg = extend_string((void *)&corwin, line, reg - (char *)corwin, end);
+
       line += end;
 
       // Line continuation? (Two slightly different input methods, -e with
       // embedded newline vs -f line by line. Must parse both correctly.)
-      if (class && line[-1] == '\\') {
+      if (!strchr("btT:", c) && line[-1] == '\\') {
+        // reg is next available space, so reg[-1] is the null terminator
         reg[-2] = 0;
         if (*line && line[1]) {
           reg -= 2;