Author: robak (ports committer)
Date: Tue Jul  3 14:40:19 2018
New Revision: 335890
URL: https://svnweb.freebsd.org/changeset/base/335890

Log:
  MFC r327317:
  
  humanize_number(3): fix math edge case in rounding large numbers
  
  Fix for remainder overflow, when in rare cases adding remainder to divider
  exceeded 1 and turned the total to 1000 in final formatting, taking up
  the space for the unit character.
  
  The fix continues the division of the original number if the above case
  happens -- added the appropriate check to the for loop performing
  the division. This lowers the value shown, to make it fit into the buffer
  space provided (1.0M for 4+1 character buffer, as used by ls).
  
  Add test case for the reported bug and extend test program to support
  providing buffer length (ls -lh uses 5, tests hard-coded 4).
  
  PR:           224498

Modified:
  stable/11/lib/libutil/humanize_number.3
  stable/11/lib/libutil/humanize_number.c
  stable/11/lib/libutil/tests/humanize_number_test.c
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/lib/libutil/humanize_number.3
==============================================================================
--- stable/11/lib/libutil/humanize_number.3     Tue Jul  3 14:32:15 2018        
(r335889)
+++ stable/11/lib/libutil/humanize_number.3     Tue Jul  3 14:40:19 2018        
(r335890)
@@ -200,3 +200,9 @@ The
 .Dv HN_IEC_PREFIXES
 flag was introduced in
 .Fx 9.0 .
+.Sh CAVEATS
+For numbers greater than 999 using buffer length of 4 and less can cause
+rounding errors.
+When using
+.Dv HN_IEC_PREFIXES
+the same error occurs for buffer length of 5 or less.

Modified: stable/11/lib/libutil/humanize_number.c
==============================================================================
--- stable/11/lib/libutil/humanize_number.c     Tue Jul  3 14:32:15 2018        
(r335889)
+++ stable/11/lib/libutil/humanize_number.c     Tue Jul  3 14:40:19 2018        
(r335890)
@@ -143,7 +143,8 @@ humanize_number(char *buf, size_t len, int64_t quotien
                 */
                for (i = 0;
                    (quotient >= max || (quotient == max - 1 &&
-                   remainder >= divisordeccut)) && i < maxscale; i++) {
+                   (remainder >= divisordeccut || remainder >=
+                   divisor / 2))) && i < maxscale; i++) {
                        remainder = quotient % divisor;
                        quotient /= divisor;
                }

Modified: stable/11/lib/libutil/tests/humanize_number_test.c
==============================================================================
--- stable/11/lib/libutil/tests/humanize_number_test.c  Tue Jul  3 14:32:15 
2018        (r335889)
+++ stable/11/lib/libutil/tests/humanize_number_test.c  Tue Jul  3 14:40:19 
2018        (r335890)
@@ -49,333 +49,337 @@ static struct {
        int64_t num;
        int flags;
        int scale;
+       size_t buflen;
 } test_args[] = {
        /* tests 0-13 test 1000 suffixes */
-       { 2, "0 ", (int64_t)0L, HN_DIVISOR_1000, HN_AUTOSCALE },
-       { 3, "1 k", (int64_t)500L, HN_DIVISOR_1000, HN_AUTOSCALE },
-       { 3, "1 M", (int64_t)500*1000L, HN_DIVISOR_1000, HN_AUTOSCALE },
-       { 3, "1 G", (int64_t)500*1000*1000L, HN_DIVISOR_1000, HN_AUTOSCALE },
-       { 3, "1 T", (int64_t)500*1000*1000*1000L, HN_DIVISOR_1000, HN_AUTOSCALE 
},
-       { 3, "1 P", (int64_t)500*1000*1000*1000*1000L, HN_DIVISOR_1000, 
HN_AUTOSCALE },
-       { 3, "1 E", (int64_t)500*1000*1000*1000*1000*1000L, HN_DIVISOR_1000, 
HN_AUTOSCALE },
-       { 2, "1 ", (int64_t)1L, HN_DIVISOR_1000, HN_AUTOSCALE },
-       { 3, "2 k", (int64_t)1500L, HN_DIVISOR_1000, HN_AUTOSCALE },
-       { 3, "2 M", (int64_t)1500*1000L, HN_DIVISOR_1000, HN_AUTOSCALE },
-       { 3, "2 G", (int64_t)1500*1000*1000L, HN_DIVISOR_1000, HN_AUTOSCALE },
-       { 3, "2 T", (int64_t)1500*1000*1000*1000L, HN_DIVISOR_1000, 
HN_AUTOSCALE },
-       { 3, "2 P", (int64_t)1500*1000*1000*1000*1000L, HN_DIVISOR_1000, 
HN_AUTOSCALE },
-       { 3, "2 E", (int64_t)1500*1000*1000*1000*1000*1000L, HN_DIVISOR_1000, 
HN_AUTOSCALE },
+       { 2, "0 ", (int64_t)0L, HN_DIVISOR_1000, HN_AUTOSCALE, 4 },
+       { 3, "1 k", (int64_t)500L, HN_DIVISOR_1000, HN_AUTOSCALE, 4 },
+       { 3, "1 M", (int64_t)500*1000L, HN_DIVISOR_1000, HN_AUTOSCALE, 4 },
+       { 3, "1 G", (int64_t)500*1000*1000L, HN_DIVISOR_1000, HN_AUTOSCALE, 4 },
+       { 3, "1 T", (int64_t)500*1000*1000*1000L, HN_DIVISOR_1000, 
HN_AUTOSCALE, 4 },
+       { 3, "1 P", (int64_t)500*1000*1000*1000*1000L, HN_DIVISOR_1000, 
HN_AUTOSCALE, 4 },
+       { 3, "1 E", (int64_t)500*1000*1000*1000*1000*1000L, HN_DIVISOR_1000, 
HN_AUTOSCALE, 4 },
+       { 2, "1 ", (int64_t)1L, HN_DIVISOR_1000, HN_AUTOSCALE, 4 },
+       { 3, "2 k", (int64_t)1500L, HN_DIVISOR_1000, HN_AUTOSCALE, 4 },
+       { 3, "2 M", (int64_t)1500*1000L, HN_DIVISOR_1000, HN_AUTOSCALE, 4 },
+       { 3, "2 G", (int64_t)1500*1000*1000L, HN_DIVISOR_1000, HN_AUTOSCALE, 4 
},
+       { 3, "2 T", (int64_t)1500*1000*1000*1000L, HN_DIVISOR_1000, 
HN_AUTOSCALE, 4 },
+       { 3, "2 P", (int64_t)1500*1000*1000*1000*1000L, HN_DIVISOR_1000, 
HN_AUTOSCALE, 4 },
+       { 3, "2 E", (int64_t)1500*1000*1000*1000*1000*1000L, HN_DIVISOR_1000, 
HN_AUTOSCALE, 4 },
 
        /* tests 14-27 test 1024 suffixes */
-       { 2, "0 ", (int64_t)0L, 0, HN_AUTOSCALE },
-       { 3, "1 K", (int64_t)512L, 0, HN_AUTOSCALE },
-       { 3, "1 M", (int64_t)512*1024L, 0, HN_AUTOSCALE },
-       { 3, "1 G", (int64_t)512*1024*1024L, 0, HN_AUTOSCALE },
-       { 3, "1 T", (int64_t)512*1024*1024*1024L, 0, HN_AUTOSCALE },
-       { 3, "1 P", (int64_t)512*1024*1024*1024*1024L, 0, HN_AUTOSCALE },
-       { 3, "1 E", (int64_t)512*1024*1024*1024*1024*1024L, 0, HN_AUTOSCALE },
-       { 2, "1 ", (int64_t)1L, 0, HN_AUTOSCALE },
-       { 3, "2 K", (int64_t)1536L, 0, HN_AUTOSCALE },
-       { 3, "2 M", (int64_t)1536*1024L, 0, HN_AUTOSCALE },
-       { 3, "2 G", (int64_t)1536*1024*1024L, 0, HN_AUTOSCALE },
-       { 3, "2 T", (int64_t)1536*1024*1024*1024L, 0, HN_AUTOSCALE },
-       { 3, "2 P", (int64_t)1536*1024*1024*1024*1024L, 0, HN_AUTOSCALE },
-       { 3, "2 E", (int64_t)1536*1024*1024*1024*1024*1024L, 0, HN_AUTOSCALE },
+       { 2, "0 ", (int64_t)0L, 0, HN_AUTOSCALE, 4 },
+       { 3, "1 K", (int64_t)512L, 0, HN_AUTOSCALE, 4 },
+       { 3, "1 M", (int64_t)512*1024L, 0, HN_AUTOSCALE, 4 },
+       { 3, "1 G", (int64_t)512*1024*1024L, 0, HN_AUTOSCALE, 4 },
+       { 3, "1 T", (int64_t)512*1024*1024*1024L, 0, HN_AUTOSCALE, 4 },
+       { 3, "1 P", (int64_t)512*1024*1024*1024*1024L, 0, HN_AUTOSCALE, 4 },
+       { 3, "1 E", (int64_t)512*1024*1024*1024*1024*1024L, 0, HN_AUTOSCALE, 4 
},
+       { 2, "1 ", (int64_t)1L, 0, HN_AUTOSCALE, 4 },
+       { 3, "2 K", (int64_t)1536L, 0, HN_AUTOSCALE, 4 },
+       { 3, "2 M", (int64_t)1536*1024L, 0, HN_AUTOSCALE, 4 },
+       { 3, "2 G", (int64_t)1536*1024*1024L, 0, HN_AUTOSCALE, 4 },
+       { 3, "2 T", (int64_t)1536*1024*1024*1024L, 0, HN_AUTOSCALE, 4 },
+       { 3, "2 P", (int64_t)1536*1024*1024*1024*1024L, 0, HN_AUTOSCALE, 4 },
+       { 3, "2 E", (int64_t)1536*1024*1024*1024*1024*1024L, 0, HN_AUTOSCALE, 4 
},
 
        /* tests 28-37 test rounding */
-       { 3, "0 M", (int64_t)500*1000L-1, HN_DIVISOR_1000, HN_AUTOSCALE },
-       { 3, "1 M", (int64_t)500*1000L, HN_DIVISOR_1000, HN_AUTOSCALE },
-       { 3, "1 M", (int64_t)1000*1000L + 500*1000L-1, HN_DIVISOR_1000, 
HN_AUTOSCALE },
-       { 3, "2 M", (int64_t)1000*1000L + 500*1000L, HN_DIVISOR_1000, 
HN_AUTOSCALE },
-       { 3, "0 K", (int64_t)512L-1, 0, HN_AUTOSCALE },
-       { 3, "1 K", (int64_t)512L, 0, HN_AUTOSCALE },
-       { 3, "0 M", (int64_t)512*1024L-1, 0, HN_AUTOSCALE },
-       { 3, "1 M", (int64_t)512*1024L, 0, HN_AUTOSCALE },
-       { 3, "1 M", (int64_t)1024*1024L + 512*1024L-1, 0, HN_AUTOSCALE },
-       { 3, "2 M", (int64_t)1024*1024L + 512*1024L, 0, HN_AUTOSCALE },
+       { 3, "0 M", (int64_t)500*1000L-1, HN_DIVISOR_1000, HN_AUTOSCALE, 4 },
+       { 3, "1 M", (int64_t)500*1000L, HN_DIVISOR_1000, HN_AUTOSCALE, 4 },
+       { 3, "1 M", (int64_t)1000*1000L + 500*1000L-1, HN_DIVISOR_1000, 
HN_AUTOSCALE, 4 },
+       { 3, "2 M", (int64_t)1000*1000L + 500*1000L, HN_DIVISOR_1000, 
HN_AUTOSCALE, 4 },
+       { 3, "0 K", (int64_t)512L-1, 0, HN_AUTOSCALE, 4 },
+       { 3, "1 K", (int64_t)512L, 0, HN_AUTOSCALE, 4 },
+       { 3, "0 M", (int64_t)512*1024L-1, 0, HN_AUTOSCALE, 4 },
+       { 3, "1 M", (int64_t)512*1024L, 0, HN_AUTOSCALE, 4 },
+       { 3, "1 M", (int64_t)1024*1024L + 512*1024L-1, 0, HN_AUTOSCALE, 4 },
+       { 3, "2 M", (int64_t)1024*1024L + 512*1024L, 0, HN_AUTOSCALE, 4 },
 
        /* tests 38-61 test specific scale factors with 1000 divisor */
-       { 3, "0 k", (int64_t)0L, HN_DIVISOR_1000, 1 },
-       { 3, "1 k", (int64_t)500L, HN_DIVISOR_1000, 1 },
-       { 3, "0 M", (int64_t)500L, HN_DIVISOR_1000, 2 },
-       { 3, "1 M", (int64_t)500*1000L, HN_DIVISOR_1000, 2 },
-       { 3, "0 G", (int64_t)500*1000L, HN_DIVISOR_1000, 3 },
-       { 3, "1 G", (int64_t)500*1000*1000L, HN_DIVISOR_1000, 3 },
-       { 3, "0 T", (int64_t)500*1000*1000L, HN_DIVISOR_1000, 4 },
-       { 3, "1 T", (int64_t)500*1000*1000*1000L, HN_DIVISOR_1000, 4 },
-       { 3, "0 P", (int64_t)500*1000*1000*1000L, HN_DIVISOR_1000, 5 },
-       { 3, "1 P", (int64_t)500*1000*1000*1000*1000L, HN_DIVISOR_1000, 5 },
-       { 3, "0 E", (int64_t)500*1000*1000*1000*1000L, HN_DIVISOR_1000, 6 },
-       { 3, "1 E", (int64_t)500*1000*1000*1000*1000*1000L, HN_DIVISOR_1000, 6 
},
-       { 3, "0 k", (int64_t)1L, HN_DIVISOR_1000, 1 },
-       { 3, "2 k", (int64_t)1500L, HN_DIVISOR_1000, 1 },
-       { 3, "0 M", (int64_t)1500L, HN_DIVISOR_1000, 2 },
-       { 3, "2 M", (int64_t)1500*1000L, HN_DIVISOR_1000, 2 },
-       { 3, "0 G", (int64_t)1500*1000L, HN_DIVISOR_1000, 3 },
-       { 3, "2 G", (int64_t)1500*1000*1000L, HN_DIVISOR_1000, 3 },
-       { 3, "0 T", (int64_t)1500*1000*1000L, HN_DIVISOR_1000, 4 },
-       { 3, "2 T", (int64_t)1500*1000*1000*1000L, HN_DIVISOR_1000, 4 },
-       { 3, "0 P", (int64_t)1500*1000*1000*1000L, HN_DIVISOR_1000, 5 },
-       { 3, "2 P", (int64_t)1500*1000*1000*1000*1000L, HN_DIVISOR_1000, 5 },
-       { 3, "0 E", (int64_t)1500*1000*1000*1000*1000L, HN_DIVISOR_1000, 6 },
-       { 3, "2 E", (int64_t)1500*1000*1000*1000*1000*1000L, HN_DIVISOR_1000, 6 
},
+       { 3, "0 k", (int64_t)0L, HN_DIVISOR_1000, 1, 4 },
+       { 3, "1 k", (int64_t)500L, HN_DIVISOR_1000, 1, 4 },
+       { 3, "0 M", (int64_t)500L, HN_DIVISOR_1000, 2, 4 },
+       { 3, "1 M", (int64_t)500*1000L, HN_DIVISOR_1000, 2, 4 },
+       { 3, "0 G", (int64_t)500*1000L, HN_DIVISOR_1000, 3, 4 },
+       { 3, "1 G", (int64_t)500*1000*1000L, HN_DIVISOR_1000, 3, 4 },
+       { 3, "0 T", (int64_t)500*1000*1000L, HN_DIVISOR_1000, 4, 4 },
+       { 3, "1 T", (int64_t)500*1000*1000*1000L, HN_DIVISOR_1000, 4, 4 },
+       { 3, "0 P", (int64_t)500*1000*1000*1000L, HN_DIVISOR_1000, 5, 4 },
+       { 3, "1 P", (int64_t)500*1000*1000*1000*1000L, HN_DIVISOR_1000, 5, 4 },
+       { 3, "0 E", (int64_t)500*1000*1000*1000*1000L, HN_DIVISOR_1000, 6, 4 },
+       { 3, "1 E", (int64_t)500*1000*1000*1000*1000*1000L, HN_DIVISOR_1000, 6, 
4 },
+       { 3, "0 k", (int64_t)1L, HN_DIVISOR_1000, 1, 4 },
+       { 3, "2 k", (int64_t)1500L, HN_DIVISOR_1000, 1, 4 },
+       { 3, "0 M", (int64_t)1500L, HN_DIVISOR_1000, 2, 4 },
+       { 3, "2 M", (int64_t)1500*1000L, HN_DIVISOR_1000, 2, 4 },
+       { 3, "0 G", (int64_t)1500*1000L, HN_DIVISOR_1000, 3, 4 },
+       { 3, "2 G", (int64_t)1500*1000*1000L, HN_DIVISOR_1000, 3, 4 },
+       { 3, "0 T", (int64_t)1500*1000*1000L, HN_DIVISOR_1000, 4, 4 },
+       { 3, "2 T", (int64_t)1500*1000*1000*1000L, HN_DIVISOR_1000, 4, 4 },
+       { 3, "0 P", (int64_t)1500*1000*1000*1000L, HN_DIVISOR_1000, 5, 4 },
+       { 3, "2 P", (int64_t)1500*1000*1000*1000*1000L, HN_DIVISOR_1000, 5, 4 },
+       { 3, "0 E", (int64_t)1500*1000*1000*1000*1000L, HN_DIVISOR_1000, 6, 4 },
+       { 3, "2 E", (int64_t)1500*1000*1000*1000*1000*1000L, HN_DIVISOR_1000, 
6, 4 },
 
        /* tests 62-85 test specific scale factors with 1024 divisor */
-       { 3, "0 K", (int64_t)0L, 0, 1 },
-       { 3, "1 K", (int64_t)512L, 0, 1 },
-       { 3, "0 M", (int64_t)512L, 0, 2 },
-       { 3, "1 M", (int64_t)512*1024L, 0, 2 },
-       { 3, "0 G", (int64_t)512*1024L, 0, 3 },
-       { 3, "1 G", (int64_t)512*1024*1024L, 0, 3 },
-       { 3, "0 T", (int64_t)512*1024*1024L, 0, 4 },
-       { 3, "1 T", (int64_t)512*1024*1024*1024L, 0, 4 },
-       { 3, "0 P", (int64_t)512*1024*1024*1024L, 0, 5 },
-       { 3, "1 P", (int64_t)512*1024*1024*1024*1024L, 0, 5 },
-       { 3, "0 E", (int64_t)512*1024*1024*1024*1024L, 0, 6 },
-       { 3, "1 E", (int64_t)512*1024*1024*1024*1024*1024L, 0, 6 },
-       { 3, "0 K", (int64_t)1L, 0, 1 },
-       { 3, "2 K", (int64_t)1536L, 0, 1 },
-       { 3, "0 M", (int64_t)1536L, 0, 2 },
-       { 3, "2 M", (int64_t)1536*1024L, 0, 2 },
-       { 3, "0 G", (int64_t)1536*1024L, 0, 3 },
-       { 3, "2 G", (int64_t)1536*1024*1024L, 0, 3 },
-       { 3, "0 T", (int64_t)1536*1024*1024L, 0, 4 },
-       { 3, "2 T", (int64_t)1536*1024*1024*1024L, 0, 4 },
-       { 3, "0 P", (int64_t)1536*1024*1024*1024L, 0, 5 },
-       { 3, "2 P", (int64_t)1536*1024*1024*1024*1024L, 0, 5 },
-       { 3, "0 E", (int64_t)1536*1024*1024*1024*1024L, 0, 6 },
-       { 3, "2 E", (int64_t)1536*1024*1024*1024*1024*1024L, 0, 6 },
+       { 3, "0 K", (int64_t)0L, 0, 1, 4 },
+       { 3, "1 K", (int64_t)512L, 0, 1, 4 },
+       { 3, "0 M", (int64_t)512L, 0, 2, 4 },
+       { 3, "1 M", (int64_t)512*1024L, 0, 2, 4 },
+       { 3, "0 G", (int64_t)512*1024L, 0, 3, 4 },
+       { 3, "1 G", (int64_t)512*1024*1024L, 0, 3, 4 },
+       { 3, "0 T", (int64_t)512*1024*1024L, 0, 4, 4 },
+       { 3, "1 T", (int64_t)512*1024*1024*1024L, 0, 4, 4 },
+       { 3, "0 P", (int64_t)512*1024*1024*1024L, 0, 5, 4 },
+       { 3, "1 P", (int64_t)512*1024*1024*1024*1024L, 0, 5, 4 },
+       { 3, "0 E", (int64_t)512*1024*1024*1024*1024L, 0, 6, 4 },
+       { 3, "1 E", (int64_t)512*1024*1024*1024*1024*1024L, 0, 6, 4 },
+       { 3, "0 K", (int64_t)1L, 0, 1, 4 },
+       { 3, "2 K", (int64_t)1536L, 0, 1, 4 },
+       { 3, "0 M", (int64_t)1536L, 0, 2, 4 },
+       { 3, "2 M", (int64_t)1536*1024L, 0, 2, 4 },
+       { 3, "0 G", (int64_t)1536*1024L, 0, 3, 4 },
+       { 3, "2 G", (int64_t)1536*1024*1024L, 0, 3, 4 },
+       { 3, "0 T", (int64_t)1536*1024*1024L, 0, 4, 4 },
+       { 3, "2 T", (int64_t)1536*1024*1024*1024L, 0, 4, 4 },
+       { 3, "0 P", (int64_t)1536*1024*1024*1024L, 0, 5, 4 },
+       { 3, "2 P", (int64_t)1536*1024*1024*1024*1024L, 0, 5, 4 },
+       { 3, "0 E", (int64_t)1536*1024*1024*1024*1024L, 0, 6, 4 },
+       { 3, "2 E", (int64_t)1536*1024*1024*1024*1024*1024L, 0, 6, 4 },
 
        /* tests 86-99 test invalid specific scale values of < 0 or >= 7 with
        and without HN_DIVISOR_1000 set */
        /*  all should return errors with new code; with old, the latter 3
        are instead processed as if having AUTOSCALE and/or GETSCALE set */
-       { -1, "", (int64_t)1L, 0, 7 },
-       { -1, "", (int64_t)1L, HN_DIVISOR_1000, 7 },
-       { -1, "", (int64_t)1L, 0, 1000 },
-       { -1, "", (int64_t)1L, HN_DIVISOR_1000, 1000 },
-       { -1, "", (int64_t)0L, 0, 1000*1000 },
-       { -1, "", (int64_t)0L, HN_DIVISOR_1000, 1000*1000 },
-       { -1, "", (int64_t)0L, 0, INT_MAX },
-       { -1, "", (int64_t)0L, HN_DIVISOR_1000, INT_MAX },
+       { -1, "", (int64_t)1L, 0, 7, 4 },
+       { -1, "", (int64_t)1L, HN_DIVISOR_1000, 7, 4 },
+       { -1, "", (int64_t)1L, 0, 1000, 4 },
+       { -1, "", (int64_t)1L, HN_DIVISOR_1000, 1000, 4 },
+       { -1, "", (int64_t)0L, 0, 1000*1000, 4 },
+       { -1, "", (int64_t)0L, HN_DIVISOR_1000, 1000*1000, 4 },
+       { -1, "", (int64_t)0L, 0, INT_MAX, 4 },
+       { -1, "", (int64_t)0L, HN_DIVISOR_1000, INT_MAX, 4 },
 
        /* Negative scale values are not handled well
         by the existing library routine - should report as error */
        /*  all should return errors with new code, fail assertion with old */
 
-       { -1, "", (int64_t)1L, 0, -1 },
-       { -1, "", (int64_t)1L, HN_DIVISOR_1000, -1 },
-       { -1, "", (int64_t)1L, 0, -1000 },
-       { -1, "", (int64_t)1L, HN_DIVISOR_1000, -1000 },
+       { -1, "", (int64_t)1L, 0, -1, 4 },
+       { -1, "", (int64_t)1L, HN_DIVISOR_1000, -1, 4 },
+       { -1, "", (int64_t)1L, 0, -1000, 4 },
+       { -1, "", (int64_t)1L, HN_DIVISOR_1000, -1000, 4 },
 
        /* __INT_MIN doesn't print properly, skipped. */
 
-       { -1, "", (int64_t)1L, 0, -__INT_MAX },
-       { -1, "", (int64_t)1L, HN_DIVISOR_1000, -__INT_MAX },
+       { -1, "", (int64_t)1L, 0, -__INT_MAX, 4 },
+       { -1, "", (int64_t)1L, HN_DIVISOR_1000, -__INT_MAX, 4 },
 
 
        /* tests for scale == 0, without autoscale */
        /* tests 100-114 test scale 0 with 1000 divisor - print first N digits 
*/
-       { 2, "0 ", (int64_t)0L, HN_DIVISOR_1000, 0 },
-       { 2, "1 ", (int64_t)1L, HN_DIVISOR_1000, 0 },
-       { 3, "10 ", (int64_t)10L, HN_DIVISOR_1000, 0 },
-       { 3, "0 M", (int64_t)150L, HN_DIVISOR_1000, HN_NOSPACE },
-       { 3, "0 M", (int64_t)500L, HN_DIVISOR_1000, HN_NOSPACE },
-       { 3, "0 M", (int64_t)999L, HN_DIVISOR_1000, HN_NOSPACE },
-       { 4, "150", (int64_t)150L, HN_DIVISOR_1000, 0 },
-       { 4, "500", (int64_t)500L, HN_DIVISOR_1000, 0 },
-       { 4, "999", (int64_t)999L, HN_DIVISOR_1000, 0 },
-       { 5, "100", (int64_t)1000L, HN_DIVISOR_1000, 0 },
-       { 5, "150", (int64_t)1500L, HN_DIVISOR_1000, 0 },
-       { 7, "500", (int64_t)500*1000L, HN_DIVISOR_1000, 0 },
-       { 8, "150", (int64_t)1500*1000L, HN_DIVISOR_1000, 0 },
-       { 10, "500", (int64_t)500*1000*1000L, HN_DIVISOR_1000, 0 },
-       { 11, "150", (int64_t)1500*1000*1000L, HN_DIVISOR_1000, 0 },
+       { 2, "0 ", (int64_t)0L, HN_DIVISOR_1000, 0, 4 },
+       { 2, "1 ", (int64_t)1L, HN_DIVISOR_1000, 0, 4 },
+       { 3, "10 ", (int64_t)10L, HN_DIVISOR_1000, 0, 4 },
+       { 3, "0 M", (int64_t)150L, HN_DIVISOR_1000, HN_NOSPACE, 4 },
+       { 3, "0 M", (int64_t)500L, HN_DIVISOR_1000, HN_NOSPACE, 4 },
+       { 3, "0 M", (int64_t)999L, HN_DIVISOR_1000, HN_NOSPACE, 4 },
+       { 4, "150", (int64_t)150L, HN_DIVISOR_1000, 0, 4 },
+       { 4, "500", (int64_t)500L, HN_DIVISOR_1000, 0, 4 },
+       { 4, "999", (int64_t)999L, HN_DIVISOR_1000, 0, 4 },
+       { 5, "100", (int64_t)1000L, HN_DIVISOR_1000, 0, 4 },
+       { 5, "150", (int64_t)1500L, HN_DIVISOR_1000, 0, 4 },
+       { 7, "500", (int64_t)500*1000L, HN_DIVISOR_1000, 0, 4 },
+       { 8, "150", (int64_t)1500*1000L, HN_DIVISOR_1000, 0, 4 },
+       { 10, "500", (int64_t)500*1000*1000L, HN_DIVISOR_1000, 0, 4 },
+       { 11, "150", (int64_t)1500*1000*1000L, HN_DIVISOR_1000, 0, 4 },
 
        /* tests 115-126 test scale 0 with 1024 divisor - print first N digits 
*/
-       { 2, "0 ", (int64_t)0L, 0, 0 },
-       { 2, "1 ", (int64_t)1L, 0, 0 },
-       { 3, "10 ", (int64_t)10L, 0, 0 },
-       { 4, "150", (int64_t)150L, 0, 0 },
-       { 4, "500", (int64_t)500L, 0, 0 },
-       { 4, "999", (int64_t)999L, 0, 0 },
-       { 5, "100", (int64_t)1000L, 0, 0 },
-       { 5, "150", (int64_t)1500L, 0, 0 },
-       { 7, "500", (int64_t)500*1000L, 0, 0 },
-       { 8, "150", (int64_t)1500*1000L, 0, 0 },
-       { 10, "500", (int64_t)500*1000*1000L, 0, 0 },
-       { 11, "150", (int64_t)1500*1000*1000L, 0, 0 },
+       { 2, "0 ", (int64_t)0L, 0, 0, 4 },
+       { 2, "1 ", (int64_t)1L, 0, 0, 4 },
+       { 3, "10 ", (int64_t)10L, 0, 0, 4 },
+       { 4, "150", (int64_t)150L, 0, 0, 4 },
+       { 4, "500", (int64_t)500L, 0, 0, 4 },
+       { 4, "999", (int64_t)999L, 0, 0, 4 },
+       { 5, "100", (int64_t)1000L, 0, 0, 4 },
+       { 5, "150", (int64_t)1500L, 0, 0, 4 },
+       { 7, "500", (int64_t)500*1000L, 0, 0, 4 },
+       { 8, "150", (int64_t)1500*1000L, 0, 0, 4 },
+       { 10, "500", (int64_t)500*1000*1000L, 0, 0, 4 },
+       { 11, "150", (int64_t)1500*1000*1000L, 0, 0, 4 },
 
+       /* Test case for rounding of edge numbers around 999.5+, see PR224498.
+        * Require buflen >= 5 */
+       { 4, "1.0M", (int64_t)1023500, HN_DECIMAL|HN_B|HN_NOSPACE, 
HN_AUTOSCALE, 5 },
+
        /* Test boundary cases for very large positive/negative number 
formatting */
        /* Explicit scale, divisor 1024 */
 
-       /* XXX = requires length 5 (buflen 6) for some cases*/
-       /* KLUDGE - test loop below will bump length 5 up to 5 */
-       { 3, "8 E",   INT64_MAX, 0, 6 },
-       { 4, "-8 E", -INT64_MAX, 0, 6 },
-       { 3, "0 E", (int64_t)92*1024*1024*1024*1024*1024L, 0, 6 },
-       { 3, "0 E", -(int64_t)92*1024*1024*1024*1024*1024L, 0, 6 },
-       { 3, "0 E", (int64_t)82*1024*1024*1024*1024*1024L, 0, 6 },
-       { 3, "0 E", -(int64_t)82*1024*1024*1024*1024*1024L, 0, 6 },
-       { 3, "0 E", (int64_t)81*1024*1024*1024*1024*1024L, 0, 6 },
-       { 3, "0 E", -(int64_t)81*1024*1024*1024*1024*1024L, 0, 6 },
-       { 4, "92 P", (int64_t)92*1024*1024*1024*1024*1024L, 0, 5 },
-       { 5, "-92 P", -(int64_t)92*1024*1024*1024*1024*1024L, 0, 5 },
-       { 4, "82 P", (int64_t)82*1024*1024*1024*1024*1024L, 0, 5 },
-       { 5, "-82 P", -(int64_t)82*1024*1024*1024*1024*1024L, 0, 5 },
-       { 4, "81 P", (int64_t)81*1024*1024*1024*1024*1024L, 0, 5 },
-       { 5, "-81 P", -(int64_t)81*1024*1024*1024*1024*1024L, 0, 5 },
+       /* Requires buflen >= 6 */
+       { 3, "8 E",   INT64_MAX, 0, 6, 6 },
+       { 4, "-8 E", -INT64_MAX, 0, 6, 6 },
+       { 3, "0 E", (int64_t)92*1024*1024*1024*1024*1024L, 0, 6, 6 },
+       { 3, "0 E", -(int64_t)92*1024*1024*1024*1024*1024L, 0, 6, 6 },
+       { 3, "0 E", (int64_t)82*1024*1024*1024*1024*1024L, 0, 6, 6 },
+       { 3, "0 E", -(int64_t)82*1024*1024*1024*1024*1024L, 0, 6, 6 },
+       { 3, "0 E", (int64_t)81*1024*1024*1024*1024*1024L, 0, 6, 6 },
+       { 3, "0 E", -(int64_t)81*1024*1024*1024*1024*1024L, 0, 6, 6 },
+       { 4, "92 P", (int64_t)92*1024*1024*1024*1024*1024L, 0, 5, 6 },
+       { 5, "-92 P", -(int64_t)92*1024*1024*1024*1024*1024L, 0, 5, 6 },
+       { 4, "82 P", (int64_t)82*1024*1024*1024*1024*1024L, 0, 5, 6 },
+       { 5, "-82 P", -(int64_t)82*1024*1024*1024*1024*1024L, 0, 5, 6 },
+       { 4, "81 P", (int64_t)81*1024*1024*1024*1024*1024L, 0, 5, 6 },
+       { 5, "-81 P", -(int64_t)81*1024*1024*1024*1024*1024L, 0, 5, 6 },
 
        /* Explicit scale, divisor 1000 */
-       { 3, "9 E",   INT64_MAX, HN_DIVISOR_1000, 6 },
-       { 4, "-9 E", -INT64_MAX, HN_DIVISOR_1000,  6 },
-       { 3, "0 E", (int64_t)82*1024*1024*1024*1024*1024L, HN_DIVISOR_1000,  6 
},
-       { 3, "0 E", -(int64_t)82*1024*1024*1024*1024*1024L, HN_DIVISOR_1000,  6 
},
-       { 3, "0 E", (int64_t)82*1024*1024*1024*1024*1024L, HN_DIVISOR_1000,  6 
},
-       { 3, "0 E", -(int64_t)82*1024*1024*1024*1024*1024L, HN_DIVISOR_1000,  6 
},
-       { 4, "92 P", (int64_t)82*1024*1024*1024*1024*1024L, HN_DIVISOR_1000,  5 
},
-       { 5, "-92 P", -(int64_t)82*1024*1024*1024*1024*1024L, HN_DIVISOR_1000,  
5 },
-       { 4, "91 P", (int64_t)81*1024*1024*1024*1024*1024L, HN_DIVISOR_1000,  5 
},
-       { 5, "-91 P", -(int64_t)81*1024*1024*1024*1024*1024L, HN_DIVISOR_1000,  
5 },
+       { 3, "9 E",   INT64_MAX, HN_DIVISOR_1000, 6, 6 },
+       { 4, "-9 E", -INT64_MAX, HN_DIVISOR_1000,  6, 6 },
+       { 3, "0 E", (int64_t)82*1024*1024*1024*1024*1024L, HN_DIVISOR_1000,  6, 
6 },
+       { 3, "0 E", -(int64_t)82*1024*1024*1024*1024*1024L, HN_DIVISOR_1000,  
6, 6 },
+       { 3, "0 E", (int64_t)82*1024*1024*1024*1024*1024L, HN_DIVISOR_1000,  6, 
6 },
+       { 3, "0 E", -(int64_t)82*1024*1024*1024*1024*1024L, HN_DIVISOR_1000,  
6, 6 },
+       { 4, "92 P", (int64_t)82*1024*1024*1024*1024*1024L, HN_DIVISOR_1000,  
5, 6 },
+       { 5, "-92 P", -(int64_t)82*1024*1024*1024*1024*1024L, HN_DIVISOR_1000,  
5, 6 },
+       { 4, "91 P", (int64_t)81*1024*1024*1024*1024*1024L, HN_DIVISOR_1000,  
5, 6 },
+       { 5, "-91 P", -(int64_t)81*1024*1024*1024*1024*1024L, HN_DIVISOR_1000,  
5, 6 },
 
        /* Autoscale, divisor 1024 */
-       { 3, "8 E",   INT64_MAX, 0, HN_AUTOSCALE },
-       { 4, "-8 E", -INT64_MAX, 0, HN_AUTOSCALE },
-       { 4, "92 P", (int64_t)92*1024*1024*1024*1024*1024L, 0, HN_AUTOSCALE },
-       { 5, "-92 P", -(int64_t)92*1024*1024*1024*1024*1024L, 0, HN_AUTOSCALE },
-       { 4, "82 P", (int64_t)82*1024*1024*1024*1024*1024L, 0, HN_AUTOSCALE },
-       { 5, "-82 P", -(int64_t)82*1024*1024*1024*1024*1024L, 0, HN_AUTOSCALE },
-       { 4, "81 P", (int64_t)81*1024*1024*1024*1024*1024L, 0, HN_AUTOSCALE },
-       { 5, "-81 P", -(int64_t)81*1024*1024*1024*1024*1024L, 0, HN_AUTOSCALE },
+       { 3, "8 E",   INT64_MAX, 0, HN_AUTOSCALE, 6 },
+       { 4, "-8 E", -INT64_MAX, 0, HN_AUTOSCALE, 6 },
+       { 4, "92 P", (int64_t)92*1024*1024*1024*1024*1024L, 0, HN_AUTOSCALE, 6 
},
+       { 5, "-92 P", -(int64_t)92*1024*1024*1024*1024*1024L, 0, HN_AUTOSCALE, 
6 },
+       { 4, "82 P", (int64_t)82*1024*1024*1024*1024*1024L, 0, HN_AUTOSCALE, 6 
},
+       { 5, "-82 P", -(int64_t)82*1024*1024*1024*1024*1024L, 0, HN_AUTOSCALE, 
6 },
+       { 4, "81 P", (int64_t)81*1024*1024*1024*1024*1024L, 0, HN_AUTOSCALE, 6 
},
+       { 5, "-81 P", -(int64_t)81*1024*1024*1024*1024*1024L, 0, HN_AUTOSCALE, 
6 },
        /* Autoscale, divisor 1000 */
-       { 3, "9 E",   INT64_MAX, HN_DIVISOR_1000, HN_AUTOSCALE },
-       { 4, "-9 E", -INT64_MAX, HN_DIVISOR_1000, HN_AUTOSCALE },
-       { 4, "92 P", (int64_t)82*1024*1024*1024*1024*1024L, HN_DIVISOR_1000, 
HN_AUTOSCALE },
-       { 5, "-92 P", -(int64_t)82*1024*1024*1024*1024*1024L, HN_DIVISOR_1000, 
HN_AUTOSCALE },
-       { 4, "91 P", (int64_t)81*1024*1024*1024*1024*1024L, HN_DIVISOR_1000, 
HN_AUTOSCALE },
-       { 5, "-91 P", -(int64_t)81*1024*1024*1024*1024*1024L, HN_DIVISOR_1000, 
HN_AUTOSCALE },
+       { 3, "9 E",   INT64_MAX, HN_DIVISOR_1000, HN_AUTOSCALE, 6 },
+       { 4, "-9 E", -INT64_MAX, HN_DIVISOR_1000, HN_AUTOSCALE, 6 },
+       { 4, "92 P", (int64_t)82*1024*1024*1024*1024*1024L, HN_DIVISOR_1000, 
HN_AUTOSCALE, 6 },
+       { 5, "-92 P", -(int64_t)82*1024*1024*1024*1024*1024L, HN_DIVISOR_1000, 
HN_AUTOSCALE, 6 },
+       { 4, "91 P", (int64_t)81*1024*1024*1024*1024*1024L, HN_DIVISOR_1000, 
HN_AUTOSCALE, 6 },
+       { 5, "-91 P", -(int64_t)81*1024*1024*1024*1024*1024L, HN_DIVISOR_1000, 
HN_AUTOSCALE, 6 },
 
        /* 0 scale, divisor 1024 */
-       { 12, "skdj",  INT64_MAX, 0, 0 },
-       { 21, "-9223", -INT64_MAX, 0, 0 },
-       { 19, "10358", (int64_t)92*1024*1024*1024*1024*1024L, 0, 0 },
-       { 20, "-1035", -(int64_t)92*1024*1024*1024*1024*1024L, 0, 0 },
-       { 18, "92323", (int64_t)82*1024*1024*1024*1024*1024L, 0, 0 },
-       { 19, "-9232", -(int64_t)82*1024*1024*1024*1024*1024L, 0, 0 },
-       { 18, "91197", (int64_t)81*1024*1024*1024*1024*1024L, 0, 0 },
-       { 19, "-9119", -(int64_t)81*1024*1024*1024*1024*1024L, 0, 0 },
+       { 12, "skdj",  INT64_MAX, 0, 0, 6 },
+       { 21, "-9223", -INT64_MAX, 0, 0, 6 },
+       { 19, "10358", (int64_t)92*1024*1024*1024*1024*1024L, 0, 0, 6 },
+       { 20, "-1035", -(int64_t)92*1024*1024*1024*1024*1024L, 0, 0, 6 },
+       { 18, "92323", (int64_t)82*1024*1024*1024*1024*1024L, 0, 0, 6 },
+       { 19, "-9232", -(int64_t)82*1024*1024*1024*1024*1024L, 0, 0, 6 },
+       { 18, "91197", (int64_t)81*1024*1024*1024*1024*1024L, 0, 0, 6 },
+       { 19, "-9119", -(int64_t)81*1024*1024*1024*1024*1024L, 0, 0, 6 },
 
        /* 0 scale, divisor 1000 */
        /* XXX - why does this fail? */
-       { -1, "", INT64_MAX, HN_DIVISOR_1000, 0 },
-       { 21, "-9223", -INT64_MAX, HN_DIVISOR_1000,  0 },
-       { 19, "10358", (int64_t)92*1024*1024*1024*1024*1024L, HN_DIVISOR_1000,  
0 },
-       { 20, "-1035", -(int64_t)92*1024*1024*1024*1024*1024L, HN_DIVISOR_1000, 
 0 },
-       { 18, "92323", (int64_t)82*1024*1024*1024*1024*1024L, HN_DIVISOR_1000,  
0 },
-       { 19, "-9232", -(int64_t)82*1024*1024*1024*1024*1024L, HN_DIVISOR_1000, 
 0 },
+       { -1, "", INT64_MAX, HN_DIVISOR_1000, 0, 6 },
+       { 21, "-9223", -INT64_MAX, HN_DIVISOR_1000,  0, 6 },
+       { 19, "10358", (int64_t)92*1024*1024*1024*1024*1024L, HN_DIVISOR_1000,  
0, 6 },
+       { 20, "-1035", -(int64_t)92*1024*1024*1024*1024*1024L, HN_DIVISOR_1000, 
 0, 6 },
+       { 18, "92323", (int64_t)82*1024*1024*1024*1024*1024L, HN_DIVISOR_1000,  
0, 6 },
+       { 19, "-9232", -(int64_t)82*1024*1024*1024*1024*1024L, HN_DIVISOR_1000, 
 0, 6 },
        /* Expected to pass */
-       { 18, "91197", (int64_t)81*1024*1024*1024*1024*1024L, HN_DIVISOR_1000,  
0 },
-       { 19, "-9119", -(int64_t)81*1024*1024*1024*1024*1024L, HN_DIVISOR_1000, 
 0 },
+       { 18, "91197", (int64_t)81*1024*1024*1024*1024*1024L, HN_DIVISOR_1000,  
0, 6 },
+       { 19, "-9119", -(int64_t)81*1024*1024*1024*1024*1024L, HN_DIVISOR_1000, 
 0, 6 },
 
 
 
        /* Need to implement tests for GETSCALE */
-/*     { ?, "", (int64_t)0L, HN_DIVISOR_1000, HN_GETSCALE },
+/*     { ?, "", (int64_t)0L, HN_DIVISOR_1000, HN_GETSCALE, 6 },
        ...
 */
         /* Tests for HN_DECIMAL */
         /* Positive, Autoscale */
-       { 5, "500 k", (int64_t)500*1000L, HN_DECIMAL|HN_DIVISOR_1000, 
HN_AUTOSCALE },
-       { 5, "994 k", (int64_t)994*1000L, HN_DECIMAL|HN_DIVISOR_1000, 
HN_AUTOSCALE },
-       { 5, "995 k", (int64_t)995*1000L, HN_DECIMAL|HN_DIVISOR_1000, 
HN_AUTOSCALE },
-       { 5, "999 k", (int64_t)999*1000L, HN_DECIMAL|HN_DIVISOR_1000, 
HN_AUTOSCALE },
-       { 5, "1.0 M", (int64_t)1000*1000L, HN_DECIMAL|HN_DIVISOR_1000, 
HN_AUTOSCALE },
-       { 5, "1.5 M", (int64_t)1500*1000L, HN_DECIMAL|HN_DIVISOR_1000, 
HN_AUTOSCALE },
-       { 5, "1.9 M", (int64_t)1949*1000L, HN_DECIMAL|HN_DIVISOR_1000, 
HN_AUTOSCALE },
-       { 5, "2.0 M", (int64_t)1950*1000L, HN_DECIMAL|HN_DIVISOR_1000, 
HN_AUTOSCALE },
-       { 5, "9.9 M", (int64_t)9949*1000L, HN_DECIMAL|HN_DIVISOR_1000, 
HN_AUTOSCALE },
-       { 4, "10 M", (int64_t)9950*1000L, HN_DECIMAL|HN_DIVISOR_1000, 
HN_AUTOSCALE },
-       { 5, "500 M", (int64_t)500*1000*1000L, HN_DECIMAL|HN_DIVISOR_1000, 
HN_AUTOSCALE },
-       { 5, "994 M", (int64_t)994*1000*1000L, HN_DECIMAL|HN_DIVISOR_1000, 
HN_AUTOSCALE },
-       { 5, "995 M", (int64_t)995*1000*1000L, HN_DECIMAL|HN_DIVISOR_1000, 
HN_AUTOSCALE },
-       { 5, "999 M", (int64_t)999*1000*1000L, HN_DECIMAL|HN_DIVISOR_1000, 
HN_AUTOSCALE },
+       { 5, "500 k", (int64_t)500*1000L, HN_DECIMAL|HN_DIVISOR_1000, 
HN_AUTOSCALE, 6 },
+       { 5, "994 k", (int64_t)994*1000L, HN_DECIMAL|HN_DIVISOR_1000, 
HN_AUTOSCALE, 6 },
+       { 5, "995 k", (int64_t)995*1000L, HN_DECIMAL|HN_DIVISOR_1000, 
HN_AUTOSCALE, 6 },
+       { 5, "999 k", (int64_t)999*1000L, HN_DECIMAL|HN_DIVISOR_1000, 
HN_AUTOSCALE, 6 },
+       { 5, "1.0 M", (int64_t)1000*1000L, HN_DECIMAL|HN_DIVISOR_1000, 
HN_AUTOSCALE, 6 },
+       { 5, "1.5 M", (int64_t)1500*1000L, HN_DECIMAL|HN_DIVISOR_1000, 
HN_AUTOSCALE, 6 },
+       { 5, "1.9 M", (int64_t)1949*1000L, HN_DECIMAL|HN_DIVISOR_1000, 
HN_AUTOSCALE, 6 },
+       { 5, "2.0 M", (int64_t)1950*1000L, HN_DECIMAL|HN_DIVISOR_1000, 
HN_AUTOSCALE, 6 },
+       { 5, "9.9 M", (int64_t)9949*1000L, HN_DECIMAL|HN_DIVISOR_1000, 
HN_AUTOSCALE, 6 },
+       { 4, "10 M", (int64_t)9950*1000L, HN_DECIMAL|HN_DIVISOR_1000, 
HN_AUTOSCALE, 6 },
+       { 5, "500 M", (int64_t)500*1000*1000L, HN_DECIMAL|HN_DIVISOR_1000, 
HN_AUTOSCALE, 6 },
+       { 5, "994 M", (int64_t)994*1000*1000L, HN_DECIMAL|HN_DIVISOR_1000, 
HN_AUTOSCALE, 6 },
+       { 5, "995 M", (int64_t)995*1000*1000L, HN_DECIMAL|HN_DIVISOR_1000, 
HN_AUTOSCALE, 6 },
+       { 5, "999 M", (int64_t)999*1000*1000L, HN_DECIMAL|HN_DIVISOR_1000, 
HN_AUTOSCALE, 6 },
 
-       { 5, "500 K", (int64_t)500*1024L, HN_DECIMAL, HN_AUTOSCALE },
-       { 5, "994 K", (int64_t)994*1024L, HN_DECIMAL, HN_AUTOSCALE },
-       { 5, "995 K", (int64_t)995*1024L, HN_DECIMAL, HN_AUTOSCALE },
-       { 5, "999 K", (int64_t)999*1024L, HN_DECIMAL, HN_AUTOSCALE },
-       { 5, "1.0 M", (int64_t)1000*1024L, HN_DECIMAL, HN_AUTOSCALE },
-       { 5, "1.0 M", (int64_t)1018*1024L, HN_DECIMAL, HN_AUTOSCALE },
-       { 5, "1.0 M", (int64_t)1019*1024L, HN_DECIMAL, HN_AUTOSCALE },
-       { 5, "1.5 M", (int64_t)1536*1024L, HN_DECIMAL, HN_AUTOSCALE },
-       { 5, "1.9 M", (int64_t)1996*1024L, HN_DECIMAL, HN_AUTOSCALE },
-       { 5, "2.0 M", (int64_t)1997*1024L, HN_DECIMAL, HN_AUTOSCALE },
-       { 5, "2.0 M", (int64_t)2047*1024L, HN_DECIMAL, HN_AUTOSCALE },
-       { 5, "2.0 M", (int64_t)2048*1024L, HN_DECIMAL, HN_AUTOSCALE },
-       { 5, "2.0 M", (int64_t)2099*1024L, HN_DECIMAL, HN_AUTOSCALE },
-       { 5, "2.1 M", (int64_t)2100*1024L, HN_DECIMAL, HN_AUTOSCALE },
-       { 5, "9.9 M", (int64_t)10188*1024L, HN_DECIMAL, HN_AUTOSCALE },
+       { 5, "500 K", (int64_t)500*1024L, HN_DECIMAL, HN_AUTOSCALE, 6 },
+       { 5, "994 K", (int64_t)994*1024L, HN_DECIMAL, HN_AUTOSCALE, 6 },
+       { 5, "995 K", (int64_t)995*1024L, HN_DECIMAL, HN_AUTOSCALE, 6 },
+       { 5, "999 K", (int64_t)999*1024L, HN_DECIMAL, HN_AUTOSCALE, 6 },
+       { 5, "1.0 M", (int64_t)1000*1024L, HN_DECIMAL, HN_AUTOSCALE, 6 },
+       { 5, "1.0 M", (int64_t)1018*1024L, HN_DECIMAL, HN_AUTOSCALE, 6 },
+       { 5, "1.0 M", (int64_t)1019*1024L, HN_DECIMAL, HN_AUTOSCALE, 6 },
+       { 5, "1.5 M", (int64_t)1536*1024L, HN_DECIMAL, HN_AUTOSCALE, 6 },
+       { 5, "1.9 M", (int64_t)1996*1024L, HN_DECIMAL, HN_AUTOSCALE, 6 },
+       { 5, "2.0 M", (int64_t)1997*1024L, HN_DECIMAL, HN_AUTOSCALE, 6 },
+       { 5, "2.0 M", (int64_t)2047*1024L, HN_DECIMAL, HN_AUTOSCALE, 6 },
+       { 5, "2.0 M", (int64_t)2048*1024L, HN_DECIMAL, HN_AUTOSCALE, 6 },
+       { 5, "2.0 M", (int64_t)2099*1024L, HN_DECIMAL, HN_AUTOSCALE, 6 },
+       { 5, "2.1 M", (int64_t)2100*1024L, HN_DECIMAL, HN_AUTOSCALE, 6 },
+       { 5, "9.9 M", (int64_t)10188*1024L, HN_DECIMAL, HN_AUTOSCALE, 6 },
        /* XXX - shouldn't the following two be "10. M"? */
-       { 4, "10 M", (int64_t)10189*1024L, HN_DECIMAL, HN_AUTOSCALE },
-       { 4, "10 M", (int64_t)10240*1024L, HN_DECIMAL, HN_AUTOSCALE },
-       { 5, "500 M", (int64_t)500*1024*1024L, HN_DECIMAL, HN_AUTOSCALE },
-       { 5, "994 M", (int64_t)994*1024*1024L, HN_DECIMAL, HN_AUTOSCALE },
-       { 5, "995 M", (int64_t)995*1024*1024L, HN_DECIMAL, HN_AUTOSCALE },
-       { 5, "999 M", (int64_t)999*1024*1024L, HN_DECIMAL, HN_AUTOSCALE },
-       { 5, "1.0 G", (int64_t)1000*1024*1024L, HN_DECIMAL, HN_AUTOSCALE },
-       { 5, "1.0 G", (int64_t)1023*1024*1024L, HN_DECIMAL, HN_AUTOSCALE },
+       { 4, "10 M", (int64_t)10189*1024L, HN_DECIMAL, HN_AUTOSCALE, 6 },
+       { 4, "10 M", (int64_t)10240*1024L, HN_DECIMAL, HN_AUTOSCALE, 6 },
+       { 5, "500 M", (int64_t)500*1024*1024L, HN_DECIMAL, HN_AUTOSCALE, 6 },
+       { 5, "994 M", (int64_t)994*1024*1024L, HN_DECIMAL, HN_AUTOSCALE, 6 },
+       { 5, "995 M", (int64_t)995*1024*1024L, HN_DECIMAL, HN_AUTOSCALE, 6 },
+       { 5, "999 M", (int64_t)999*1024*1024L, HN_DECIMAL, HN_AUTOSCALE, 6 },
+       { 5, "1.0 G", (int64_t)1000*1024*1024L, HN_DECIMAL, HN_AUTOSCALE, 6 },
+       { 5, "1.0 G", (int64_t)1023*1024*1024L, HN_DECIMAL, HN_AUTOSCALE, 6 },
 
         /* Negative, Autoscale - should pass */
-       { 6, "-1.5 ", -(int64_t)1500*1000L, HN_DECIMAL|HN_DIVISOR_1000, 
HN_AUTOSCALE },
-       { 6, "-1.9 ", -(int64_t)1949*1000L, HN_DECIMAL|HN_DIVISOR_1000, 
HN_AUTOSCALE },
-       { 6, "-9.9 ", -(int64_t)9949*1000L, HN_DECIMAL|HN_DIVISOR_1000, 
HN_AUTOSCALE },
+       { 6, "-1.5 ", -(int64_t)1500*1000L, HN_DECIMAL|HN_DIVISOR_1000, 
HN_AUTOSCALE, 6 },
+       { 6, "-1.9 ", -(int64_t)1949*1000L, HN_DECIMAL|HN_DIVISOR_1000, 
HN_AUTOSCALE, 6 },
+       { 6, "-9.9 ", -(int64_t)9949*1000L, HN_DECIMAL|HN_DIVISOR_1000, 
HN_AUTOSCALE, 6 },
 
-       { 6, "-1.5 ", -(int64_t)1536*1024L, HN_DECIMAL, HN_AUTOSCALE },
-       { 6, "-1.9 ", -(int64_t)1949*1024L, HN_DECIMAL, HN_AUTOSCALE },
-       { 6, "-9.7 ", -(int64_t)9949*1024L, HN_DECIMAL, HN_AUTOSCALE },
+       { 6, "-1.5 ", -(int64_t)1536*1024L, HN_DECIMAL, HN_AUTOSCALE, 6 },
+       { 6, "-1.9 ", -(int64_t)1949*1024L, HN_DECIMAL, HN_AUTOSCALE, 6 },
+       { 6, "-9.7 ", -(int64_t)9949*1024L, HN_DECIMAL, HN_AUTOSCALE, 6 },
 
        /* Positive/negative, at maximum scale */
-       { 5, "500 P", (int64_t)500*1000*1000*1000*1000*1000L, HN_DIVISOR_1000, 
HN_AUTOSCALE },
-       { 5, "1.9 E", (int64_t)1949*1000*1000*1000*1000*1000L, HN_DIVISOR_1000, 
HN_AUTOSCALE },
-       { 5, "8.9 E", (int64_t)8949*1000*1000*1000*1000*1000L, HN_DIVISOR_1000, 
HN_AUTOSCALE },
-       { 5, "9.2 E", INT64_MAX, HN_DECIMAL|HN_DIVISOR_1000, HN_AUTOSCALE },
+       { 5, "500 P", (int64_t)500*1000*1000*1000*1000*1000L, HN_DIVISOR_1000, 
HN_AUTOSCALE, 6 },
+       { 5, "1.9 E", (int64_t)1949*1000*1000*1000*1000*1000L, HN_DIVISOR_1000, 
HN_AUTOSCALE, 6 },
+       { 5, "8.9 E", (int64_t)8949*1000*1000*1000*1000*1000L, HN_DIVISOR_1000, 
HN_AUTOSCALE, 6 },
+       { 5, "9.2 E", INT64_MAX, HN_DECIMAL|HN_DIVISOR_1000, HN_AUTOSCALE, 6 },
         /* Negatives work with latest rev only: */
-       { 6, "-9.2 ", -INT64_MAX, HN_DECIMAL|HN_DIVISOR_1000, HN_AUTOSCALE },
-       { 6, "-8.9 ", -(int64_t)8949*1000*1000*1000*1000*1000L, 
HN_DECIMAL|HN_DIVISOR_1000, HN_AUTOSCALE },
+       { 6, "-9.2 ", -INT64_MAX, HN_DECIMAL|HN_DIVISOR_1000, HN_AUTOSCALE, 6 },
+       { 6, "-8.9 ", -(int64_t)8949*1000*1000*1000*1000*1000L, 
HN_DECIMAL|HN_DIVISOR_1000, HN_AUTOSCALE, 6 },
 
-       { 5, "8.0 E",   INT64_MAX, HN_DECIMAL, HN_AUTOSCALE },
-       { 5, "7.9 E",   INT64_MAX-(int64_t)100*1024*1024*1024*1024*1024LL, 
HN_DECIMAL, HN_AUTOSCALE },
-       { 6, "-8.0 ", -INT64_MAX, HN_DECIMAL, HN_AUTOSCALE },
-       { 6, "-7.9 ",   -INT64_MAX+(int64_t)100*1024*1024*1024*1024*1024LL, 
HN_DECIMAL, HN_AUTOSCALE },
+       { 5, "8.0 E",   INT64_MAX, HN_DECIMAL, HN_AUTOSCALE, 6 },
+       { 5, "7.9 E",   INT64_MAX-(int64_t)100*1024*1024*1024*1024*1024LL, 
HN_DECIMAL, HN_AUTOSCALE, 6 },
+       { 6, "-8.0 ", -INT64_MAX, HN_DECIMAL, HN_AUTOSCALE, 6 },
+       { 6, "-7.9 ",   -INT64_MAX+(int64_t)100*1024*1024*1024*1024*1024LL, 
HN_DECIMAL, HN_AUTOSCALE, 6 },
 
        /* Positive, Fixed scales */
-       { 5, "500 k", (int64_t)500*1000L, HN_DECIMAL|HN_DIVISOR_1000, 1 },
-       { 5, "0.5 M", (int64_t)500*1000L, HN_DECIMAL|HN_DIVISOR_1000, 2 },
-       { 5, "949 k", (int64_t)949*1000L, HN_DECIMAL|HN_DIVISOR_1000, 1 },
-       { 5, "0.9 M", (int64_t)949*1000L, HN_DECIMAL|HN_DIVISOR_1000, 2 },
-       { 5, "950 k", (int64_t)950*1000L, HN_DECIMAL|HN_DIVISOR_1000, 1 },
-       { 5, "1.0 M", (int64_t)950*1000L, HN_DECIMAL|HN_DIVISOR_1000, 2 },
-       { 5, "999 k", (int64_t)999*1000L, HN_DECIMAL|HN_DIVISOR_1000, 1 },
-       { 5, "1.0 M", (int64_t)999*1000L, HN_DECIMAL|HN_DIVISOR_1000, 2 },
-       { 5, "1.5 M", (int64_t)1500*1000L, HN_DECIMAL|HN_DIVISOR_1000, 2 },
-       { 5, "1.9 M", (int64_t)1949*1000L, HN_DECIMAL|HN_DIVISOR_1000, 2 },
-       { 5, "2.0 M", (int64_t)1950*1000L, HN_DECIMAL|HN_DIVISOR_1000, 2 },
-       { 5, "9.9 M", (int64_t)9949*1000L, HN_DECIMAL|HN_DIVISOR_1000, 2 },
-       { 4, "10 M", (int64_t)9950*1000L, HN_DECIMAL|HN_DIVISOR_1000, 2 },
-       { 5, "500 M", (int64_t)500*1000*1000L, HN_DECIMAL|HN_DIVISOR_1000, 2 },
-       { 5, "0.5 G", (int64_t)500*1000*1000L, HN_DECIMAL|HN_DIVISOR_1000, 3 },
-       { 5, "999 M", (int64_t)999*1000*1000L, HN_DECIMAL|HN_DIVISOR_1000, 2 },
-       { 5, "1.0 G", (int64_t)999*1000*1000L, HN_DECIMAL|HN_DIVISOR_1000, 3 },
+       { 5, "500 k", (int64_t)500*1000L, HN_DECIMAL|HN_DIVISOR_1000, 1, 6 },
+       { 5, "0.5 M", (int64_t)500*1000L, HN_DECIMAL|HN_DIVISOR_1000, 2, 6 },
+       { 5, "949 k", (int64_t)949*1000L, HN_DECIMAL|HN_DIVISOR_1000, 1, 6 },
+       { 5, "0.9 M", (int64_t)949*1000L, HN_DECIMAL|HN_DIVISOR_1000, 2, 6 },
+       { 5, "950 k", (int64_t)950*1000L, HN_DECIMAL|HN_DIVISOR_1000, 1, 6 },
+       { 5, "1.0 M", (int64_t)950*1000L, HN_DECIMAL|HN_DIVISOR_1000, 2, 6 },
+       { 5, "999 k", (int64_t)999*1000L, HN_DECIMAL|HN_DIVISOR_1000, 1, 6 },
+       { 5, "1.0 M", (int64_t)999*1000L, HN_DECIMAL|HN_DIVISOR_1000, 2, 6 },
+       { 5, "1.5 M", (int64_t)1500*1000L, HN_DECIMAL|HN_DIVISOR_1000, 2, 6 },
+       { 5, "1.9 M", (int64_t)1949*1000L, HN_DECIMAL|HN_DIVISOR_1000, 2, 6 },
+       { 5, "2.0 M", (int64_t)1950*1000L, HN_DECIMAL|HN_DIVISOR_1000, 2, 6 },
+       { 5, "9.9 M", (int64_t)9949*1000L, HN_DECIMAL|HN_DIVISOR_1000, 2, 6 },
+       { 4, "10 M", (int64_t)9950*1000L, HN_DECIMAL|HN_DIVISOR_1000, 2, 6 },
+       { 5, "500 M", (int64_t)500*1000*1000L, HN_DECIMAL|HN_DIVISOR_1000, 2, 6 
},
+       { 5, "0.5 G", (int64_t)500*1000*1000L, HN_DECIMAL|HN_DIVISOR_1000, 3, 6 
},
+       { 5, "999 M", (int64_t)999*1000*1000L, HN_DECIMAL|HN_DIVISOR_1000, 2, 6 
},
+       { 5, "1.0 G", (int64_t)999*1000*1000L, HN_DECIMAL|HN_DIVISOR_1000, 3, 6 
},
        /* Positive/negative, at maximum scale */
-       { 5, "500 P", (int64_t)500*1000*1000*1000*1000*1000L, HN_DIVISOR_1000, 
5 },
-       { 5, "1.0 E", (int64_t)500*1000*1000*1000*1000*1000L, HN_DIVISOR_1000, 
6 },
-       { 5, "1.9 E", (int64_t)1949*1000*1000*1000*1000*1000L, HN_DIVISOR_1000, 
6 },
-       { 5, "8.9 E", (int64_t)8949*1000*1000*1000*1000*1000L, HN_DIVISOR_1000, 
6 },
-       { 5, "9.2 E", INT64_MAX, HN_DECIMAL|HN_DIVISOR_1000, 6 },
+       { 5, "500 P", (int64_t)500*1000*1000*1000*1000*1000L, HN_DIVISOR_1000, 
5, 6 },
+       { 5, "1.0 E", (int64_t)500*1000*1000*1000*1000*1000L, HN_DIVISOR_1000, 
6, 6 },
+       { 5, "1.9 E", (int64_t)1949*1000*1000*1000*1000*1000L, HN_DIVISOR_1000, 
6, 6 },
+       { 5, "8.9 E", (int64_t)8949*1000*1000*1000*1000*1000L, HN_DIVISOR_1000, 
6, 6 },
+       { 5, "9.2 E", INT64_MAX, HN_DECIMAL|HN_DIVISOR_1000, 6, 6 },
 
        /* HN_DECIMAL + binary + fixed scale cases not completed */
-       { 5, "512 K", (int64_t)512*1024L, HN_DECIMAL, 1 },
-       { 5, "0.5 M", (int64_t)512*1024L, HN_DECIMAL, 2 },
+       { 5, "512 K", (int64_t)512*1024L, HN_DECIMAL, 1, 6 },
+       { 5, "0.5 M", (int64_t)512*1024L, HN_DECIMAL, 2, 6 },
 
        /* Negative, Fixed scales */
         /* Not yet added, but should work with latest rev */
@@ -439,9 +443,9 @@ static struct {
  } flags[] = {
        { HN_AUTOSCALE, "HN_AUTOSCALE" },
        { HN_GETSCALE, "HN_GETSCALE" },
-       { HN_DIVISOR_1000, "HN_DIVISOR_1000"},
-       { HN_B, "HN_B"},
-       { HN_DECIMAL, "HN_DECIMAL"},
+       { HN_DIVISOR_1000, "HN_DIVISOR_1000" },
+       { HN_B, "HN_B" },
+       { HN_DECIMAL, "HN_DECIMAL" },
 };
 
 static const char *separator = "|";
@@ -496,13 +500,14 @@ main(int argc, char * const argv[])
 {
        char *buf;
        char *flag_str, *scale_str;
-       size_t buflen, errcnt, i, skipped, tested;
+       size_t blen, buflen, errcnt, i, skipped, tested;
        int r;
        int includeNegScale;
        int includeExabyteTests;
        int verbose;
 
-       buflen = 4;
+       buf = NULL;
+       buflen = 0;
        includeNegScale = 0;
        includeExabyteTests = 0;
        verbose = 0;
@@ -510,7 +515,6 @@ main(int argc, char * const argv[])
        read_options(argc, argv, &buflen, &includeNegScale,
            &includeExabyteTests, &verbose);
 
-       buf = malloc(buflen);
        errcnt = 0;
        tested = 0;
        skipped = 0;
@@ -520,16 +524,8 @@ main(int argc, char * const argv[])
 
        printf("1..%zu\n", nitems(test_args));
        for (i = 0; i < nitems(test_args); i++) {
-               /* KLUDGE */
-               if (test_args[i].num == INT64_MAX && buflen == 4) {
-                       /* Start final tests which require buffer of 6 */
-                       free(buf);
-                       buflen = 6;
-                        buf = malloc(buflen);
-                        if (verbose)
-                                printf("Buffer length increased to %zu\n",
-                                   buflen);
-               }
+               blen = (buflen > 0) ? buflen : test_args[i].buflen;
+               buf = realloc(buf, blen);
 
                if (test_args[i].scale < 0 && ! includeNegScale) {
                        skipped++;
@@ -542,7 +538,7 @@ main(int argc, char * const argv[])
                        continue;
                }
 
-               r = humanize_number(buf, buflen, test_args[i].num, "",
+               r = humanize_number(buf, blen, test_args[i].num, "",
                    test_args[i].scale, test_args[i].flags);
                flag_str = str_flags(test_args[i].flags, "[no flags]");
                scale_str = str_scale(test_args[i].scale);
@@ -553,7 +549,7 @@ main(int argc, char * const argv[])
                                    "buflen: %zu, got: %d + \"%s\", "
                                    "expected %d + \"%s\"; num = %jd, "
                                    "scale = %s, flags= %s.\n",
-                                   i, buflen, r, buf, test_args[i].retval,
+                                   i, blen, r, buf, test_args[i].retval,
                                    test_args[i].res,
                                    (intmax_t)test_args[i].num,
                                    scale_str, flag_str);
@@ -565,10 +561,10 @@ main(int argc, char * const argv[])
                        if (verbose)
                                printf("result mismatch on index %zu, got: "
                                    "\"%s\", expected \"%s\"; num = %jd, "
-                                   "scale = %s, flags= %s.\n",
+                                   "buflen: %zu, scale = %s, flags= %s.\n",
                                    i, buf, test_args[i].res,
                                    (intmax_t)test_args[i].num,
-                                   scale_str, flag_str);
+                                   blen, scale_str, flag_str);
                        else
                                printf("not ok %zu # buf \"%s\" != \"%s\"\n",
                                    i + 1, buf, test_args[i].res);
@@ -577,15 +573,15 @@ main(int argc, char * const argv[])
                        if (verbose)
                                printf("successful result on index %zu, "
                                    "returned %d, got: \"%s\"; num = %jd, "
-                                   "scale = %s, flags= %s.\n",
-                                   i, r, buf,
-                                   (intmax_t)test_args[i].num,
-                                   scale_str, flag_str);
+                                   "buflen = %zd, scale = %s, flags= %s.\n",
+                                   i, r, buf, (intmax_t)test_args[i].num,
+                                   blen, scale_str, flag_str);
                        else
                                printf("ok %zu\n", i + 1);
                }
                tested++;
        }
+       free(buf);
 
        if (verbose)
                printf("total errors: %zu/%zu tests, %zu skipped\n", errcnt,
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to