Subject: Re: bug#13227: seq -s broken in coretutils 8.20?
From: Pádraig Brady <[email-masked]>
To: Philipp Gortan <[email-masked]>
Cc: [email-masked]
Date: Thu, 20 Dec 2012 00:33:05 +0000
List-Id: <debbugs-submit.debbugs.gnu.org>

On 12/19/2012 07:01 PM, Pádraig Brady wrote:
> On 12/19/2012 04:53 PM, Philipp Gortan wrote:
>> Dear coreutils crowd,
>>
>> I recently upgraded the coreutils on my Gentoo AMD64 from 8.16 to 8.20.
>> I used the seq command to generate the values of an SQL "in" statement.
>> Since I upgraded, the SQL is no longer correct - here is what I found out:
>>
>> $ seq -s, 6 9; seq --version
>>
>> 6
>> 7,8,9,seq (GNU coreutils) 8.20
>> ...
>>
>> (nb: newline after the "6", the comma after the 9 and the missing newline)

The attached should fix it.

thanks,
Pádraig.
From 9d9cdfd5df898ade2e680aab5ce37fcd0032c687 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?P=C3=A1draig=20Brady?= <[email-masked]>
Date: Wed, 19 Dec 2012 19:27:10 +0000
Subject: [PATCH] seq: fix newline output when -s specified

This regression was introduced in commit v8.19-132-g3786fb6.

* src/seq.c (seq_fast): Don't use puts() to output the first number,
and instead insert it into the buffer as for other numbers.
Also output the terminator unconditionally.
* tests/misc/seq.pl: Add some basic tests for the -s option.
* NEWS: Mention the fix.
* THANKS.in: Reported by Philipp Gortan.
---
 NEWS              |    4 ++++
 THANKS.in         |    1 +
 src/seq.c         |   20 +++++++++++++-------
 tests/misc/seq.pl |    5 +++++
 4 files changed, 23 insertions(+), 7 deletions(-)

diff --git a/NEWS b/NEWS
index e4472df..ae7ec2a 100644
--- a/NEWS
+++ b/NEWS
@@ -43,6 +43,10 @@ GNU coreutils NEWS                                    -*- outline -*-
   the output numbers are properly aligned and of the correct width.
   [This bug was present in "the beginning".]
 
+  seq -s now doesn't output an erroneous newline after the first number, and
+  outputs a newline after the last number rather than a trailing separator.
+  [bug introduced in coreutils-8.20]
+
 ** Changes in behavior
 
   df --total now prints '-' into the target column (mount point) of the
diff --git a/THANKS.in b/THANKS.in
index c2651e7..67b60b9 100644
--- a/THANKS.in
+++ b/THANKS.in
@@ -505,6 +505,7 @@ Phil Richards                       [email-masked]
 Philippe De Muyter                  [email-masked]
 Philippe Schnoebelen                [email-masked]
 Phillip Jones                       [email-masked]
+Philipp Gortan                      [email-masked]
 Philipp Thomas                      [email-masked]
 Piergiorgio Sartor                  [email-masked]
 Pieter Bowman                       [email-masked]
diff --git a/src/seq.c b/src/seq.c
index 9c2c51f..108808b 100644
--- a/src/seq.c
+++ b/src/seq.c
@@ -419,30 +419,36 @@ seq_fast (char const *a, char const *b)
   bool ok = cmp (p, p_len, q, q_len) <= 0;
   if (ok)
     {
-      /* Buffer at least this many output lines per fwrite call.
+      /* Buffer at least this many numbers per fwrite call.
          This gives a speed-up of more than 2x over the unbuffered code
          when printing the first 10^9 integers.  */
       enum {N = 40};
       char *buf = xmalloc (N * (n + 1));
       char const *buf_end = buf + N * (n + 1);
 
-      puts (p);
       char *z = buf;
+
+      /* Write first number to buffer.  */
+      z = mempcpy (z, p, p_len);
+
+      /* Append separator then number.  */
       while (cmp (p, p_len, q, q_len) < 0)
         {
+          *z++ = *separator;
           incr (&p, &p_len);
           z = mempcpy (z, p, p_len);
-          *z++ = *separator;
-          if (buf_end - n - 1 < z)
+          /* If no place for another separator + number then
+             output buffer so far, and reset to start of buffer.  */
+          if (buf_end - (n + 1) < z)
             {
               fwrite (buf, z - buf, 1, stdout);
               z = buf;
             }
         }
 
-      /* Write any remaining, buffered output.  */
-      if (buf < z)
-        fwrite (buf, z - buf, 1, stdout);
+      /* Write any remaining buffered output, and the terminator.  */
+      *z++ = *terminator;
+      fwrite (buf, z - buf, 1, stdout);
 
       IF_LINT (free (buf));
     }
diff --git a/tests/misc/seq.pl b/tests/misc/seq.pl
index 447baa4..416b839 100755
--- a/tests/misc/seq.pl
+++ b/tests/misc/seq.pl
@@ -128,6 +128,11 @@ my @Tests =
    ['long-leading-zeros2', qw(000 02), {OUT => [qw(0 1 2)]}],
    ['long-leading-zeros3', qw(00 02), {OUT => [qw(0 1 2)]}],
    ['long-leading-zeros4', qw(0 02), {OUT => [qw(0 1 2)]}],
+
+   # Exercise the -s option, which was broken in 8.20
+   ['sep-1', qw(-s, 1 3), {OUT => [qw(1,2,3)]}],
+   ['sep-2', qw(-s, 1 1), {OUT => [qw(1)]}],
+   ['sep-3', qw(-s,, 1 3), {OUT => [qw(1,,2,,3)]}],
   );
 
 # Append a newline to each entry in the OUT array.
-- 
1.7.6.4