This is the mail archive of the newlib@sourceware.org mailing list for the newlib 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]

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' 




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