]> git.ipfire.org Git - thirdparty/coreutils.git/commitdiff
seq: handle exponents more consistently
authorPádraig Brady <P@draigBrady.com>
Tue, 23 Jun 2015 21:51:24 +0000 (22:51 +0100)
committerPádraig Brady <P@draigBrady.com>
Wed, 24 Jun 2015 16:04:01 +0000 (17:04 +0100)
src/seq.c (scan_arg): Set precision and width _after_ exponentiation.
For example, this will make '1.1e1 12' and '11 1.2e1' equivalent.
One can still set the precision by specifying extra precision on
the start value, or more naturally with a precision on a step value.
* tests/misc/seq-precision.sh: Add new cases.

src/seq.c
tests/misc/seq-precision.sh

index 95e6cd639cd1302b073fc7ecd4acde6e0233eae8..2426c4de386711dbcaf5a62d5b8591cf610f430f 100644 (file)
--- a/src/seq.c
+++ b/src/seq.c
@@ -147,20 +147,24 @@ scan_arg (const char *arg)
   while (isspace (to_uchar (*arg)) || *arg == '+')
     arg++;
 
+  /* Default to auto width and precision.  */
   ret.width = 0;
   ret.precision = INT_MAX;
 
+  /* Use no precision (and possibly fast generation) for integers.  */
   char const *decimal_point = strchr (arg, '.');
   if (! decimal_point && ! strchr (arg, 'p') /* not a hex float */)
     ret.precision = 0;
 
+  /* auto set width and precision for decimal inputs.  */
   if (! arg[strcspn (arg, "xX")] && isfinite (ret.value))
     {
+      size_t fraction_len = 0;
       ret.width = strlen (arg);
 
       if (decimal_point)
         {
-          size_t fraction_len = strcspn (decimal_point + 1, "eE");
+          fraction_len = strcspn (decimal_point + 1, "eE");
           if (fraction_len <= INT_MAX)
             ret.precision = fraction_len;
           ret.width += (fraction_len == 0                      /* #.  -> #   */
@@ -174,7 +178,8 @@ scan_arg (const char *arg)
       if (e)
         {
           long exponent = strtol (e + 1, NULL, 10);
-          ret.precision += exponent < 0 ? -exponent : 0;
+          ret.precision += exponent < 0 ? -exponent
+                                        : - MIN (ret.precision, exponent);
           /* Don't account for e.... in the width since this is not output.  */
           ret.width -= strlen (arg) - (e - arg);
           /* Adjust the width as per the exponent.  */
@@ -189,6 +194,12 @@ scan_arg (const char *arg)
                 ret.width++;
               exponent = -exponent;
             }
+          else
+            {
+              if (decimal_point && ret.precision == 0 && fraction_len)
+                ret.width--; /* discount space for '.'  */
+              exponent -= MIN (fraction_len, exponent);
+            }
           ret.width += exponent;
         }
     }
index e6a2bd7b81b4c3fa85714d5b2791ca920aeb1f0b..b8382ca19c816cec8c7725f656f4be8348a57909 100755 (executable)
@@ -58,4 +58,22 @@ seq 1 .1 0x2 | head -n2 > out || fail=1
 printf "%s\n" 1.0 1.1 > exp || framework_failure_
 compare exp out || fail=1
 
+# Ensure consistent handling of precision/width for exponents
+
+seq 1.1e1 12 > out || fail=1
+printf "%s\n" 11 12 > exp || framework_failure_
+compare exp out || fail=1
+
+seq 11 1.2e1 > out || fail=1
+printf "%s\n" 11 12 > exp || framework_failure_
+compare exp out || fail=1
+
+seq -w 1.1e4 | head -n1 > out || fail=1
+printf "%s\n" 00001 > exp || framework_failure_
+compare exp out || fail=1
+
+seq -w 1.10000e5 1.10000e5 > out || fail=1
+printf "%s\n" 110000 > exp || framework_failure_
+compare exp out || fail=1
+
 Exit $fail