bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

vasnprintf(-0.0L) on Irix [was: snapshot in preparation for m4 1.4.12]


From: Eric Blake
Subject: vasnprintf(-0.0L) on Irix [was: snapshot in preparation for m4 1.4.12]
Date: Tue, 16 Sep 2008 15:44:50 +0000 (UTC)
User-agent: Loom/3.14 (http://gmane.org/)

Bruno Haible <bruno <at> clisp.org> writes:

> > > the system sprintf does not know how to print -0, so the result is
> > > 0.000000 and lacks -.  Does it make more sense to adjust the existing
> > > gl_PRINTF_INFINITE_LONG_DOUBLE (which also tests for NaN) to add a test
> > > for negative zero, or to add a new macro gl_PRINTF_ZERO_LONG_DOUBLE?
> 
> Based on this info, I would have recommended to add a separate test to
> m4/printf.m4, for clarity; however, in vasnprintf.m4 there are enough
> #ifdefs, therefore I would simply have defined 
NEED_PRINTF_INFINITE_LONG_DOUBLE.
> 
> > At any rate, the Irix box also failed the infinite long double test, so it
> > already has problem with inf and/or NaN, and the place to add code for
> > -0.0 should be relatively easy to locate.
> 
> In this situation, m4/printf.m4 needs no changes at all. Find here a
> proposed fix:
> 
> Bruno
> 
> --- lib/vasnprintf.c.orig     2008-09-13 19:02:12.000000000 +0200
> +++ lib/vasnprintf.c  2008-09-13 19:01:42.000000000 +0200
> @@ -255,11 +255,11 @@
> 
>  #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.  */

Close, but without the rest of the patch, this triggered an abort in 
vasnprintf.  However, with both pieces in place, I've tested that Irix 5.3 
passes the testsuite.  So here's what I'm pushing:

From: Eric Blake <address@hidden>
Date: Tue, 16 Sep 2008 09:36:24 -0600
Subject: [PATCH] vasnprintf: support Irix 5.3

* lib/vasnprintf.c (VASNPRINTF): Also handle -0.0L on platforms
that mishandle long double infinity.
Reported by Tom G. Christensen.

Signed-off-by: Eric Blake <address@hidden>
---
 ChangeLog        |    8 +++++++
 lib/vasnprintf.c |   61 ++++++++++++++++++++++++++++++++++++++++++++++++-----
 2 files changed, 63 insertions(+), 6 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 86939ec..47fbf01 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,12 @@
 2008-09-16  Bruno Haible  <address@hidden>
+       and Eric Blake  <address@hidden>
+
+       vasnprintf: support Irix 5.3
+       * lib/vasnprintf.c (VASNPRINTF): Also handle -0.0L on platforms
+       that mishandle long double infinity.
+       Reported by Tom G. Christensen.
+
+2008-09-16  Bruno Haible  <address@hidden>
 
        * doc/glibc-functions/scandir.texi: Mention the function is missing on
        Solaris 9.
diff --git a/lib/vasnprintf.c b/lib/vasnprintf.c
index 4ddf45f..ace8933 100644
--- a/lib/vasnprintf.c
+++ b/lib/vasnprintf.c
@@ -255,11 +255,11 @@ is_infinite_or_zero (double x)
 
 #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
@@ -2578,8 +2578,10 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
 # 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
                        ))
              {
@@ -3139,7 +3141,54 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
                              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++ = '+';
+                               /* Produce the same number of exponent digits as
+                                  the native printf implementation.  */
+#   if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
+                               *p++ = '0';
+#   endif
+                               *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
+                             abort ();
 #  endif
                          }
 
-- 
1.6.0







reply via email to

[Prev in Thread] Current Thread [Next in Thread]