coreutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: pr: floating-point error


From: Pádraig Brady
Subject: Re: pr: floating-point error
Date: Wed, 24 Oct 2012 10:26:13 +0100
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:13.0) Gecko/20120615 Thunderbird/13.0.1

On 10/24/2012 09:03 AM, Ondrej Oprala wrote:
Hello,
one of our customers made a bug report, stating that pr -nNUM FILE
causes a floating point exception if NUM >= 32
and I would really like to hear your opinion on how to solve this.
The easiest solution would be to document the <32 limit for the -n option.
The more difficult one would be to support numbers of arbitrary length.
I was thinking about the second solution and  AFAIK the line number is not
used in any arithmetic (apart from incrementation), so it could be represented 
as
an array of digits, with a function incrementing the array from the rightmost 
element
as needed. Then we would just print out the array one element at a time. It 
would
probably cause a performance penalty though.
Thanks in advance for any advice or suggestions.

Ouch. Confirmed that this dumps core:

  echo . | pr -T -n.32

We can fix that up with something like the following.
I'll add a test and commit.

cheers,
Pádraig.

diff --git a/src/pr.c b/src/pr.c
index e97c434..3fada19 100644
--- a/src/pr.c
+++ b/src/pr.c
@@ -630,10 +630,6 @@ static uintmax_t page_number;
    2    moo     4       hoo     6       zoo */
 static int line_number;

-/* With line_number overflow, we use power_10 to cut off the higher-order
-   digits of the line_number */
-static int power_10;
-
 /* (-n) True means lines should be preceded by numbers. */
 static bool numbered_lines = false;

@@ -1289,12 +1285,6 @@ init_parameters (int number_of_files)
          printing files in parallel. */
       if (parallel_files)
         chars_used_by_number = number_width;
-
-      /* We use power_10 to cut off the higher-order digits of the
-         line_number in function add_line_number */
-      tmp_i = chars_per_number;
-      for (power_10 = 1; tmp_i > 0; --tmp_i)
-        power_10 = 10 * power_10;
     }

   chars_per_column = (chars_per_line - chars_used_by_number
@@ -1306,7 +1296,8 @@ init_parameters (int number_of_files)
   if (numbered_lines)
     {
       free (number_buff);
-      number_buff = xmalloc (2 * chars_per_number);
+      number_buff = xmalloc (MAX (chars_per_number,
+                                  INT_BUFSIZE_BOUND (line_number)) + 1);
     }

   /* Pick the maximum between the tab width and the width of an
@@ -2029,19 +2020,13 @@ add_line_number (COLUMN *p)
 {
   int i;
   char *s;
-  int left_cut;
+  int num_width;

   /* Cutting off the higher-order digits is more informative than
-     lower-order cut off*/
-  if (line_number < power_10)
-    sprintf (number_buff, "%*d", chars_per_number, line_number);
-  else
-    {
-      left_cut = line_number % power_10;
-      sprintf (number_buff, "%0*d", chars_per_number, left_cut);
-    }
+     lower-order cut off. */
+  num_width = sprintf (number_buff, "%*d", chars_per_number, line_number);
   line_number++;
-  s = number_buff;
+  s = number_buff + (num_width - chars_per_number);
   for (i = chars_per_number; i > 0; i--)
     (p->char_func) (*s++);




reply via email to

[Prev in Thread] Current Thread [Next in Thread]