vasnprintf: support Irix 5.3
authorEric Blake <ebb9@byu.net>
Tue, 16 Sep 2008 15:36:24 +0000 (09:36 -0600)
committerEric Blake <ebb9@byu.net>
Tue, 16 Sep 2008 15:37:13 +0000 (09:37 -0600)
* 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 <ebb9@byu.net>
ChangeLog
lib/vasnprintf.c

index 86939ec..47fbf01 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,12 @@
 2008-09-16  Bruno Haible  <bruno@clisp.org>
+       and Eric Blake  <ebb9@byu.net>
+
+       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  <bruno@clisp.org>
 
        * doc/glibc-functions/scandir.texi: Mention the function is missing on
        Solaris 9.
index 4ddf45f..ace8933 100644 (file)
@@ -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
                          }