summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/functions/fprintf.texi3
-rw-r--r--doc/functions/printf.texi3
-rw-r--r--doc/functions/snprintf.texi3
-rw-r--r--doc/functions/sprintf.texi3
-rw-r--r--doc/functions/vfprintf.texi3
-rw-r--r--doc/functions/vprintf.texi3
-rw-r--r--doc/functions/vsnprintf.texi3
-rw-r--r--doc/functions/vsprintf.texi3
-rw-r--r--lib/vasnprintf.c622
-rw-r--r--m4/fprintf-posix.m414
-rw-r--r--m4/printf.m4171
-rw-r--r--m4/snprintf-posix.m422
-rw-r--r--m4/sprintf-posix.m414
-rw-r--r--m4/vasnprintf-posix.m418
-rw-r--r--m4/vasnprintf.m425
-rw-r--r--m4/vasprintf-posix.m418
-rw-r--r--m4/vfprintf-posix.m414
-rw-r--r--m4/vsnprintf-posix.m422
-rw-r--r--m4/vsprintf-posix.m414
-rw-r--r--modules/fprintf-posix1
-rw-r--r--modules/snprintf-posix1
-rw-r--r--modules/sprintf-posix1
-rw-r--r--modules/vasnprintf-posix1
-rw-r--r--modules/vasprintf-posix1
-rw-r--r--modules/vfprintf-posix1
-rw-r--r--modules/vsnprintf-posix1
-rw-r--r--modules/vsprintf-posix1
27 files changed, 879 insertions, 107 deletions
diff --git a/doc/functions/fprintf.texi b/doc/functions/fprintf.texi
index 47382e37e5..5c76d3d874 100644
--- a/doc/functions/fprintf.texi
+++ b/doc/functions/fprintf.texi
@@ -37,6 +37,9 @@ NetBSD 3.0, Cygwin 2006, mingw.
printf @code{"%010f"} of NaN and Infinity yields an incorrect result (padded
with zeroes) on some platforms:
MacOS X 10.3, FreeBSD 6.0, NetBSD 3.0, AIX 5.2, IRIX 6.5, OSF/1 5.1, Solaris 10, Cygwin 2007, mingw.
+@item
+This function can crash in out-of-memory conditions on some platforms:
+MacOS X 10.3, FreeBSD 6.0, NetBSD 3.0.
@end itemize
Portability problems not fixed by Gnulib:
diff --git a/doc/functions/printf.texi b/doc/functions/printf.texi
index 9a729fd28f..dc49ed544f 100644
--- a/doc/functions/printf.texi
+++ b/doc/functions/printf.texi
@@ -37,6 +37,9 @@ NetBSD 3.0, Cygwin 2006, mingw.
printf @code{"%010f"} of NaN and Infinity yields an incorrect result (padded
with zeroes) on some platforms:
MacOS X 10.3, FreeBSD 6.0, NetBSD 3.0, AIX 5.2, IRIX 6.5, OSF/1 5.1, Solaris 10, Cygwin 2007, mingw.
+@item
+This function can crash in out-of-memory conditions on some platforms:
+MacOS X 10.3, FreeBSD 6.0, NetBSD 3.0.
@end itemize
Portability problems not fixed by Gnulib:
diff --git a/doc/functions/snprintf.texi b/doc/functions/snprintf.texi
index fabc2da9b4..a2a81bcffd 100644
--- a/doc/functions/snprintf.texi
+++ b/doc/functions/snprintf.texi
@@ -45,6 +45,9 @@ printf @code{"%010f"} of NaN and Infinity yields an incorrect result (padded
with zeroes) on some platforms:
MacOS X 10.3, FreeBSD 6.0, NetBSD 3.0, AIX 5.2, IRIX 6.5, OSF/1 5.1, Solaris 10, Cygwin 2007, mingw.
@item
+This function can crash in out-of-memory conditions on some platforms:
+MacOS X 10.3, FreeBSD 6.0, NetBSD 3.0.
+@item
This function does not truncate the result as specified in C99 on some platforms:
mingw.
@item
diff --git a/doc/functions/sprintf.texi b/doc/functions/sprintf.texi
index 3ab986f50f..458a36f8a6 100644
--- a/doc/functions/sprintf.texi
+++ b/doc/functions/sprintf.texi
@@ -37,6 +37,9 @@ NetBSD 3.0, Cygwin 2006, mingw.
printf @code{"%010f"} of NaN and Infinity yields an incorrect result (padded
with zeroes) on some platforms:
MacOS X 10.3, FreeBSD 6.0, NetBSD 3.0, AIX 5.2, IRIX 6.5, OSF/1 5.1, Solaris 10, Cygwin 2007, mingw.
+@item
+This function can crash in out-of-memory conditions on some platforms:
+MacOS X 10.3, FreeBSD 6.0, NetBSD 3.0.
@end itemize
Portability problems not fixed by Gnulib:
diff --git a/doc/functions/vfprintf.texi b/doc/functions/vfprintf.texi
index b499323c6f..5726dcb0fb 100644
--- a/doc/functions/vfprintf.texi
+++ b/doc/functions/vfprintf.texi
@@ -37,6 +37,9 @@ NetBSD 3.0, Cygwin 2006, mingw.
printf @code{"%010f"} of NaN and Infinity yields an incorrect result (padded
with zeroes) on some platforms:
MacOS X 10.3, FreeBSD 6.0, NetBSD 3.0, AIX 5.2, IRIX 6.5, OSF/1 5.1, Solaris 10, Cygwin 2007, mingw.
+@item
+This function can crash in out-of-memory conditions on some platforms:
+MacOS X 10.3, FreeBSD 6.0, NetBSD 3.0.
@end itemize
Portability problems not fixed by Gnulib:
diff --git a/doc/functions/vprintf.texi b/doc/functions/vprintf.texi
index cb59dfcd47..62f5fe9746 100644
--- a/doc/functions/vprintf.texi
+++ b/doc/functions/vprintf.texi
@@ -37,6 +37,9 @@ NetBSD 3.0, Cygwin 2006, mingw.
printf @code{"%010f"} of NaN and Infinity yields an incorrect result (padded
with zeroes) on some platforms:
MacOS X 10.3, FreeBSD 6.0, NetBSD 3.0, AIX 5.2, IRIX 6.5, OSF/1 5.1, Solaris 10, Cygwin 2007, mingw.
+@item
+This function can crash in out-of-memory conditions on some platforms:
+MacOS X 10.3, FreeBSD 6.0, NetBSD 3.0.
@end itemize
Portability problems not fixed by Gnulib:
diff --git a/doc/functions/vsnprintf.texi b/doc/functions/vsnprintf.texi
index 99e792db6f..36d4778072 100644
--- a/doc/functions/vsnprintf.texi
+++ b/doc/functions/vsnprintf.texi
@@ -45,6 +45,9 @@ printf @code{"%010f"} of NaN and Infinity yields an incorrect result (padded
with zeroes) on some platforms:
MacOS X 10.3, FreeBSD 6.0, NetBSD 3.0, AIX 5.2, IRIX 6.5, OSF/1 5.1, Solaris 10, Cygwin 2007, mingw.
@item
+This function can crash in out-of-memory conditions on some platforms:
+MacOS X 10.3, FreeBSD 6.0, NetBSD 3.0.
+@item
This function does not truncate the result as specified in C99 on some platforms:
mingw.
@item
diff --git a/doc/functions/vsprintf.texi b/doc/functions/vsprintf.texi
index 1da4959719..bc0ed4c011 100644
--- a/doc/functions/vsprintf.texi
+++ b/doc/functions/vsprintf.texi
@@ -37,6 +37,9 @@ NetBSD 3.0, Cygwin 2006, mingw.
printf @code{"%010f"} of NaN and Infinity yields an incorrect result (padded
with zeroes) on some platforms:
MacOS X 10.3, FreeBSD 6.0, NetBSD 3.0, AIX 5.2, IRIX 6.5, OSF/1 5.1, Solaris 10, Cygwin 2007, mingw.
+@item
+This function can crash in out-of-memory conditions on some platforms:
+MacOS X 10.3, FreeBSD 6.0, NetBSD 3.0.
@end itemize
Portability problems not fixed by Gnulib:
diff --git a/lib/vasnprintf.c b/lib/vasnprintf.c
index 6b4d6c6a51..55202cbe8c 100644
--- a/lib/vasnprintf.c
+++ b/lib/vasnprintf.c
@@ -88,18 +88,17 @@
/* Checked size_t computations. */
#include "xsize.h"
-#if NEED_PRINTF_LONG_DOUBLE && !defined IN_LIBINTL
+#if (NEED_PRINTF_DOUBLE || NEED_PRINTF_LONG_DOUBLE) && !defined IN_LIBINTL
# include <math.h>
# include "float+.h"
-# include "fpucw.h"
#endif
-#if NEED_PRINTF_INFINITE_DOUBLE && !defined IN_LIBINTL
+#if (NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE) && !defined IN_LIBINTL
# include <math.h>
# include "isnan.h"
#endif
-#if NEED_PRINTF_INFINITE_LONG_DOUBLE && !defined IN_LIBINTL
+#if (NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE) && !defined IN_LIBINTL
# include <math.h>
# include "isnanl-nolibm.h"
# include "fpucw.h"
@@ -200,7 +199,7 @@ local_wcslen (const wchar_t *s)
/* Here we need to call the native sprintf, not rpl_sprintf. */
#undef sprintf
-#if (NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE) && !defined IN_LIBINTL
+#if (NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_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
@@ -227,7 +226,7 @@ decimal_point_char ()
# endif
#endif
-#if NEED_PRINTF_INFINITE_DOUBLE && !defined IN_LIBINTL
+#if NEED_PRINTF_INFINITE_DOUBLE && !NEED_PRINTF_DOUBLE && !defined IN_LIBINTL
/* Equivalent to !isfinite(x) || x == 0, but does not require libm. */
static int
@@ -238,7 +237,7 @@ is_infinite_or_zero (double x)
#endif
-#if NEED_PRINTF_INFINITE_LONG_DOUBLE && !defined IN_LIBINTL
+#if NEED_PRINTF_INFINITE_LONG_DOUBLE && !NEED_PRINTF_LONG_DOUBLE && !defined IN_LIBINTL
/* Equivalent to !isfinite(x), but does not require libm. */
static int
@@ -249,7 +248,7 @@ is_infinitel (long double x)
#endif
-#if NEED_PRINTF_LONG_DOUBLE && !defined IN_LIBINTL
+#if (NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_DOUBLE) && !defined IN_LIBINTL
/* Converting 'long double' to decimal without rare rounding bugs requires
real bignums. We use the naming conventions of GNU gmp, but vastly simpler
@@ -795,6 +794,8 @@ convert_to_decimal (mpn_t a, size_t extra_zeroes)
return c_ptr;
}
+# if NEED_PRINTF_LONG_DOUBLE
+
/* Assuming x is finite and >= 0:
write x as x = 2^e * m, where m is a bignum.
Return the allocated memory in case of success, NULL in case of memory
@@ -823,8 +824,8 @@ decode_long_double (long double x, int *ep, mpn_t *mp)
2^31 and 2^32 to 'unsigned int', therefore play safe and cast only
'long double' values between 0 and 2^16 (to 'unsigned int' or 'int',
doesn't matter). */
-# if (LDBL_MANT_BIT % GMP_LIMB_BITS) != 0
-# if (LDBL_MANT_BIT % GMP_LIMB_BITS) > GMP_LIMB_BITS / 2
+# if (LDBL_MANT_BIT % GMP_LIMB_BITS) != 0
+# if (LDBL_MANT_BIT % GMP_LIMB_BITS) > GMP_LIMB_BITS / 2
{
mp_limb_t hi, lo;
y *= (mp_limb_t) 1 << (LDBL_MANT_BIT % (GMP_LIMB_BITS / 2));
@@ -839,7 +840,7 @@ decode_long_double (long double x, int *ep, mpn_t *mp)
abort ();
m.limbs[LDBL_MANT_BIT / GMP_LIMB_BITS] = (hi << (GMP_LIMB_BITS / 2)) | lo;
}
-# else
+# else
{
mp_limb_t d;
y *= (mp_limb_t) 1 << (LDBL_MANT_BIT % GMP_LIMB_BITS);
@@ -849,8 +850,8 @@ decode_long_double (long double x, int *ep, mpn_t *mp)
abort ();
m.limbs[LDBL_MANT_BIT / GMP_LIMB_BITS] = d;
}
+# endif
# endif
-# endif
for (i = LDBL_MANT_BIT / GMP_LIMB_BITS; i > 0; )
{
mp_limb_t hi, lo;
@@ -876,17 +877,101 @@ decode_long_double (long double x, int *ep, mpn_t *mp)
return m.limbs;
}
-/* Assuming x is finite and >= 0, and n is an integer:
+# endif
+
+# if NEED_PRINTF_DOUBLE
+
+/* Assuming x is finite and >= 0:
+ write x as x = 2^e * m, where m is a bignum.
+ Return the allocated memory in case of success, NULL in case of memory
+ allocation failure. */
+static void *
+decode_double (double x, int *ep, mpn_t *mp)
+{
+ mpn_t m;
+ int exp;
+ double y;
+ size_t i;
+
+ /* Allocate memory for result. */
+ m.nlimbs = (DBL_MANT_BIT + GMP_LIMB_BITS - 1) / GMP_LIMB_BITS;
+ m.limbs = (mp_limb_t *) malloc (m.nlimbs * sizeof (mp_limb_t));
+ if (m.limbs == NULL)
+ return NULL;
+ /* Split into exponential part and mantissa. */
+ y = frexp (x, &exp);
+ if (!(y >= 0.0 && y < 1.0))
+ abort ();
+ /* x = 2^exp * y = 2^(exp - DBL_MANT_BIT) * (y * DBL_MANT_BIT), and the
+ latter is an integer. */
+ /* Convert the mantissa (y * DBL_MANT_BIT) to a sequence of limbs.
+ I'm not sure whether it's safe to cast a 'double' value between
+ 2^31 and 2^32 to 'unsigned int', therefore play safe and cast only
+ 'double' values between 0 and 2^16 (to 'unsigned int' or 'int',
+ doesn't matter). */
+# if (DBL_MANT_BIT % GMP_LIMB_BITS) != 0
+# if (DBL_MANT_BIT % GMP_LIMB_BITS) > GMP_LIMB_BITS / 2
+ {
+ mp_limb_t hi, lo;
+ y *= (mp_limb_t) 1 << (DBL_MANT_BIT % (GMP_LIMB_BITS / 2));
+ hi = (int) y;
+ y -= hi;
+ if (!(y >= 0.0 && y < 1.0))
+ abort ();
+ y *= (mp_limb_t) 1 << (GMP_LIMB_BITS / 2);
+ lo = (int) y;
+ y -= lo;
+ if (!(y >= 0.0 && y < 1.0))
+ abort ();
+ m.limbs[DBL_MANT_BIT / GMP_LIMB_BITS] = (hi << (GMP_LIMB_BITS / 2)) | lo;
+ }
+# else
+ {
+ mp_limb_t d;
+ y *= (mp_limb_t) 1 << (DBL_MANT_BIT % GMP_LIMB_BITS);
+ d = (int) y;
+ y -= d;
+ if (!(y >= 0.0 && y < 1.0))
+ abort ();
+ m.limbs[DBL_MANT_BIT / GMP_LIMB_BITS] = d;
+ }
+# endif
+# endif
+ for (i = DBL_MANT_BIT / GMP_LIMB_BITS; i > 0; )
+ {
+ mp_limb_t hi, lo;
+ y *= (mp_limb_t) 1 << (GMP_LIMB_BITS / 2);
+ hi = (int) y;
+ y -= hi;
+ if (!(y >= 0.0 && y < 1.0))
+ abort ();
+ y *= (mp_limb_t) 1 << (GMP_LIMB_BITS / 2);
+ lo = (int) y;
+ y -= lo;
+ if (!(y >= 0.0 && y < 1.0))
+ abort ();
+ m.limbs[--i] = (hi << (GMP_LIMB_BITS / 2)) | lo;
+ }
+ if (!(y == 0.0))
+ abort ();
+ /* Normalise. */
+ while (m.nlimbs > 0 && m.limbs[m.nlimbs - 1] == 0)
+ m.nlimbs--;
+ *mp = m;
+ *ep = exp - DBL_MANT_BIT;
+ return m.limbs;
+}
+
+# endif
+
+/* Assuming x = 2^e * m is finite and >= 0, and n is an integer:
Returns the decimal representation of round (x * 10^n).
Return the allocated memory - containing the decimal digits in low-to-high
order, terminated with a NUL character - in case of success, NULL in case
of memory allocation failure. */
static char *
-scale10_round_decimal_long_double (long double x, int n)
+scale10_round_decimal_decoded (int e, mpn_t m, void *memory, int n)
{
- int e;
- mpn_t m;
- void *memory = decode_long_double (x, &e, &m);
int s;
size_t extra_zeroes;
unsigned int abs_n;
@@ -1099,6 +1184,44 @@ scale10_round_decimal_long_double (long double x, int n)
return digits;
}
+# if NEED_PRINTF_LONG_DOUBLE
+
+/* Assuming x is finite and >= 0, and n is an integer:
+ Returns the decimal representation of round (x * 10^n).
+ Return the allocated memory - containing the decimal digits in low-to-high
+ order, terminated with a NUL character - in case of success, NULL in case
+ of memory allocation failure. */
+static char *
+scale10_round_decimal_long_double (long double x, int n)
+{
+ int e;
+ mpn_t m;
+ void *memory = decode_long_double (x, &e, &m);
+ return scale10_round_decimal_decoded (e, m, memory, n);
+}
+
+# endif
+
+# if NEED_PRINTF_DOUBLE
+
+/* Assuming x is finite and >= 0, and n is an integer:
+ Returns the decimal representation of round (x * 10^n).
+ Return the allocated memory - containing the decimal digits in low-to-high
+ order, terminated with a NUL character - in case of success, NULL in case
+ of memory allocation failure. */
+static char *
+scale10_round_decimal_double (double x, int n)
+{
+ int e;
+ mpn_t m;
+ void *memory = decode_double (x, &e, &m);
+ return scale10_round_decimal_decoded (e, m, memory, n);
+}
+
+# endif
+
+# if NEED_PRINTF_LONG_DOUBLE
+
/* Assuming x is finite and > 0:
Return an approximation for n with 10^n <= x < 10^(n+1).
The approximation is usually the right n, but may be off by 1 sometimes. */
@@ -1186,6 +1309,99 @@ floorlog10l (long double x)
return (int) l + (l < 0 ? -1 : 0);
}
+# endif
+
+# if NEED_PRINTF_DOUBLE
+
+/* Assuming x is finite and > 0:
+ Return an approximation for n with 10^n <= x < 10^(n+1).
+ The approximation is usually the right n, but may be off by 1 sometimes. */
+static int
+floorlog10 (double x)
+{
+ int exp;
+ double y;
+ double z;
+ double l;
+
+ /* Split into exponential part and mantissa. */
+ y = frexp (x, &exp);
+ if (!(y >= 0.0 && y < 1.0))
+ abort ();
+ if (y == 0.0)
+ return INT_MIN;
+ if (y < 0.5)
+ {
+ while (y < (1.0 / (1 << (GMP_LIMB_BITS / 2)) / (1 << (GMP_LIMB_BITS / 2))))
+ {
+ y *= 1.0 * (1 << (GMP_LIMB_BITS / 2)) * (1 << (GMP_LIMB_BITS / 2));
+ exp -= GMP_LIMB_BITS;
+ }
+ if (y < (1.0 / (1 << 16)))
+ {
+ y *= 1.0 * (1 << 16);
+ exp -= 16;
+ }
+ if (y < (1.0 / (1 << 8)))
+ {
+ y *= 1.0 * (1 << 8);
+ exp -= 8;
+ }
+ if (y < (1.0 / (1 << 4)))
+ {
+ y *= 1.0 * (1 << 4);
+ exp -= 4;
+ }
+ if (y < (1.0 / (1 << 2)))
+ {
+ y *= 1.0 * (1 << 2);
+ exp -= 2;
+ }
+ if (y < (1.0 / (1 << 1)))
+ {
+ y *= 1.0 * (1 << 1);
+ exp -= 1;
+ }
+ }
+ if (!(y >= 0.5 && y < 1.0))
+ abort ();
+ /* Compute an approximation for l = log2(x) = exp + log2(y). */
+ l = exp;
+ z = y;
+ if (z < 0.70710678118654752444)
+ {
+ z *= 1.4142135623730950488;
+ l -= 0.5;
+ }
+ if (z < 0.8408964152537145431)
+ {
+ z *= 1.1892071150027210667;
+ l -= 0.25;
+ }
+ if (z < 0.91700404320467123175)
+ {
+ z *= 1.0905077326652576592;
+ l -= 0.125;
+ }
+ if (z < 0.9576032806985736469)
+ {
+ z *= 1.0442737824274138403;
+ l -= 0.0625;
+ }
+ /* Now 0.95 <= z <= 1.01. */
+ z = 1 - z;
+ /* log(1-z) = - 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)));
+ /* Finally multiply with log(2)/log(10), yields an approximation for
+ log10(x). */
+ l *= 0.30102999566398119523;
+ /* Round down to the next integer. */
+ return (int) l + (l < 0 ? -1 : 0);
+}
+
+# endif
+
#endif
DCHAR_T *
@@ -2290,13 +2506,15 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
}
}
#endif
-#if (NEED_PRINTF_INFINITE_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE || NEED_PRINTF_LONG_DOUBLE) && !defined IN_LIBINTL
+#if (NEED_PRINTF_INFINITE_DOUBLE || NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE || NEED_PRINTF_LONG_DOUBLE) && !defined IN_LIBINTL
else if ((dp->conversion == 'f' || dp->conversion == 'F'
|| dp->conversion == 'e' || dp->conversion == 'E'
|| dp->conversion == 'g' || dp->conversion == 'G'
|| dp->conversion == 'a' || dp->conversion == 'A')
&& (0
-# if NEED_PRINTF_INFINITE_DOUBLE
+# if NEED_PRINTF_DOUBLE
+ || a.arg[dp->arg_index].type == TYPE_DOUBLE
+# elif NEED_PRINTF_INFINITE_DOUBLE
|| (a.arg[dp->arg_index].type == TYPE_DOUBLE
/* The systems (mingw) which produce wrong output
for Inf, -Inf, and NaN also do so for -0.0.
@@ -2313,7 +2531,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
# endif
))
{
-# if NEED_PRINTF_INFINITE_DOUBLE && (NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE)
+# if (NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE) && (NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE)
arg_type type = a.arg[dp->arg_index].type;
# endif
int flags = dp->flags;
@@ -2396,17 +2614,21 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
precision = 6;
/* Allocate a temporary buffer of sufficient size. */
-# if NEED_PRINTF_INFINITE_DOUBLE && NEED_PRINTF_LONG_DOUBLE
+# if NEED_PRINTF_DOUBLE && NEED_PRINTF_LONG_DOUBLE
+ tmp_length = (type == TYPE_LONGDOUBLE ? LDBL_DIG + 1 : DBL_DIG + 1);
+# elif NEED_PRINTF_INFINITE_DOUBLE && NEED_PRINTF_LONG_DOUBLE
tmp_length = (type == TYPE_LONGDOUBLE ? LDBL_DIG + 1 : 0);
# elif NEED_PRINTF_LONG_DOUBLE
tmp_length = LDBL_DIG + 1;
+# elif NEED_PRINTF_DOUBLE
+ tmp_length = DBL_DIG + 1;
# else
tmp_length = 0;
# endif
if (tmp_length < precision)
tmp_length = precision;
# if NEED_PRINTF_LONG_DOUBLE
-# if NEED_PRINTF_INFINITE_DOUBLE
+# if NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE
if (type == TYPE_LONGDOUBLE)
# endif
if (dp->conversion == 'f' || dp->conversion == 'F')
@@ -2421,6 +2643,22 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
}
}
# endif
+# if NEED_PRINTF_DOUBLE
+# if NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE
+ if (type == TYPE_DOUBLE)
+# endif
+ if (dp->conversion == 'f' || dp->conversion == 'F')
+ {
+ double arg = a.arg[dp->arg_index].a.a_double;
+ if (!(isnan (arg) || arg + arg == arg))
+ {
+ /* arg is finite and nonzero. */
+ int exponent = floorlog10 (arg < 0 ? -arg : arg);
+ if (exponent >= 0 && tmp_length < exponent + precision)
+ tmp_length = exponent + precision;
+ }
+ }
+# endif
/* Account for sign, decimal point etc. */
tmp_length = xsum (tmp_length, 12);
@@ -2448,7 +2686,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
p = tmp;
# if NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE
-# if NEED_PRINTF_INFINITE_DOUBLE
+# if NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE
if (type == TYPE_LONGDOUBLE)
# endif
{
@@ -2808,13 +3046,12 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
END_LONG_DOUBLE_ROUNDING ();
}
}
-# if NEED_PRINTF_INFINITE_DOUBLE
+# if NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE
else
# endif
# endif
-# if NEED_PRINTF_INFINITE_DOUBLE
+# if NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE
{
- /* Simpler than above: handle only NaN, Infinity, zero. */
double arg = a.arg[dp->arg_index].a.a_double;
if (isnan (arg))
@@ -2832,7 +3069,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
{
int sign = 0;
- if (signbit (arg)) /* arg < 0.0L or negative zero */
+ if (signbit (arg)) /* arg < 0.0 or negative zero */
{
sign = -1;
arg = -arg;
@@ -2858,6 +3095,332 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
}
else
{
+# if NEED_PRINTF_DOUBLE
+ pad_ptr = p;
+
+ if (dp->conversion == 'f' || dp->conversion == 'F')
+ {
+ char *digits;
+ size_t ndigits;
+
+ digits =
+ scale10_round_decimal_double (arg, precision);
+ if (digits == NULL)
+ goto out_of_memory;
+ ndigits = strlen (digits);
+
+ if (ndigits > precision)
+ do
+ {
+ --ndigits;
+ *p++ = digits[ndigits];
+ }
+ while (ndigits > precision);
+ else
+ *p++ = '0';
+ /* Here ndigits <= precision. */
+ if ((flags & FLAG_ALT) || precision > 0)
+ {
+ *p++ = decimal_point_char ();
+ for (; precision > ndigits; precision--)
+ *p++ = '0';
+ while (ndigits > 0)
+ {
+ --ndigits;
+ *p++ = digits[ndigits];
+ }
+ }
+
+ free (digits);
+ }
+ else if (dp->conversion == 'e' || dp->conversion == 'E')
+ {
+ int exponent;
+
+ if (arg == 0.0)
+ {
+ exponent = 0;
+ *p++ = '0';
+ if ((flags & FLAG_ALT) || precision > 0)
+ {
+ *p++ = decimal_point_char ();
+ for (; precision > 0; precision--)
+ *p++ = '0';
+ }
+ }
+ else
+ {
+ /* arg > 0.0. */
+ int adjusted;
+ char *digits;
+ size_t ndigits;
+
+ exponent = floorlog10 (arg);
+ adjusted = 0;
+ for (;;)
+ {
+ digits =
+ scale10_round_decimal_double (arg,
+ (int)precision - exponent);
+ if (digits == NULL)
+ goto out_of_memory;
+ ndigits = strlen (digits);
+
+ if (ndigits == precision + 1)
+ break;
+ if (ndigits < precision
+ || ndigits > precision + 2)
+ /* The exponent was not guessed
+ precisely enough. */
+ abort ();
+ if (adjusted)
+ /* None of two values of exponent is
+ the right one. Prevent an endless
+ loop. */
+ abort ();
+ free (digits);
+ if (ndigits == precision)
+ exponent -= 1;
+ else
+ exponent += 1;
+ adjusted = 1;
+ }
+
+ /* Here ndigits = precision+1. */
+ *p++ = digits[--ndigits];
+ if ((flags & FLAG_ALT) || precision > 0)
+ {
+ *p++ = decimal_point_char ();
+ while (ndigits > 0)
+ {
+ --ndigits;
+ *p++ = digits[ndigits];
+ }
+ }
+
+ free (digits);
+ }
+
+ *p++ = dp->conversion; /* 'e' or 'E' */
+# if WIDE_CHAR_VERSION
+ {
+ static const wchar_t decimal_format[] =
+ /* Produce the same number of exponent digits
+ as the native printf implementation. */
+# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+ { '%', '+', '.', '3', 'd', '\0' };
+# else
+ { '%', '+', '.', '2', 'd', '\0' };
+# endif
+ SNPRINTF (p, 6 + 1, decimal_format, exponent);
+ }
+ while (*p != '\0')
+ p++;
+# else
+ {
+ static const char decimal_format[] =
+ /* Produce the same number of exponent digits
+ as the native printf implementation. */
+# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+ "%+.3d";
+# else
+ "%+.2d";
+# endif
+ if (sizeof (DCHAR_T) == 1)
+ {
+ sprintf ((char *) p, decimal_format, exponent);
+ while (*p != '\0')
+ p++;
+ }
+ else
+ {
+ char expbuf[6 + 1];
+ const char *ep;
+ sprintf (expbuf, decimal_format, exponent);
+ for (ep = expbuf; (*p = *ep) != '\0'; ep++)
+ p++;
+ }
+ }
+# endif
+ }
+ else if (dp->conversion == 'g' || dp->conversion == 'G')
+ {
+ if (precision == 0)
+ precision = 1;
+ /* precision >= 1. */
+
+ if (arg == 0.0)
+ /* The exponent is 0, >= -4, < precision.
+ Use fixed-point notation. */
+ {
+ size_t ndigits = precision;
+ /* Number of trailing zeroes that have to be
+ dropped. */
+ size_t nzeroes =
+ (flags & FLAG_ALT ? 0 : precision - 1);
+
+ --ndigits;
+ *p++ = '0';
+ if ((flags & FLAG_ALT) || ndigits > nzeroes)
+ {
+ *p++ = decimal_point_char ();
+ while (ndigits > nzeroes)
+ {
+ --ndigits;
+ *p++ = '0';
+ }
+ }
+ }
+ else
+ {
+ /* arg > 0.0. */
+ int exponent;
+ int adjusted;
+ char *digits;
+ size_t ndigits;
+ size_t nzeroes;
+
+ exponent = floorlog10 (arg);
+ adjusted = 0;
+ for (;;)
+ {
+ digits =
+ scale10_round_decimal_double (arg,
+ (int)(precision - 1) - exponent);
+ if (digits == NULL)
+ goto out_of_memory;
+ ndigits = strlen (digits);
+
+ if (ndigits == precision)
+ break;
+ if (ndigits < precision - 1
+ || ndigits > precision + 1)
+ /* The exponent was not guessed
+ precisely enough. */
+ abort ();
+ if (adjusted)
+ /* None of two values of exponent is
+ the right one. Prevent an endless
+ loop. */
+ abort ();
+ free (digits);
+ if (ndigits < precision)
+ exponent -= 1;
+ else
+ exponent += 1;
+ adjusted = 1;
+ }
+ /* Here ndigits = precision. */
+
+ /* Determine the number of trailing zeroes
+ that have to be dropped. */
+ nzeroes = 0;
+ if ((flags & FLAG_ALT) == 0)
+ while (nzeroes < ndigits
+ && digits[nzeroes] == '0')
+ nzeroes++;
+
+ /* The exponent is now determined. */
+ if (exponent >= -4
+ && exponent < (long)precision)
+ {
+ /* Fixed-point notation:
+ max(exponent,0)+1 digits, then the
+ decimal point, then the remaining
+ digits without trailing zeroes. */
+ if (exponent >= 0)
+ {
+ size_t count = exponent + 1;
+ /* Note: count <= precision = ndigits. */
+ for (; count > 0; count--)
+ *p++ = digits[--ndigits];
+ if ((flags & FLAG_ALT) || ndigits > nzeroes)
+ {
+ *p++ = decimal_point_char ();
+ while (ndigits > nzeroes)
+ {
+ --ndigits;
+ *p++ = digits[ndigits];
+ }
+ }
+ }
+ else
+ {
+ size_t count = -exponent - 1;
+ *p++ = '0';
+ *p++ = decimal_point_char ();
+ for (; count > 0; count--)
+ *p++ = '0';
+ while (ndigits > nzeroes)
+ {
+ --ndigits;
+ *p++ = digits[ndigits];
+ }
+ }
+ }
+ else
+ {
+ /* Exponential notation. */
+ *p++ = digits[--ndigits];
+ if ((flags & FLAG_ALT) || ndigits > nzeroes)
+ {
+ *p++ = decimal_point_char ();
+ while (ndigits > nzeroes)
+ {
+ --ndigits;
+ *p++ = digits[ndigits];
+ }
+ }
+ *p++ = dp->conversion - 'G' + 'E'; /* 'e' or 'E' */
+# if WIDE_CHAR_VERSION
+ {
+ static const wchar_t decimal_format[] =
+ /* Produce the same number of exponent digits
+ as the native printf implementation. */
+# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+ { '%', '+', '.', '3', 'd', '\0' };
+# else
+ { '%', '+', '.', '2', 'd', '\0' };
+# endif
+ SNPRINTF (p, 6 + 1, decimal_format, exponent);
+ }
+ while (*p != '\0')
+ p++;
+# else
+ {
+ static const char decimal_format[] =
+ /* Produce the same number of exponent digits
+ as the native printf implementation. */
+# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+ "%+.3d";
+# else
+ "%+.2d";
+# endif
+ if (sizeof (DCHAR_T) == 1)
+ {
+ sprintf ((char *) p, decimal_format, exponent);
+ while (*p != '\0')
+ p++;
+ }
+ else
+ {
+ char expbuf[6 + 1];
+ const char *ep;
+ sprintf (expbuf, decimal_format, exponent);
+ for (ep = expbuf; (*p = *ep) != '\0'; ep++)
+ p++;
+ }
+ }
+# endif
+ }
+
+ free (digits);
+ }
+ }
+ else
+ abort ();
+# else
+ /* arg is finite. */
if (!(arg == 0.0))
abort ();
@@ -2886,9 +3449,9 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
*p++ = '+';
/* Produce the same number of exponent digits as
the native printf implementation. */
-# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+# if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
*p++ = '0';
-# endif
+# endif
*p++ = '0';
*p++ = '0';
}
@@ -2906,6 +3469,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
}
else
abort ();
+# endif
}
}
}
diff --git a/m4/fprintf-posix.m4 b/m4/fprintf-posix.m4
index dfade559ff..9908f94121 100644
--- a/m4/fprintf-posix.m4
+++ b/m4/fprintf-posix.m4
@@ -1,4 +1,4 @@
-# fprintf-posix.m4 serial 7
+# fprintf-posix.m4 serial 8
dnl Copyright (C) 2007 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
@@ -17,6 +17,7 @@ AC_DEFUN([gl_FUNC_FPRINTF_POSIX],
AC_REQUIRE([gl_PRINTF_POSITIONS])
AC_REQUIRE([gl_PRINTF_FLAG_GROUPING])
AC_REQUIRE([gl_PRINTF_FLAG_ZERO])
+ AC_REQUIRE([gl_PRINTF_ENOMEM])
gl_cv_func_fprintf_posix=no
case "$gl_cv_func_printf_sizes_c99" in
*yes)
@@ -38,9 +39,13 @@ AC_DEFUN([gl_FUNC_FPRINTF_POSIX],
*yes)
case "$gl_cv_func_printf_flag_zero" in
*yes)
- # fprintf exists and is already POSIX
- # compliant.
- gl_cv_func_fprintf_posix=yes
+ case "$gl_cv_func_printf_enomem" in
+ *yes)
+ # fprintf exists and is already
+ # POSIX compliant.
+ gl_cv_func_fprintf_posix=yes
+ ;;
+ esac
;;
esac
;;
@@ -69,6 +74,7 @@ AC_DEFUN([gl_FUNC_FPRINTF_POSIX],
gl_PREREQ_VASNPRINTF_DIRECTIVE_F
gl_PREREQ_VASNPRINTF_FLAG_GROUPING
gl_PREREQ_VASNPRINTF_FLAG_ZERO
+ gl_PREREQ_VASNPRINTF_ENOMEM
gl_REPLACE_VASNPRINTF
gl_REPLACE_FPRINTF
fi
diff --git a/m4/printf.m4 b/m4/printf.m4
index 8de382b4ff..ab5698edcf 100644
--- a/m4/printf.m4
+++ b/m4/printf.m4
@@ -1,4 +1,4 @@
-# printf.m4 serial 17
+# printf.m4 serial 18
dnl Copyright (C) 2003, 2007 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
@@ -721,6 +721,109 @@ changequote([,])dnl
])
])
+dnl Test whether the *printf family of functions recovers gracefully in case
+dnl of an out-of-memory condition, or whether it crashes the entire program.
+dnl Result is gl_cv_func_printf_enomem.
+
+AC_DEFUN([gl_PRINTF_ENOMEM],
+[
+ AC_REQUIRE([AC_PROG_CC])
+ AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
+ AC_CACHE_CHECK([whether printf survives out-of-memory conditions],
+ [gl_cv_func_printf_enomem],
+ [
+ if test "$cross_compiling" = no; then
+ AC_LANG_CONFTEST([AC_LANG_SOURCE([
+changequote(,)dnl
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <errno.h>
+int main()
+{
+ struct rlimit limit;
+ int ret;
+ /* Some printf implementations allocate temporary space with malloc. */
+ /* On BSD systems, malloc() is limited by RLIMIT_DATA. */
+#ifdef RLIMIT_DATA
+ if (getrlimit (RLIMIT_DATA, &limit) < 0)
+ return 77;
+ if (limit.rlim_max == RLIM_INFINITY || limit.rlim_max > 5000000)
+ limit.rlim_max = 5000000;
+ limit.rlim_cur = limit.rlim_max;
+ if (setrlimit (RLIMIT_DATA, &limit) < 0)
+ return 77;
+#endif
+ /* On Linux systems, malloc() is limited by RLIMIT_AS. */
+#ifdef RLIMIT_AS
+ if (getrlimit (RLIMIT_AS, &limit) < 0)
+ return 77;
+ if (limit.rlim_max == RLIM_INFINITY || limit.rlim_max > 5000000)
+ limit.rlim_max = 5000000;
+ limit.rlim_cur = limit.rlim_max;
+ if (setrlimit (RLIMIT_AS, &limit) < 0)
+ return 77;
+#endif
+ /* Some printf implementations allocate temporary space on the stack. */
+#ifdef RLIMIT_STACK
+ if (getrlimit (RLIMIT_STACK, &limit) < 0)
+ return 77;
+ if (limit.rlim_max == RLIM_INFINITY || limit.rlim_max > 5000000)
+ limit.rlim_max = 5000000;
+ limit.rlim_cur = limit.rlim_max;
+ if (setrlimit (RLIMIT_STACK, &limit) < 0)
+ return 77;
+#endif
+ ret = printf ("%.5000000f", 1.0);
+ return !(ret == 5000002 || (ret < 0 && errno == ENOMEM));
+}
+changequote([,])dnl
+ ])])
+ if AC_TRY_EVAL([ac_link]) && test -s conftest$ac_exeext; then
+ (./conftest
+ result=$?
+ if test $result != 0 && test $result != 77; then result=1; fi
+ exit $result
+ ) >/dev/null 2>/dev/null
+ case $? in
+ 0) gl_cv_func_printf_enomem="yes" ;;
+ 77) gl_cv_func_printf_enomem="guessing no" ;;
+ *) gl_cv_func_printf_enomem="no" ;;
+ esac
+ else
+ gl_cv_func_printf_enomem="guessing no"
+ fi
+ rm -fr conftest*
+ else
+changequote(,)dnl
+ case "$host_os" in
+ # Guess yes on glibc systems.
+ *-gnu*) gl_cv_func_printf_enomem="guessing yes";;
+ # Guess yes on Solaris.
+ solaris*) gl_cv_func_printf_enomem="guessing yes";;
+ # Guess yes on AIX.
+ aix*) gl_cv_func_printf_enomem="guessing yes";;
+ # Guess yes on HP-UX/hppa.
+ hpux*) case "$host_cpu" in
+ hppa*) gl_cv_func_printf_enomem="guessing yes";;
+ *) gl_cv_func_printf_enomem="guessing no";;
+ esac
+ ;;
+ # Guess yes on IRIX.
+ irix*) gl_cv_func_printf_enomem="guessing yes";;
+ # Guess yes on OSF/1.
+ osf*) gl_cv_func_printf_enomem="guessing yes";;
+ # Guess yes on BeOS.
+ beos*) gl_cv_func_printf_enomem="guessing yes";;
+ # If we don't know, assume the worst.
+ *) gl_cv_func_printf_enomem="guessing no";;
+ esac
+changequote([,])dnl
+ fi
+ ])
+])
+
dnl Test whether the snprintf function exists. (ISO C99, POSIX:2001)
dnl Result is ac_cv_func_snprintf.
@@ -1039,11 +1142,12 @@ dnl 7 = gl_PRINTF_DIRECTIVE_N
dnl 8 = gl_PRINTF_POSITIONS
dnl 9 = gl_PRINTF_FLAG_GROUPING
dnl 10 = gl_PRINTF_FLAG_ZERO
-dnl 11 = gl_SNPRINTF_PRESENCE
-dnl 12 = gl_SNPRINTF_TRUNCATION_C99
-dnl 13 = gl_SNPRINTF_RETVAL_C99
-dnl 14 = gl_SNPRINTF_DIRECTIVE_N
-dnl 15 = gl_VSNPRINTF_ZEROSIZE_C99
+dnl 11 = gl_PRINTF_ENOMEM
+dnl 12 = gl_SNPRINTF_PRESENCE
+dnl 13 = gl_SNPRINTF_TRUNCATION_C99
+dnl 14 = gl_SNPRINTF_RETVAL_C99
+dnl 15 = gl_SNPRINTF_DIRECTIVE_N
+dnl 16 = gl_VSNPRINTF_ZEROSIZE_C99
dnl
dnl 1 = checking whether printf supports size specifiers as in C99...
dnl 2 = checking whether printf supports 'long double' arguments...
@@ -1055,33 +1159,34 @@ dnl 7 = checking whether printf supports the 'n' directive...
dnl 8 = checking whether printf supports POSIX/XSI format strings with positions...
dnl 9 = checking whether printf supports the grouping flag...
dnl 10 = checking whether printf supports the zero flag correctly...
-dnl 11 = checking for snprintf...
-dnl 12 = checking whether snprintf truncates the result as in C99...
-dnl 13 = checking whether snprintf returns a byte count as in C99...
-dnl 14 = checking whether snprintf fully supports the 'n' directive...
-dnl 15 = checking whether vsnprintf respects a zero size as in C99...
+dnl 11 = checking whether printf survives out-of-memory conditions...
+dnl 12 = checking for snprintf...
+dnl 13 = checking whether snprintf truncates the result as in C99...
+dnl 14 = checking whether snprintf returns a byte count as in C99...
+dnl 15 = checking whether snprintf fully supports the 'n' directive...
+dnl 16 = checking whether vsnprintf respects a zero size as in C99...
dnl
dnl . = yes, # = no.
dnl
-dnl 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
-dnl glibc 2.5 . . . . . . . . . . . . . . .
-dnl glibc 2.3.6 . . . . # . . . . . . . . . .
-dnl FreeBSD 5.4, 6.1 . . . . # . . . . # . . . . .
-dnl MacOS X 10.3.9 . . . . # . . . . # . . . . .
-dnl OpenBSD 3.9, 4.0 . ? ? ? # ? . . ? ? . . . ? ?
-dnl Cygwin 2007 (= Cygwin 1.5.24) . . . . # # . . . # . . . . .
-dnl Cygwin 2006 (= Cygwin 1.5.19) # . . . # # . . # # . . . . .
-dnl Solaris 10 . . # # # . . . . # . . . . .
-dnl Solaris 2.6 ... 9 # . # # # # . . . # . . . . .
-dnl Solaris 2.5.1 # . # # # # . . . # # # # # #
-dnl AIX 5.2 . . # # # . . . . # . . . . .
-dnl AIX 4.3.2, 5.1 # . # # # # . . . # . . . . .
-dnl HP-UX 11.31 . . . . # . . . . # . . # # .
-dnl HP-UX 10.20, 11.{00,11,23} # . . . # # . . . # . . # # #
-dnl IRIX 6.5 # . # # # # . . . # . . # . .
-dnl OSF/1 5.1 # . # # # # . . . # . . # . #
-dnl OSF/1 4.0d # . # # # # . . . # # # # # #
-dnl NetBSD 4.0 . ? ? ? ? ? . . ? ? . . . ? ?
-dnl NetBSD 3.0 . . . . # # . # # # . . . . .
-dnl BeOS # # . # # # . # . . . . . . .
-dnl mingw # # # # # # . # # # . # # # .
+dnl 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
+dnl glibc 2.5 . . . . . . . . . . . . . . . .
+dnl glibc 2.3.6 . . . . # . . . . . . . . . . .
+dnl FreeBSD 5.4, 6.1 . . . . # . . . . # # . . . . .
+dnl MacOS X 10.3.9 . . . . # . . . . # # . . . . .
+dnl OpenBSD 3.9, 4.0 . ? ? ? # ? . . ? ? ? . . . ? ?
+dnl Cygwin 2007 (= Cygwin 1.5.24) . . . . # # . . . # ? . . . . .
+dnl Cygwin 2006 (= Cygwin 1.5.19) # . . . # # . . # # ? . . . . .
+dnl Solaris 10 . . # # # . . . . # . . . . . .
+dnl Solaris 2.6 ... 9 # . # # # # . . . # . . . . . .
+dnl Solaris 2.5.1 # . # # # # . . . # . # # # # #
+dnl AIX 5.2 . . # # # . . . . # . . . . . .
+dnl AIX 4.3.2, 5.1 # . # # # # . . . # . . . . . .
+dnl HP-UX 11.31 . . . . # . . . . # . . . # # .
+dnl HP-UX 10.20, 11.{00,11,23} # . . . # # . . . # . . . # # #
+dnl IRIX 6.5 # . # # # # . . . # . . . # . .
+dnl OSF/1 5.1 # . # # # # . . . # . . . # . #
+dnl OSF/1 4.0d # . # # # # . . . # . # # # # #
+dnl NetBSD 4.0 . ? ? ? ? ? . . ? ? ? . . . ? ?
+dnl NetBSD 3.0 . . . . # # . # # # # . . . . .
+dnl BeOS # # . # # # . # . . ? . . . . .
+dnl mingw # # # # # # . # # # ? . # # # .
diff --git a/m4/snprintf-posix.m4 b/m4/snprintf-posix.m4
index d7d451124a..6353d9c634 100644
--- a/m4/snprintf-posix.m4
+++ b/m4/snprintf-posix.m4
@@ -1,4 +1,4 @@
-# snprintf-posix.m4 serial 8
+# snprintf-posix.m4 serial 9
dnl Copyright (C) 2007 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
@@ -17,6 +17,7 @@ AC_DEFUN([gl_FUNC_SNPRINTF_POSIX],
AC_REQUIRE([gl_PRINTF_POSITIONS])
AC_REQUIRE([gl_PRINTF_FLAG_GROUPING])
AC_REQUIRE([gl_PRINTF_FLAG_ZERO])
+ AC_REQUIRE([gl_PRINTF_ENOMEM])
gl_cv_func_snprintf_posix=no
AC_CHECK_FUNCS([snprintf])
if test $ac_cv_func_snprintf = yes; then
@@ -44,17 +45,21 @@ AC_DEFUN([gl_FUNC_SNPRINTF_POSIX],
*yes)
case "$gl_cv_func_printf_flag_zero" in
*yes)
- case "$gl_cv_func_snprintf_truncation_c99" in
+ case "$gl_cv_func_printf_enomem" in
*yes)
- case "$gl_cv_func_snprintf_retval_c99" in
+ case "$gl_cv_func_snprintf_truncation_c99" in
*yes)
- case "$gl_cv_func_snprintf_directive_n" in
+ case "$gl_cv_func_snprintf_retval_c99" in
*yes)
- case "$gl_cv_func_vsnprintf_zerosize_c99" in
+ case "$gl_cv_func_snprintf_directive_n" in
*yes)
- # snprintf exists and is
- # already POSIX compliant.
- gl_cv_func_snprintf_posix=yes
+ case "$gl_cv_func_vsnprintf_zerosize_c99" in
+ *yes)
+ # snprintf exists and is
+ # already POSIX compliant.
+ gl_cv_func_snprintf_posix=yes
+ ;;
+ esac
;;
esac
;;
@@ -92,6 +97,7 @@ AC_DEFUN([gl_FUNC_SNPRINTF_POSIX],
gl_PREREQ_VASNPRINTF_DIRECTIVE_F
gl_PREREQ_VASNPRINTF_FLAG_GROUPING
gl_PREREQ_VASNPRINTF_FLAG_ZERO
+ gl_PREREQ_VASNPRINTF_ENOMEM
gl_REPLACE_VASNPRINTF
gl_REPLACE_SNPRINTF
fi
diff --git a/m4/sprintf-posix.m4 b/m4/sprintf-posix.m4
index 6fc75231f3..8e6fcaa860 100644
--- a/m4/sprintf-posix.m4
+++ b/m4/sprintf-posix.m4
@@ -1,4 +1,4 @@
-# sprintf-posix.m4 serial 7
+# sprintf-posix.m4 serial 8
dnl Copyright (C) 2007 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
@@ -17,6 +17,7 @@ AC_DEFUN([gl_FUNC_SPRINTF_POSIX],
AC_REQUIRE([gl_PRINTF_POSITIONS])
AC_REQUIRE([gl_PRINTF_FLAG_GROUPING])
AC_REQUIRE([gl_PRINTF_FLAG_ZERO])
+ AC_REQUIRE([gl_PRINTF_ENOMEM])
gl_cv_func_sprintf_posix=no
case "$gl_cv_func_printf_sizes_c99" in
*yes)
@@ -38,9 +39,13 @@ AC_DEFUN([gl_FUNC_SPRINTF_POSIX],
*yes)
case "$gl_cv_func_printf_flag_zero" in
*yes)
- # sprintf exists and is already POSIX
- # compliant.
- gl_cv_func_sprintf_posix=yes
+ case "$gl_cv_func_printf_enomem" in
+ *yes)
+ # sprintf exists and is already
+ # POSIX compliant.
+ gl_cv_func_sprintf_posix=yes
+ ;;
+ esac
;;
esac
;;
@@ -69,6 +74,7 @@ AC_DEFUN([gl_FUNC_SPRINTF_POSIX],
gl_PREREQ_VASNPRINTF_DIRECTIVE_F
gl_PREREQ_VASNPRINTF_FLAG_GROUPING
gl_PREREQ_VASNPRINTF_FLAG_ZERO
+ gl_PREREQ_VASNPRINTF_ENOMEM
gl_REPLACE_VASNPRINTF
gl_REPLACE_SPRINTF
fi
diff --git a/m4/vasnprintf-posix.m4 b/m4/vasnprintf-posix.m4
index ecc075f8cd..73b10bafa8 100644
--- a/m4/vasnprintf-posix.m4
+++ b/m4/vasnprintf-posix.m4
@@ -1,4 +1,4 @@
-# vasnprintf-posix.m4 serial 8
+# vasnprintf-posix.m4 serial 9
dnl Copyright (C) 2007 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
@@ -17,6 +17,7 @@ AC_DEFUN([gl_FUNC_VASNPRINTF_POSIX],
AC_REQUIRE([gl_PRINTF_POSITIONS])
AC_REQUIRE([gl_PRINTF_FLAG_GROUPING])
AC_REQUIRE([gl_PRINTF_FLAG_ZERO])
+ AC_REQUIRE([gl_PRINTF_ENOMEM])
gl_cv_func_vasnprintf_posix=no
AC_CHECK_FUNCS_ONCE([vasnprintf])
case "$gl_cv_func_printf_sizes_c99" in
@@ -39,11 +40,15 @@ AC_DEFUN([gl_FUNC_VASNPRINTF_POSIX],
*yes)
case "$gl_cv_func_printf_flag_zero" in
*yes)
- if test $ac_cv_func_vasnprintf = yes; then
- # vasnprintf exists and is already
- # POSIX compliant.
- gl_cv_func_vasnprintf_posix=yes
- fi
+ case "$gl_cv_func_printf_enomem" in
+ *yes)
+ if test $ac_cv_func_vasnprintf = yes; then
+ # vasnprintf exists and is already
+ # POSIX compliant.
+ gl_cv_func_vasnprintf_posix=yes
+ fi
+ ;;
+ esac
;;
esac
;;
@@ -72,6 +77,7 @@ AC_DEFUN([gl_FUNC_VASNPRINTF_POSIX],
gl_PREREQ_VASNPRINTF_DIRECTIVE_F
gl_PREREQ_VASNPRINTF_FLAG_GROUPING
gl_PREREQ_VASNPRINTF_FLAG_ZERO
+ gl_PREREQ_VASNPRINTF_ENOMEM
gl_REPLACE_VASNPRINTF
fi
])
diff --git a/m4/vasnprintf.m4 b/m4/vasnprintf.m4
index ef2de787f0..e9733354e8 100644
--- a/m4/vasnprintf.m4
+++ b/m4/vasnprintf.m4
@@ -1,4 +1,4 @@
-# vasnprintf.m4 serial 20
+# vasnprintf.m4 serial 21
dnl Copyright (C) 2002-2004, 2006-2007 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
@@ -178,6 +178,28 @@ AC_DEFUN([gl_PREREQ_VASNPRINTF_FLAG_ZERO],
esac
])
+# Extra prerequisites of lib/vasnprintf.c for surviving out-of-memory
+# conditions.
+AC_DEFUN([gl_PREREQ_VASNPRINTF_ENOMEM],
+[
+ AC_REQUIRE([gl_PRINTF_ENOMEM])
+ case "$gl_cv_func_printf_enomem" in
+ *yes)
+ ;;
+ *)
+ AC_DEFINE([NEED_PRINTF_ENOMEM], 1,
+ [Define if the vasnprintf implementation needs special code for
+ surviving out-of-memory conditions.])
+ AC_DEFINE([NEED_PRINTF_DOUBLE], 1,
+ [Define if the vasnprintf implementation needs special code for
+ 'double' arguments.])
+ AC_DEFINE([NEED_PRINTF_LONG_DOUBLE], 1,
+ [Define if the vasnprintf implementation needs special code for
+ 'long double' arguments.])
+ ;;
+ esac
+])
+
# Prerequisites of lib/vasnprintf.c including all extras for POSIX compliance.
AC_DEFUN([gl_PREREQ_VASNPRINTF_WITH_EXTRAS],
[
@@ -189,6 +211,7 @@ AC_DEFUN([gl_PREREQ_VASNPRINTF_WITH_EXTRAS],
gl_PREREQ_VASNPRINTF_DIRECTIVE_F
gl_PREREQ_VASNPRINTF_FLAG_GROUPING
gl_PREREQ_VASNPRINTF_FLAG_ZERO
+ gl_PREREQ_VASNPRINTF_ENOMEM
])
# Prerequisites of lib/asnprintf.c.
diff --git a/m4/vasprintf-posix.m4 b/m4/vasprintf-posix.m4
index ab26ef5943..9d63ea3ee3 100644
--- a/m4/vasprintf-posix.m4
+++ b/m4/vasprintf-posix.m4
@@ -1,4 +1,4 @@
-# vasprintf-posix.m4 serial 8
+# vasprintf-posix.m4 serial 9
dnl Copyright (C) 2007 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
@@ -17,6 +17,7 @@ AC_DEFUN([gl_FUNC_VASPRINTF_POSIX],
AC_REQUIRE([gl_PRINTF_POSITIONS])
AC_REQUIRE([gl_PRINTF_FLAG_GROUPING])
AC_REQUIRE([gl_PRINTF_FLAG_ZERO])
+ AC_REQUIRE([gl_PRINTF_ENOMEM])
gl_cv_func_vasprintf_posix=no
AC_CHECK_FUNCS([vasprintf])
case "$gl_cv_func_printf_sizes_c99" in
@@ -39,11 +40,15 @@ AC_DEFUN([gl_FUNC_VASPRINTF_POSIX],
*yes)
case "$gl_cv_func_printf_flag_zero" in
*yes)
- if test $ac_cv_func_vasprintf = yes; then
- # vasprintf exists and is already
- # POSIX compliant.
- gl_cv_func_vasprintf_posix=yes
- fi
+ case "$gl_cv_func_printf_enomem" in
+ *yes)
+ if test $ac_cv_func_vasprintf = yes; then
+ # vasprintf exists and is already
+ # POSIX compliant.
+ gl_cv_func_vasprintf_posix=yes
+ fi
+ ;;
+ esac
;;
esac
;;
@@ -72,6 +77,7 @@ AC_DEFUN([gl_FUNC_VASPRINTF_POSIX],
gl_PREREQ_VASNPRINTF_DIRECTIVE_F
gl_PREREQ_VASNPRINTF_FLAG_GROUPING
gl_PREREQ_VASNPRINTF_FLAG_ZERO
+ gl_PREREQ_VASNPRINTF_ENOMEM
gl_REPLACE_VASNPRINTF
gl_REPLACE_VASPRINTF
fi
diff --git a/m4/vfprintf-posix.m4 b/m4/vfprintf-posix.m4
index aefa6fdf3e..da2b19a567 100644
--- a/m4/vfprintf-posix.m4
+++ b/m4/vfprintf-posix.m4
@@ -1,4 +1,4 @@
-# vfprintf-posix.m4 serial 7
+# vfprintf-posix.m4 serial 8
dnl Copyright (C) 2007 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
@@ -17,6 +17,7 @@ AC_DEFUN([gl_FUNC_VFPRINTF_POSIX],
AC_REQUIRE([gl_PRINTF_POSITIONS])
AC_REQUIRE([gl_PRINTF_FLAG_GROUPING])
AC_REQUIRE([gl_PRINTF_FLAG_ZERO])
+ AC_REQUIRE([gl_PRINTF_ENOMEM])
gl_cv_func_vfprintf_posix=no
case "$gl_cv_func_printf_sizes_c99" in
*yes)
@@ -38,9 +39,13 @@ AC_DEFUN([gl_FUNC_VFPRINTF_POSIX],
*yes)
case "$gl_cv_func_printf_flag_zero" in
*yes)
- # vfprintf exists and is already
- # POSIX compliant.
- gl_cv_func_vfprintf_posix=yes
+ case "$gl_cv_func_printf_enomem" in
+ *yes)
+ # vfprintf exists and is already
+ # POSIX compliant.
+ gl_cv_func_vfprintf_posix=yes
+ ;;
+ esac
;;
esac
;;
@@ -69,6 +74,7 @@ AC_DEFUN([gl_FUNC_VFPRINTF_POSIX],
gl_PREREQ_VASNPRINTF_DIRECTIVE_F
gl_PREREQ_VASNPRINTF_FLAG_GROUPING
gl_PREREQ_VASNPRINTF_FLAG_ZERO
+ gl_PREREQ_VASNPRINTF_ENOMEM
gl_REPLACE_VASNPRINTF
gl_REPLACE_VFPRINTF
fi
diff --git a/m4/vsnprintf-posix.m4 b/m4/vsnprintf-posix.m4
index a4855f3b26..aaf5d2c2c3 100644
--- a/m4/vsnprintf-posix.m4
+++ b/m4/vsnprintf-posix.m4
@@ -1,4 +1,4 @@
-# vsnprintf-posix.m4 serial 8
+# vsnprintf-posix.m4 serial 9
dnl Copyright (C) 2007 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
@@ -17,6 +17,7 @@ AC_DEFUN([gl_FUNC_VSNPRINTF_POSIX],
AC_REQUIRE([gl_PRINTF_POSITIONS])
AC_REQUIRE([gl_PRINTF_FLAG_GROUPING])
AC_REQUIRE([gl_PRINTF_FLAG_ZERO])
+ AC_REQUIRE([gl_PRINTF_ENOMEM])
gl_cv_func_vsnprintf_posix=no
AC_CHECK_FUNCS([vsnprintf])
if test $ac_cv_func_vsnprintf = yes; then
@@ -45,17 +46,21 @@ AC_DEFUN([gl_FUNC_VSNPRINTF_POSIX],
*yes)
case "$gl_cv_func_printf_flag_zero" in
*yes)
- case "$gl_cv_func_snprintf_truncation_c99" in
+ case "$gl_cv_func_printf_enomem" in
*yes)
- case "$gl_cv_func_snprintf_retval_c99" in
+ case "$gl_cv_func_snprintf_truncation_c99" in
*yes)
- case "$gl_cv_func_snprintf_directive_n" in
+ case "$gl_cv_func_snprintf_retval_c99" in
*yes)
- case "$gl_cv_func_vsnprintf_zerosize_c99" in
+ case "$gl_cv_func_snprintf_directive_n" in
*yes)
- # vsnprintf exists and is
- # already POSIX compliant.
- gl_cv_func_vsnprintf_posix=yes
+ case "$gl_cv_func_vsnprintf_zerosize_c99" in
+ *yes)
+ # vsnprintf exists and is
+ # already POSIX compliant.
+ gl_cv_func_vsnprintf_posix=yes
+ ;;
+ esac
;;
esac
;;
@@ -93,6 +98,7 @@ AC_DEFUN([gl_FUNC_VSNPRINTF_POSIX],
gl_PREREQ_VASNPRINTF_DIRECTIVE_F
gl_PREREQ_VASNPRINTF_FLAG_GROUPING
gl_PREREQ_VASNPRINTF_FLAG_ZERO
+ gl_PREREQ_VASNPRINTF_ENOMEM
gl_REPLACE_VASNPRINTF
gl_REPLACE_VSNPRINTF
fi
diff --git a/m4/vsprintf-posix.m4 b/m4/vsprintf-posix.m4
index 144fc585a1..48ca6eff63 100644
--- a/m4/vsprintf-posix.m4
+++ b/m4/vsprintf-posix.m4
@@ -1,4 +1,4 @@
-# vsprintf-posix.m4 serial 7
+# vsprintf-posix.m4 serial 8
dnl Copyright (C) 2007 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
@@ -17,6 +17,7 @@ AC_DEFUN([gl_FUNC_VSPRINTF_POSIX],
AC_REQUIRE([gl_PRINTF_POSITIONS])
AC_REQUIRE([gl_PRINTF_FLAG_GROUPING])
AC_REQUIRE([gl_PRINTF_FLAG_ZERO])
+ AC_REQUIRE([gl_PRINTF_ENOMEM])
gl_cv_func_vsprintf_posix=no
case "$gl_cv_func_printf_sizes_c99" in
*yes)
@@ -38,9 +39,13 @@ AC_DEFUN([gl_FUNC_VSPRINTF_POSIX],
*yes)
case "$gl_cv_func_printf_flag_zero" in
*yes)
- # vsprintf exists and is already
- # POSIX compliant.
- gl_cv_func_vsprintf_posix=yes
+ case "$gl_cv_func_printf_enomem" in
+ *yes)
+ # vsprintf exists and is already
+ # POSIX compliant.
+ gl_cv_func_vsprintf_posix=yes
+ ;;
+ esac
;;
esac
;;
@@ -69,6 +74,7 @@ AC_DEFUN([gl_FUNC_VSPRINTF_POSIX],
gl_PREREQ_VASNPRINTF_DIRECTIVE_F
gl_PREREQ_VASNPRINTF_FLAG_GROUPING
gl_PREREQ_VASNPRINTF_FLAG_ZERO
+ gl_PREREQ_VASNPRINTF_ENOMEM
gl_REPLACE_VASNPRINTF
gl_REPLACE_VSPRINTF
fi
diff --git a/modules/fprintf-posix b/modules/fprintf-posix
index 40e606c12c..22db09c902 100644
--- a/modules/fprintf-posix
+++ b/modules/fprintf-posix
@@ -12,6 +12,7 @@ fseterr
vasnprintf
isnan-nolibm
isnanl-nolibm
+frexp-nolibm
frexpl-nolibm
printf-frexp
printf-frexpl
diff --git a/modules/snprintf-posix b/modules/snprintf-posix
index 0a5e8d6936..62fad88e89 100644
--- a/modules/snprintf-posix
+++ b/modules/snprintf-posix
@@ -11,6 +11,7 @@ snprintf
vasnprintf
isnan-nolibm
isnanl-nolibm
+frexp-nolibm
frexpl-nolibm
printf-frexp
printf-frexpl
diff --git a/modules/sprintf-posix b/modules/sprintf-posix
index 0ae1ef4436..2fb663269e 100644
--- a/modules/sprintf-posix
+++ b/modules/sprintf-posix
@@ -11,6 +11,7 @@ stdio
vasnprintf
isnan-nolibm
isnanl-nolibm
+frexp-nolibm
frexpl-nolibm
printf-frexp
printf-frexpl
diff --git a/modules/vasnprintf-posix b/modules/vasnprintf-posix
index b701718242..c2a927f596 100644
--- a/modules/vasnprintf-posix
+++ b/modules/vasnprintf-posix
@@ -10,6 +10,7 @@ Depends-on:
vasnprintf
isnan-nolibm
isnanl-nolibm
+frexp-nolibm
frexpl-nolibm
printf-frexp
printf-frexpl
diff --git a/modules/vasprintf-posix b/modules/vasprintf-posix
index 2b75dff791..e9f898ab94 100644
--- a/modules/vasprintf-posix
+++ b/modules/vasprintf-posix
@@ -10,6 +10,7 @@ vasprintf
vasnprintf
isnan-nolibm
isnanl-nolibm
+frexp-nolibm
frexpl-nolibm
printf-frexp
printf-frexpl
diff --git a/modules/vfprintf-posix b/modules/vfprintf-posix
index 7d0b8cd39f..31352f22d4 100644
--- a/modules/vfprintf-posix
+++ b/modules/vfprintf-posix
@@ -12,6 +12,7 @@ fseterr
vasnprintf
isnan-nolibm
isnanl-nolibm
+frexp-nolibm
frexpl-nolibm
printf-frexp
printf-frexpl
diff --git a/modules/vsnprintf-posix b/modules/vsnprintf-posix
index fc499995ab..c86b7e4daa 100644
--- a/modules/vsnprintf-posix
+++ b/modules/vsnprintf-posix
@@ -11,6 +11,7 @@ vsnprintf
vasnprintf
isnan-nolibm
isnanl-nolibm
+frexp-nolibm
frexpl-nolibm
printf-frexp
printf-frexpl
diff --git a/modules/vsprintf-posix b/modules/vsprintf-posix
index d96745cfc6..aaf7b5d108 100644
--- a/modules/vsprintf-posix
+++ b/modules/vsprintf-posix
@@ -11,6 +11,7 @@ stdio
vasnprintf
isnan-nolibm
isnanl-nolibm
+frexp-nolibm
frexpl-nolibm
printf-frexp
printf-frexpl