#if (NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE) && !defined IN_LIBINTL
# include <math.h>
-# include "isnand.h"
+# include "isnand-nolibm.h"
#endif
#if (NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE) && !defined IN_LIBINTL
#if (NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_DOUBLE) && !defined IN_LIBINTL
# include <math.h>
-# include "isnand.h"
+# include "isnand-nolibm.h"
# include "printf-frexp.h"
#endif
# endif
#else
/* TCHAR_T is char. */
-# /* Use snprintf if it exists under the name 'snprintf' or '_snprintf'.
+ /* Use snprintf if it exists under the name 'snprintf' or '_snprintf'.
But don't use it on BeOS, since BeOS snprintf produces no output if the
- size argument is >= 0x3000000. */
-# if (HAVE_DECL__SNPRINTF || HAVE_SNPRINTF) && !defined __BEOS__
+ size argument is >= 0x3000000.
+ Also don't use it on Linux libc5, since there snprintf with size = 1
+ writes any output without bounds, like sprintf. */
+# if (HAVE_DECL__SNPRINTF || HAVE_SNPRINTF) && !defined __BEOS__ && !(__GNU_LIBRARY__ == 1)
# define USE_SNPRINTF 1
# else
# define USE_SNPRINTF 0
/* Here we need to call the native sprintf, not rpl_sprintf. */
#undef sprintf
-#if (NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE) && !defined IN_LIBINTL
+/* GCC >= 4.0 with -Wall emits unjustified "... may be used uninitialized"
+ warnings in this file. Use -Dlint to suppress them. */
+#ifdef lint
+# define IF_LINT(Code) Code
+#else
+# define IF_LINT(Code) /* empty */
+#endif
+
+/* Avoid some warnings from "gcc -Wshadow".
+ This file doesn't use the exp() and remainder() functions. */
+#undef exp
+#define exp expo
+#undef remainder
+#define remainder rem
+
+#if (NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE || NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE) && !defined IN_LIBINTL
/* Determine the decimal-point character according to the current locale. */
# ifndef decimal_point_char_defined
# define decimal_point_char_defined 1
#if NEED_PRINTF_INFINITE_LONG_DOUBLE && !NEED_PRINTF_LONG_DOUBLE && !defined IN_LIBINTL
-/* Equivalent to !isfinite(x), but does not require libm. */
+/* Equivalent to !isfinite(x) || x == 0, but does not require libm. */
static int
-is_infinitel (long double x)
+is_infinite_or_zerol (long double x)
{
- return isnanl (x) || (x + x == x && x != 0.0L);
+ return isnanl (x) || x + x == x;
}
#endif
static char *
scale10_round_decimal_long_double (long double x, int n)
{
- int e;
+ int e IF_LINT(= 0);
mpn_t m;
void *memory = decode_long_double (x, &e, &m);
return scale10_round_decimal_decoded (e, m, memory, n);
static char *
scale10_round_decimal_double (double x, int n)
{
- int e;
+ int e IF_LINT(= 0);
mpn_t m;
void *memory = decode_double (x, &e, &m);
return scale10_round_decimal_decoded (e, m, memory, n);
}
/* Now 0.95 <= z <= 1.01. */
z = 1 - z;
- /* log(1-z) = - z - z^2/2 - z^3/3 - z^4/4 - ...
+ /* log2(1-z) = 1/log(2) * (- z - z^2/2 - z^3/3 - z^4/4 - ...)
Four terms are enough to get an approximation with error < 10^-7. */
- l -= z * (1.0 + z * (0.5 + z * ((1.0 / 3) + z * 0.25)));
+ l -= 1.4426950408889634074 * z * (1.0 + z * (0.5 + z * ((1.0 / 3) + z * 0.25)));
/* Finally multiply with log(2)/log(10), yields an approximation for
log10(x). */
l *= 0.30102999566398119523;
}
/* Now 0.95 <= z <= 1.01. */
z = 1 - z;
- /* log(1-z) = - z - z^2/2 - z^3/3 - z^4/4 - ...
+ /* log2(1-z) = 1/log(2) * (- z - z^2/2 - z^3/3 - z^4/4 - ...)
Four terms are enough to get an approximation with error < 10^-7. */
- l -= z * (1.0 + z * (0.5 + z * ((1.0 / 3) + z * 0.25)));
+ l -= 1.4426950408889634074 * z * (1.0 + z * (0.5 + z * ((1.0 / 3) + z * 0.25)));
/* Finally multiply with log(2)/log(10), yields an approximation for
log10(x). */
l *= 0.30102999566398119523;
# endif
+/* Tests whether a string of digits consists of exactly PRECISION zeroes and
+ a single '1' digit. */
+static int
+is_borderline (const char *digits, size_t precision)
+{
+ for (; precision > 0; precision--, digits++)
+ if (*digits != '0')
+ return 0;
+ if (*digits != '1')
+ return 0;
+ digits++;
+ return *digits == '\0';
+}
+
#endif
DCHAR_T *
# elif NEED_PRINTF_INFINITE_LONG_DOUBLE
|| (a.arg[dp->arg_index].type == TYPE_LONGDOUBLE
/* Some systems produce wrong output for Inf,
- -Inf, and NaN. */
- && is_infinitel (a.arg[dp->arg_index].a.a_longdouble))
+ -Inf, and NaN. Some systems in this category
+ (IRIX 5.3) also do so for -0.0. Therefore we
+ treat this case here as well. */
+ && is_infinite_or_zerol (a.arg[dp->arg_index].a.a_longdouble))
# endif
))
{
/* POSIX specifies the default precision to be 6 for %f, %F,
%e, %E, but not for %g, %G. Implementations appear to use
- the same default precision also for %g, %G. */
+ the same default precision also for %g, %G. But for %a, %A,
+ the default precision is 0. */
if (!has_precision)
- precision = 6;
+ if (!(dp->conversion == 'a' || dp->conversion == 'A'))
+ precision = 6;
/* Allocate a temporary buffer of sufficient size. */
# if NEED_PRINTF_DOUBLE && NEED_PRINTF_LONG_DOUBLE
exponent += 1;
adjusted = 1;
}
-
/* Here ndigits = precision+1. */
+ if (is_borderline (digits, precision))
+ {
+ /* Maybe the exponent guess was too high
+ and a smaller exponent can be reached
+ by turning a 10...0 into 9...9x. */
+ char *digits2 =
+ scale10_round_decimal_long_double (arg,
+ (int)precision - exponent + 1);
+ if (digits2 == NULL)
+ {
+ free (digits);
+ END_LONG_DOUBLE_ROUNDING ();
+ goto out_of_memory;
+ }
+ if (strlen (digits2) == precision + 1)
+ {
+ free (digits);
+ digits = digits2;
+ exponent -= 1;
+ }
+ else
+ free (digits2);
+ }
+ /* Here ndigits = precision+1. */
+
*p++ = digits[--ndigits];
if ((flags & FLAG_ALT) || precision > 0)
{
adjusted = 1;
}
/* Here ndigits = precision. */
+ if (is_borderline (digits, precision - 1))
+ {
+ /* Maybe the exponent guess was too high
+ and a smaller exponent can be reached
+ by turning a 10...0 into 9...9x. */
+ char *digits2 =
+ scale10_round_decimal_long_double (arg,
+ (int)(precision - 1) - exponent + 1);
+ if (digits2 == NULL)
+ {
+ free (digits);
+ END_LONG_DOUBLE_ROUNDING ();
+ goto out_of_memory;
+ }
+ if (strlen (digits2) == precision)
+ {
+ free (digits);
+ digits = digits2;
+ exponent -= 1;
+ }
+ else
+ free (digits2);
+ }
+ /* Here ndigits = precision. */
/* Determine the number of trailing zeroes
that have to be dropped. */
abort ();
# else
/* arg is finite. */
- abort ();
+ if (!(arg == 0.0L))
+ abort ();
+
+ pad_ptr = p;
+
+ if (dp->conversion == 'f' || dp->conversion == 'F')
+ {
+ *p++ = '0';
+ if ((flags & FLAG_ALT) || precision > 0)
+ {
+ *p++ = decimal_point_char ();
+ for (; precision > 0; precision--)
+ *p++ = '0';
+ }
+ }
+ else if (dp->conversion == 'e' || dp->conversion == 'E')
+ {
+ *p++ = '0';
+ if ((flags & FLAG_ALT) || precision > 0)
+ {
+ *p++ = decimal_point_char ();
+ for (; precision > 0; precision--)
+ *p++ = '0';
+ }
+ *p++ = dp->conversion; /* 'e' or 'E' */
+ *p++ = '+';
+ *p++ = '0';
+ *p++ = '0';
+ }
+ else if (dp->conversion == 'g' || dp->conversion == 'G')
+ {
+ *p++ = '0';
+ if (flags & FLAG_ALT)
+ {
+ size_t ndigits =
+ (precision > 0 ? precision - 1 : 0);
+ *p++ = decimal_point_char ();
+ for (; ndigits > 0; --ndigits)
+ *p++ = '0';
+ }
+ }
+ else if (dp->conversion == 'a' || dp->conversion == 'A')
+ {
+ *p++ = '0';
+ *p++ = dp->conversion - 'A' + 'X';
+ pad_ptr = p;
+ *p++ = '0';
+ if ((flags & FLAG_ALT) || precision > 0)
+ {
+ *p++ = decimal_point_char ();
+ for (; precision > 0; precision--)
+ *p++ = '0';
+ }
+ *p++ = dp->conversion - 'A' + 'P';
+ *p++ = '+';
+ *p++ = '0';
+ }
+ else
+ abort ();
# endif
}
exponent += 1;
adjusted = 1;
}
-
/* Here ndigits = precision+1. */
+ if (is_borderline (digits, precision))
+ {
+ /* Maybe the exponent guess was too high
+ and a smaller exponent can be reached
+ by turning a 10...0 into 9...9x. */
+ char *digits2 =
+ scale10_round_decimal_double (arg,
+ (int)precision - exponent + 1);
+ if (digits2 == NULL)
+ {
+ free (digits);
+ goto out_of_memory;
+ }
+ if (strlen (digits2) == precision + 1)
+ {
+ free (digits);
+ digits = digits2;
+ exponent -= 1;
+ }
+ else
+ free (digits2);
+ }
+ /* Here ndigits = precision+1. */
+
*p++ = digits[--ndigits];
if ((flags & FLAG_ALT) || precision > 0)
{
adjusted = 1;
}
/* Here ndigits = precision. */
+ if (is_borderline (digits, precision - 1))
+ {
+ /* Maybe the exponent guess was too high
+ and a smaller exponent can be reached
+ by turning a 10...0 into 9...9x. */
+ char *digits2 =
+ scale10_round_decimal_double (arg,
+ (int)(precision - 1) - exponent + 1);
+ if (digits2 == NULL)
+ {
+ free (digits);
+ goto out_of_memory;
+ }
+ if (strlen (digits2) == precision)
+ {
+ free (digits);
+ digits = digits2;
+ exponent -= 1;
+ }
+ else
+ free (digits2);
+ }
+ /* Here ndigits = precision. */
/* Determine the number of trailing zeroes
that have to be dropped. */
#endif
TCHAR_T *fbp;
unsigned int prefix_count;
- int prefixes[2];
+ int prefixes[2] IF_LINT (= { 0 });
#if !USE_SNPRINTF
size_t tmp_length;
TCHAR_T tmpbuf[700];
abort ();
prefixes[prefix_count++] = a.arg[dp->width_arg_index].a.a_int;
}
- if (dp->precision_arg_index != ARG_NONE)
+ if (!prec_ourselves && dp->precision_arg_index != ARG_NONE)
{
if (!(a.arg[dp->precision_arg_index].type == TYPE_INT))
abort ();