Another sed bug. (The e2fsprogs build uses multiple line continuations on the same...
authorRob Landley <rob@landley.net>
Mon, 22 Dec 2014 05:17:06 +0000 (23:17 -0600)
committerRob Landley <rob@landley.net>
Mon, 22 Dec 2014 05:17:06 +0000 (23:17 -0600)
tests/sed.test
toys/posix/sed.c

index 789a1a5..dfc7602 100644 (file)
@@ -75,6 +75,8 @@ testing "sed c range" "sed '2,4c blah'" "one\nblah\nfive\nsix" "" \
 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"
index 7f07020..65a6fe0 100644 (file)
@@ -753,6 +753,7 @@ static void jewel_of_judgement(char **pline, long len)
   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 @@ writenow:
       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;