summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2012-08-06 14:38:47 +0000
committerpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2012-08-06 14:38:47 +0000
commite94500d9199dd11107328e8e4da793b03997e301 (patch)
treee1b9ae12eba24f12f687268367afe52d07850cc6
parent50a8647d6402d6b6f547b9d77d9ab1b6679a578d (diff)
downloadnuttx-e94500d9199dd11107328e8e4da793b03997e301.tar.gz
nuttx-e94500d9199dd11107328e8e4da793b03997e301.tar.bz2
nuttx-e94500d9199dd11107328e8e4da793b03997e301.zip
Fix more floating point formatting bugs
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@5013 42af7a65-404d-4744-a932-0658087f49c3
-rw-r--r--nuttx/ChangeLog2
-rw-r--r--nuttx/lib/stdio/lib_libdtoa.c135
-rw-r--r--nuttx/lib/stdio/lib_libvsprintf.c4
3 files changed, 103 insertions, 38 deletions
diff --git a/nuttx/ChangeLog b/nuttx/ChangeLog
index d57d9c4d8..603d2db97 100644
--- a/nuttx/ChangeLog
+++ b/nuttx/ChangeLog
@@ -3129,4 +3129,6 @@
point numbers (conversions are fine, but presentation was bad). This
is a critical bug fix if you use printf or sprintf to deal with floating
point numbers.
+ * lib/stdio/lib_libdtoa.c and lib_libvsprintf.c: Correct some floating
+ point options.
diff --git a/nuttx/lib/stdio/lib_libdtoa.c b/nuttx/lib/stdio/lib_libdtoa.c
index 2d4309abe..77045d9b0 100644
--- a/nuttx/lib/stdio/lib_libdtoa.c
+++ b/nuttx/lib/stdio/lib_libdtoa.c
@@ -48,6 +48,8 @@
* Pre-processor Definitions
****************************************************************************/
+#define MAX_PREC 16
+
#ifndef MIN
# define MIN(a,b) (a < b ? a : b)
#endif
@@ -107,7 +109,20 @@ static void zeroes(FAR struct lib_outstream_s *obj, int nzeroes)
*
* Description:
* This is part of lib_vsprintf(). It handles the floating point formats.
- * This version supports only the &f (with precision).
+ * This version supports only the %f (with precision). If no precision
+ * was provided in the format, this will use precision == 0 which is
+ * probably not what you want.
+ *
+ * Input Parameters:
+ * obj - The output stream object
+ * fmt - The format character. Not used 'f' is always assumed
+ * prec - The number of digits to the right of the decimal point. If no
+ * precision is provided in the format, this will be zero. And,
+ * unfortunately in this case, it will be treated literally as
+ * a precision of zero.
+ * flags - Only ALTFORM and SHOWPLUS flags are supported. ALTFORM only
+ * applies if prec == 0 which is not supported anyway.
+ * value - The floating point value to convert.
*
****************************************************************************/
@@ -146,10 +161,10 @@ static void lib_dtoa(FAR struct lib_outstream_s *obj, int fmt, int prec,
{
obj->put(obj, '-');
}
-
- /* Always print at least one digit to the right of the decimal point. */
-
- prec = MAX(1, prec);
+ else if (IS_SHOWPLUS(flags))
+ {
+ obj->put(obj, '+');
+ }
/* Special case exact zero or the case where the number is smaller than
* the print precision.
@@ -160,53 +175,101 @@ static void lib_dtoa(FAR struct lib_outstream_s *obj, int fmt, int prec,
/* kludge for __dtoa irregularity */
obj->put(obj, '0');
- obj->put(obj, '.');
- }
- else if (expt <= 0)
- {
- obj->put(obj, '0');
- obj->put(obj, '.');
- /* Print leading zeros */
+ /* A decimal point is printed only in the alternate form or if a
+ * particular precision is requested.
+ */
- if (expt < 0)
+ if (prec > 0 || IS_ALTFORM(flags))
{
- nchars = MIN(-expt, prec);
- zeroes(obj, nchars);
- prec -= nchars;
- }
-
- /* Print the significant digits */
+ obj->put(obj, '.');
- nchars = MIN(numlen, prec);
- for (i = nchars; i > 0; i--)
- {
- obj->put(obj, *digits);
- digits++;
+ /* Always print at least one digit to the right of the decimal point. */
+
+ prec = MAX(1, prec);
}
+ }
- /* Decremnt to get the number of trailing zeroes to print */
+ /* A non-zero value will be printed */
- prec -= nchars;
- }
else
{
- /* Print the integer part */
- for (i = expt; i > 0; i--)
+ /* Handle the case where the value is less than 1.0 (in magnitude) and
+ * will need a leading zero.
+ */
+
+ if (expt <= 0)
{
- obj->put(obj, *digits);
- digits++;
+ /* Print a single zero to the left of the decimal point */
+
+ obj->put(obj, '0');
+
+ /* Print the decimal point */
+
+ obj->put(obj, '.');
+
+ /* Print any leading zeros to the right of the decimal point */
+
+ if (expt < 0)
+ {
+ nchars = MIN(-expt, prec);
+ zeroes(obj, nchars);
+ prec -= nchars;
+ }
}
- /* Print the decimal place */
+ /* Handle the general case where the value is greater than 1.0 (in
+ * magnitude).
+ */
+
+ else
+ {
+ /* Print the integer part to the left of the decimal point */
+
+ for (i = expt; i > 0; i--)
+ {
+ obj->put(obj, *digits);
+ digits++;
+ }
+
+ /* Get the length of the fractional part */
+
+ numlen -= expt;
- obj->put(obj, '.');
+ /* If there is no fractional part, then a decimal point is printed
+ * only in the alternate form or if a particular precision is
+ * requested.
+ */
- /* Print the decimal */
+ if (numlen > 0 || prec > 0 || IS_ALTFORM(flags))
+ {
+ /* Print the decimal point */
+
+ obj->put(obj, '.');
+
+ /* Always print at least one digit to the right of the decimal
+ * point.
+ */
+
+ prec = MAX(1, prec);
+ }
+ }
+
+ /* If a precision was specified, then limit the number digits to the
+ * right of the decimal point.
+ */
+
+ if (prec > 0)
+ {
+ nchars = MIN(numlen, prec);
+ }
+ else
+ {
+ nchars = numlen;
+ }
- numlen -= expt;
- nchars = MIN(numlen, prec);
+ /* Print the fractional part to the right of the decimal point */
for (i = nchars; i > 0; i--)
{
diff --git a/nuttx/lib/stdio/lib_libvsprintf.c b/nuttx/lib/stdio/lib_libvsprintf.c
index 1fb0376a9..2bf095880 100644
--- a/nuttx/lib/stdio/lib_libvsprintf.c
+++ b/nuttx/lib/stdio/lib_libvsprintf.c
@@ -1587,7 +1587,7 @@ int lib_vsprintf(FAR struct lib_outstream_s *obj, FAR const char *src, va_list a
/* Perform left field justification actions */
- prejustify(obj, fmt, flags, width, dblsize);
+ prejustify(obj, fmt, 0, width, dblsize);
/* Output the number */
@@ -1595,7 +1595,7 @@ int lib_vsprintf(FAR struct lib_outstream_s *obj, FAR const char *src, va_list a
/* Perform right field justification actions */
- postjustify(obj, fmt, flags, width, dblsize);
+ postjustify(obj, fmt, 0, width, dblsize);
#else
/* Output the number with a fixed precision */