This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH] enable SI unit suffix in printf_size


On Wed, Oct 19, 2005 at 04:17:45PM -0700, Paul Eggert wrote:
> Ian Wienand <ianw@gelato.unsw.edu.au> writes:
> There seems to be some confusion here, since SI units are decimal.
> Perhaps you're thinking of IEC 60027-2?  That's not SI; it's
> something else.  See <http://en.wikipedia.org/wiki/Binary_prefixes>.

It seems despite the fact I've always referred to them as SI binary
units, I did really mean IEC 60027-2;
http://physics.nist.gov/cuu/Units/binary.html says

 It is important to recognize that the new prefixes for binary
 multiples are not part of the International System of Units (SI), the
 modern metric system. However, for ease of understanding and recall,
 they were derived from the SI prefixes for positive powers of ten.

> SI specifies "k" (not "K") for 1000, so adding support for true SI
> would require rethinking and/or documentation clarification for "k".
> (In contrast IEC 60027-2 always specifies upper-case multipliers, so it
> uses "Ki", not "ki".)

I don't think it makes any claim to be standardised, but a little k
does seem to be the most correct output.
 
> Another minor point: IEC 60027-2 does not specify Zi or Yi prefixes.
> They are common extensions (GNU coreutils uses them, for example), but
> the documentation shouldn't claim they're part of the standard.

A exabyte ought to be enough for anyone :)

-i

2005-10-19  Ian Wienand  <ianw@gelato.unsw.edu.au>

	* stdio-common/printf_size.c: enable use of alt modifier to show
	IEC units and lower case k to fit with SI units with base 10
	* manual/stdio.texi : describe above

Index: manual/stdio.texi
===================================================================
RCS file: /cvs/glibc/libc/manual/stdio.texi,v
retrieving revision 1.134
diff -u -r1.134 stdio.texi
--- manual/stdio.texi	25 Sep 2005 18:24:55 -0000	1.134
+++ manual/stdio.texi	19 Oct 2005 23:43:33 -0000
@@ -3112,7 +3112,10 @@
 powers of 1024 or powers of 1000.  Which one is used depends on the
 format character specified while registered this handler.  If the
 character is of lower case, 1024 is used.  For upper case characters,
-1000 is used.
+1000 is used.  If you use lower case you can also specify the
+alternative (@samp{#}) modifier to show IEC 60027-2 style binary units
+(note that the default behaviour of @samp{#} to always print the
+decimal will be overridden in this case).
 
 The postfix tag corresponds to bytes, kilobytes, megabytes, gigabytes,
 etc.  The full table is:
Index: stdio-common/printf_size.c
===================================================================
RCS file: /cvs/glibc/libc/stdio-common/printf_size.c,v
retrieving revision 1.15
diff -u -r1.15 printf_size.c
--- stdio-common/printf_size.c	4 Aug 2004 21:43:30 -0000	1.15
+++ stdio-common/printf_size.c	19 Oct 2005 23:43:35 -0000
@@ -1,5 +1,5 @@
 /* Print size value using units for orders of magnitude.
-   Copyright (C) 1997-2002, 2004 Free Software Foundation, Inc.
+   Copyright (C) 1997-2002, 2004, 2005 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
    Based on a proposal by Larry McVoy <lm@sgi.com>.
@@ -85,19 +85,23 @@
 			const void *const *args);
 
 
+
 int
 printf_size (FILE *fp, const struct printf_info *info, const void *const *args)
 {
   /* Units for the both formats.  */
 #define BINARY_UNITS	" kmgtpezy"
-#define DECIMAL_UNITS	" KMGTPEZY"
-  static const char units[2][sizeof (BINARY_UNITS)] =
+#define DECIMAL_UNITS	" kMGTPEZY"
+#define IEC_UNITS	"  KiMiGiTiPiEiZiYi"
+  static const char units[3][sizeof (IEC_UNITS)] =
   {
     BINARY_UNITS,	/* For binary format.  */
-    DECIMAL_UNITS	/* For decimal format.  */
+    DECIMAL_UNITS,	/* For decimal format.  */
+    IEC_UNITS		/* For IEC unit format.  */
   };
-  const char *tag = units[isupper (info->spec) != 0];
+  const char *tag;
   int divisor = isupper (info->spec) ? 1000 : 1024;
+  int tag_inc;
 
   /* The floating-point value to output.  */
   union
@@ -118,6 +122,17 @@
   int done = 0;
   int wide = info->wide;
 
+  /* allow IEC units as an alt (#) for 1024 divisor  */
+  if (info->alt && !isupper(info->spec))
+    {
+      tag = units[2];
+      tag_inc = 2;
+    }
+  else
+    {
+      tag = units[isupper (info->spec) != 0];
+      tag_inc = 1;
+    }
 
   /* Fetch the argument value.	*/
 #ifndef __NO_LONG_DOUBLE_MATH
@@ -140,10 +155,10 @@
 	  negative = fpnum.ldbl.d < 0;
 	}
       else
-	while (fpnum.ldbl.d >= divisor && tag[1] != '\0')
+	while (fpnum.ldbl.d >= divisor && tag[tag_inc] != '\0')
 	  {
 	    fpnum.ldbl.d /= divisor;
-	    ++tag;
+	    tag += tag_inc;
 	  }
     }
   else
@@ -166,10 +181,10 @@
 	  negative = fpnum.dbl.d < 0;
 	}
       else
-	while (fpnum.dbl.d >= divisor && tag[1] != '\0')
+	while (fpnum.dbl.d >= divisor && tag[tag_inc] != '\0')
 	  {
 	    fpnum.dbl.d /= divisor;
-	    ++tag;
+	    tag += tag_inc;
 	  }
     }
 
@@ -205,10 +220,12 @@
   fp_info.spec = 'f';
   fp_info.prec = info->prec < 0 ? 3 : info->prec;
   fp_info.wide = wide;
-
+  /* Override alt (#) specifier when using IEC units */
+  if (info->alt && !isupper(info->spec))
+    fp_info.alt = 0;
   if (fp_info.left && fp_info.pad == L' ')
     {
-      /* We must do the padding ourself since the unit character must
+      /* We must do the padding ourself since the unit characters must
 	 be placed before the padding spaces.  */
       fp_info.width = 0;
 
@@ -216,6 +233,8 @@
       if (done > 0)
 	{
 	  outchar (*tag);
+	  if (tag_inc == 2)
+	    outchar(*(tag + 1));
 	  if (info->width > done)
 	    PADN (' ', info->width - done);
 	}
@@ -223,12 +242,16 @@
   else
     {
       /* We can let __printf_fp do all the printing and just add our
-	 unit character afterwards.  */
-      fp_info.width = info->width - 1;
+	 unit characters afterwards.  */
+      fp_info.width = info->width - tag_inc;
 
       done = __printf_fp (fp, &fp_info, &ptr);
       if (done > 0)
-	outchar (*tag);
+	{
+	  outchar(*tag);
+	  if (tag_inc == 2)
+	    outchar(*(tag + 1));
+	}
     }
 
   return done;


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]