This is the mail archive of the
newlib@sourceware.org
mailing list for the newlib project.
printf %F broken
- From: Eric Blake <ebb9 at byu dot net>
- To: newlib at sources dot redhat dot com
- Date: Wed, 11 Apr 2007 21:18:51 +0000 (UTC)
- Subject: printf %F broken
Ever since %F support was added (2005-10-11), it was broken, because newlib
assumes that printf is compiled in a character encoding where 'F' < 'e'. I'm
not sure if newlib has any non-ASCII targets, so I have propagated that
assumption in the patch below, and reduced code size slightly in the process by
further exploiting the assumption. If anyone REALLY wants to compile newlib in
EBCDIC, this patch won't help them.
For an example of the bug, on cygwin, using bash's builtin (which calls
newlib's printf):
$ printf %.f 1234
1234
$ printf %.F 1234
1F+03
OK to check this in now (even though I may be changing it later when I get time
to implement %a/%A)?
2007-04-11 Eric Blake <ebb9@byu.net>
* libc/stdio/vfprintf.c (_VFPRINTF_F): Don't confuse %F with %e.
Index: libc/stdio/vfprintf.c
===================================================================
RCS file: /cvs/src/src/newlib/libc/stdio/vfprintf.c,v
retrieving revision 1.48
diff -u -r1.48 vfprintf.c
--- libc/stdio/vfprintf.c 15 Mar 2007 18:40:48 -0000 1.48
+++ libc/stdio/vfprintf.c 11 Apr 2007 20:56:46 -0000
@@ -876,7 +876,7 @@
if (isinf (_fpvalue)) {
if (_fpvalue < 0)
sign = '-';
- if (ch == 'E' || ch == 'F' || ch == 'G')
+ if (ch <= 'G') /* 'E', 'F', or 'G' */
cp = "INF";
else
cp = "inf";
@@ -884,7 +884,7 @@
break;
}
if (isnan (_fpvalue)) {
- if (ch == 'E' || ch == 'F' || ch == 'G')
+ if (ch <= 'G') /* 'E', 'F', or 'G' */
cp = "NAN";
else
cp = "nan";
@@ -905,7 +905,7 @@
if (tmp == 2) {
if (_fpvalue < 0)
sign = '-';
- if (ch == 'E' || ch == 'F' || ch == 'G')
+ if (ch <= 'G') /* 'E', 'F', or 'G' */
cp = "INF";
else
cp = "inf";
@@ -913,7 +913,7 @@
break;
}
if (tmp == 1) {
- if (ch == 'E' || ch == 'F' || ch == 'G')
+ if (ch <= 'G') /* 'E', 'F', or 'G' */
cp = "NAN";
else
cp = "nan";
@@ -929,10 +929,12 @@
if (ch == 'g' || ch == 'G') {
if (expt <= -4 || expt > prec)
- ch = (ch == 'g') ? 'e' : 'E';
+ ch -= 2; /* 'e' or 'E' */
else
ch = 'g';
- }
+ }
+ else if (ch == 'F')
+ ch = 'f';
if (ch <= 'e') { /* 'e' or 'E' fmt */
--expt;
expsize = exponent (expstr, expt, ch);
@@ -1187,6 +1189,7 @@
* required by a decimal [diouxX] precision, then print the
* string proper, then emit zeroes required by any leftover
* floating precision; finally, if LADJUST, pad with blanks.
+ * If flags&FPT, ch must be in [eEfg].
*
* Compute actual size, so we know how much to pad.
* size excludes decimal prec; realsz includes it.
@@ -1338,7 +1341,7 @@
} ld;
#endif
- if (ch == 'f') {
+ if (ch == 'f' || ch == 'F') {
mode = 3; /* ndigits after the decimal point */
} else {
/* To obtain ndigits after the decimal point for the 'e'