* m4/include_next.m4 (gl_CHECK_NEXT_HEADERS): Check some typos
[gnulib.git] / tests / test-vasprintf-posix.c
index 3cf430f..3d7aa43 100644 (file)
 
 /* Written by Bruno Haible <bruno@clisp.org>, 2007.  */
 
-#ifdef HAVE_CONFIG_H
-# include <config.h>
-#endif
+#include <config.h>
 
 #include <stdio.h>
 
+#include <float.h>
 #include <stdarg.h>
 #include <stddef.h>
 #include <stdio.h>
@@ -54,6 +53,28 @@ NaN ()
 # define NaN() (0.0 / 0.0)
 #endif
 
+/* The SGI MIPS floating-point format does not distinguish 0.0 and -0.0.  */
+static int
+have_minus_zero ()
+{
+  static double plus_zero = 0.0;
+  static double minus_zero = -0.0;
+  return memcmp (&plus_zero, &minus_zero, sizeof (double)) != 0;
+}
+
+/* Representation of an 80-bit 'long double' as an initializer for a sequence
+   of 'unsigned int' words.  */
+#ifdef WORDS_BIGENDIAN
+# define LDBL80_WORDS(exponent,manthi,mantlo) \
+    { ((unsigned int) (exponent) << 16) | ((unsigned int) (manthi) >> 16), \
+      ((unsigned int) (manthi) << 16) | (unsigned int) (mantlo) >> 16),    \
+      (unsigned int) (mantlo) << 16                                        \
+    }
+#else
+# define LDBL80_WORDS(exponent,manthi,mantlo) \
+    { mantlo, manthi, exponent }
+#endif
+
 static int
 strmatch (const char *pattern, const char *string)
 {
@@ -65,6 +86,27 @@ strmatch (const char *pattern, const char *string)
   return 1;
 }
 
+/* Test whether string[start_index..end_index-1] is a valid textual
+   representation of NaN.  */
+static int
+strisnan (const char *string, size_t start_index, size_t end_index, int uppercase)
+{
+  if (start_index < end_index)
+    {
+      if (string[start_index] == '-')
+       start_index++;
+      if (start_index + 3 <= end_index
+         && memcmp (string + start_index, uppercase ? "NAN" : "nan", 3) == 0)
+       {
+         start_index += 3;
+         if (start_index == end_index
+             || (string[start_index] == '(' && string[end_index - 1] == ')'))
+           return 1;
+       }
+    }
+  return 0;
+}
+         
 static void
 test_function (int (*my_asprintf) (char **, const char *, ...))
 {
@@ -168,7 +210,8 @@ test_function (int (*my_asprintf) (char **, const char *, ...))
     int retval =
       my_asprintf (&result, "%a %d", -0.0, 33, 44, 55);
     ASSERT (result != NULL);
-    ASSERT (strcmp (result, "-0x0p+0 33") == 0);
+    if (have_minus_zero ())
+      ASSERT (strcmp (result, "-0x0p+0 33") == 0);
     ASSERT (retval == strlen (result));
     free (result);
   }
@@ -198,7 +241,9 @@ test_function (int (*my_asprintf) (char **, const char *, ...))
     int retval =
       my_asprintf (&result, "%a %d", NaN (), 33, 44, 55);
     ASSERT (result != NULL);
-    ASSERT (strcmp (result, "nan 33") == 0);
+    ASSERT (strlen (result) >= 3 + 3
+           && strisnan (result, 0, strlen (result) - 3, 0)
+           && strcmp (result + strlen (result) - 3, " 33") == 0);
     ASSERT (retval == strlen (result));
     free (result);
   }
@@ -427,11 +472,13 @@ test_function (int (*my_asprintf) (char **, const char *, ...))
   { /* FLAG_ZERO with NaN.  */
     char *result;
     int retval =
-      my_asprintf (&result, "%010a %d", NaN (), 33, 44, 55);
+      my_asprintf (&result, "%050a %d", NaN (), 33, 44, 55);
     ASSERT (result != NULL);
     /* "0000000nan 33" is not a valid result; see
        <http://lists.gnu.org/archive/html/bug-gnulib/2007-04/msg00107.html> */
-    ASSERT (strcmp (result, "       nan 33") == 0);
+    ASSERT (strlen (result) == 50 + 3
+           && strisnan (result, strspn (result, " "), strlen (result) - 3, 0)
+           && strcmp (result + strlen (result) - 3, " 33") == 0);
     ASSERT (retval == strlen (result));
     free (result);
   }
@@ -477,7 +524,8 @@ test_function (int (*my_asprintf) (char **, const char *, ...))
     int retval =
       my_asprintf (&result, "%La %d", -0.0L, 33, 44, 55);
     ASSERT (result != NULL);
-    ASSERT (strcmp (result, "-0x0p+0 33") == 0);
+    if (have_minus_zero ())
+      ASSERT (strcmp (result, "-0x0p+0 33") == 0);
     ASSERT (retval == strlen (result));
     free (result);
   }
@@ -507,10 +555,113 @@ test_function (int (*my_asprintf) (char **, const char *, ...))
     int retval =
       my_asprintf (&result, "%La %d", 0.0L / 0.0L, 33, 44, 55);
     ASSERT (result != NULL);
-    ASSERT (strcmp (result, "nan 33") == 0);
+    ASSERT (strlen (result) >= 3 + 3
+           && strisnan (result, 0, strlen (result) - 3, 0)
+           && strcmp (result + strlen (result) - 3, " 33") == 0);
+    ASSERT (retval == strlen (result));
+    free (result);
+  }
+#if CHECK_PRINTF_SAFE && ((defined __ia64 && LDBL_MANT_DIG == 64) || (defined __x86_64__ || defined __amd64__) || (defined __i386 || defined __i386__ || defined _I386 || defined _M_IX86 || defined _X86_))
+  { /* Quiet NaN.  */
+    static union { unsigned int word[4]; long double value; } x =
+      { LDBL80_WORDS (0xFFFF, 0xC3333333, 0x00000000) };
+    char *result;
+    int retval =
+      my_asprintf (&result, "%La %d", x.value, 33, 44, 55);
+    ASSERT (result != NULL);
+    ASSERT (strlen (result) >= 3 + 3
+           && strisnan (result, 0, strlen (result) - 3, 0)
+           && strcmp (result + strlen (result) - 3, " 33") == 0);
+    ASSERT (retval == strlen (result));
+    free (result);
+  }
+  {
+    /* Signalling NaN.  */
+    static union { unsigned int word[4]; long double value; } x =
+      { LDBL80_WORDS (0xFFFF, 0x83333333, 0x00000000) };
+    char *result;
+    int retval =
+      my_asprintf (&result, "%La %d", x.value, 33, 44, 55);
+    ASSERT (result != NULL);
+    ASSERT (strlen (result) >= 3 + 3
+           && strisnan (result, 0, strlen (result) - 3, 0)
+           && strcmp (result + strlen (result) - 3, " 33") == 0);
+    ASSERT (retval == strlen (result));
+    free (result);
+  }
+  /* The isnanl function should recognize Pseudo-NaNs, Pseudo-Infinities,
+     Pseudo-Zeroes, Unnormalized Numbers, and Pseudo-Denormals, as defined in
+       Intel IA-64 Architecture Software Developer's Manual, Volume 1:
+       Application Architecture.
+       Table 5-2 "Floating-Point Register Encodings"
+       Figure 5-6 "Memory to Floating-Point Register Data Translation"
+   */
+  { /* Pseudo-NaN.  */
+    static union { unsigned int word[4]; long double value; } x =
+      { LDBL80_WORDS (0xFFFF, 0x40000001, 0x00000000) };
+    char *result;
+    int retval =
+      my_asprintf (&result, "%La %d", x.value, 33, 44, 55);
+    ASSERT (result != NULL);
+    ASSERT (strlen (result) >= 3 + 3
+           && strisnan (result, 0, strlen (result) - 3, 0)
+           && strcmp (result + strlen (result) - 3, " 33") == 0);
+    ASSERT (retval == strlen (result));
+    free (result);
+  }
+  { /* Pseudo-Infinity.  */
+    static union { unsigned int word[4]; long double value; } x =
+      { LDBL80_WORDS (0xFFFF, 0x00000000, 0x00000000) };
+    char *result;
+    int retval =
+      my_asprintf (&result, "%La %d", x.value, 33, 44, 55);
+    ASSERT (result != NULL);
+    ASSERT (strlen (result) >= 3 + 3
+           && strisnan (result, 0, strlen (result) - 3, 0)
+           && strcmp (result + strlen (result) - 3, " 33") == 0);
+    ASSERT (retval == strlen (result));
+    free (result);
+  }
+  { /* Pseudo-Zero.  */
+    static union { unsigned int word[4]; long double value; } x =
+      { LDBL80_WORDS (0x4004, 0x00000000, 0x00000000) };
+    char *result;
+    int retval =
+      my_asprintf (&result, "%La %d", x.value, 33, 44, 55);
+    ASSERT (result != NULL);
+    ASSERT (strlen (result) >= 3 + 3
+           && strisnan (result, 0, strlen (result) - 3, 0)
+           && strcmp (result + strlen (result) - 3, " 33") == 0);
+    ASSERT (retval == strlen (result));
+    free (result);
+  }
+  { /* Unnormalized number.  */
+    static union { unsigned int word[4]; long double value; } x =
+      { LDBL80_WORDS (0x4000, 0x63333333, 0x00000000) };
+    char *result;
+    int retval =
+      my_asprintf (&result, "%La %d", x.value, 33, 44, 55);
+    ASSERT (result != NULL);
+    ASSERT (strlen (result) >= 3 + 3
+           && strisnan (result, 0, strlen (result) - 3, 0)
+           && strcmp (result + strlen (result) - 3, " 33") == 0);
+    ASSERT (retval == strlen (result));
+    free (result);
+  }
+  { /* Pseudo-Denormal.  */
+    static union { unsigned int word[4]; long double value; } x =
+      { LDBL80_WORDS (0x0000, 0x83333333, 0x00000000) };
+    char *result;
+    int retval =
+      my_asprintf (&result, "%La %d", x.value, 33, 44, 55);
+    ASSERT (result != NULL);
+    ASSERT (strlen (result) >= 3 + 3
+           && strisnan (result, 0, strlen (result) - 3, 0)
+           && strcmp (result + strlen (result) - 3, " 33") == 0);
     ASSERT (retval == strlen (result));
     free (result);
   }
+#endif
 
   { /* Rounding near the decimal point.  */
     char *result;
@@ -737,11 +888,13 @@ test_function (int (*my_asprintf) (char **, const char *, ...))
   { /* FLAG_ZERO with NaN.  */
     char *result;
     int retval =
-      my_asprintf (&result, "%010La %d", 0.0L / 0.0L, 33, 44, 55);
+      my_asprintf (&result, "%050La %d", 0.0L / 0.0L, 33, 44, 55);
     ASSERT (result != NULL);
     /* "0000000nan 33" is not a valid result; see
        <http://lists.gnu.org/archive/html/bug-gnulib/2007-04/msg00107.html> */
-    ASSERT (strcmp (result, "       nan 33") == 0);
+    ASSERT (strlen (result) == 50 + 3
+           && strisnan (result, strspn (result, " "), strlen (result) - 3, 0)
+           && strcmp (result + strlen (result) - 3, " 33") == 0);
     ASSERT (retval == strlen (result));
     free (result);
   }
@@ -884,7 +1037,8 @@ test_function (int (*my_asprintf) (char **, const char *, ...))
     int retval =
       my_asprintf (&result, "%f %d", -0.0, 33, 44, 55);
     ASSERT (result != NULL);
-    ASSERT (strcmp (result, "-0.000000 33") == 0);
+    if (have_minus_zero ())
+      ASSERT (strcmp (result, "-0.000000 33") == 0);
     ASSERT (retval == strlen (result));
     free (result);
   }
@@ -916,7 +1070,9 @@ test_function (int (*my_asprintf) (char **, const char *, ...))
     int retval =
       my_asprintf (&result, "%f %d", NaN (), 33, 44, 55);
     ASSERT (result != NULL);
-    ASSERT (strcmp (result, "nan 33") == 0);
+    ASSERT (strlen (result) >= 3 + 3
+           && strisnan (result, 0, strlen (result) - 3, 0)
+           && strcmp (result + strlen (result) - 3, " 33") == 0);
     ASSERT (retval == strlen (result));
     free (result);
   }
@@ -1005,9 +1161,11 @@ test_function (int (*my_asprintf) (char **, const char *, ...))
   { /* FLAG_ZERO with NaN.  */
     char *result;
     int retval =
-      my_asprintf (&result, "%015f %d", NaN (), 33, 44, 55);
+      my_asprintf (&result, "%050f %d", NaN (), 33, 44, 55);
     ASSERT (result != NULL);
-    ASSERT (strcmp (result, "            nan 33") == 0);
+    ASSERT (strlen (result) == 50 + 3
+           && strisnan (result, strspn (result, " "), strlen (result) - 3, 0)
+           && strcmp (result + strlen (result) - 3, " 33") == 0);
     ASSERT (retval == strlen (result));
     free (result);
   }
@@ -1158,7 +1316,8 @@ test_function (int (*my_asprintf) (char **, const char *, ...))
     int retval =
       my_asprintf (&result, "%Lf %d", -0.0L, 33, 44, 55);
     ASSERT (result != NULL);
-    ASSERT (strcmp (result, "-0.000000 33") == 0);
+    if (have_minus_zero ())
+      ASSERT (strcmp (result, "-0.000000 33") == 0);
     ASSERT (retval == strlen (result));
     free (result);
   }
@@ -1191,10 +1350,113 @@ test_function (int (*my_asprintf) (char **, const char *, ...))
     int retval =
       my_asprintf (&result, "%Lf %d", zero / zero, 33, 44, 55);
     ASSERT (result != NULL);
-    ASSERT (strcmp (result, "nan 33") == 0);
+    ASSERT (strlen (result) >= 3 + 3
+           && strisnan (result, 0, strlen (result) - 3, 0)
+           && strcmp (result + strlen (result) - 3, " 33") == 0);
+    ASSERT (retval == strlen (result));
+    free (result);
+  }
+#if CHECK_PRINTF_SAFE && ((defined __ia64 && LDBL_MANT_DIG == 64) || (defined __x86_64__ || defined __amd64__) || (defined __i386 || defined __i386__ || defined _I386 || defined _M_IX86 || defined _X86_))
+  { /* Quiet NaN.  */
+    static union { unsigned int word[4]; long double value; } x =
+      { LDBL80_WORDS (0xFFFF, 0xC3333333, 0x00000000) };
+    char *result;
+    int retval =
+      my_asprintf (&result, "%Lf %d", x.value, 33, 44, 55);
+    ASSERT (result != NULL);
+    ASSERT (strlen (result) >= 3 + 3
+           && strisnan (result, 0, strlen (result) - 3, 0)
+           && strcmp (result + strlen (result) - 3, " 33") == 0);
     ASSERT (retval == strlen (result));
     free (result);
   }
+  {
+    /* Signalling NaN.  */
+    static union { unsigned int word[4]; long double value; } x =
+      { LDBL80_WORDS (0xFFFF, 0x83333333, 0x00000000) };
+    char *result;
+    int retval =
+      my_asprintf (&result, "%Lf %d", x.value, 33, 44, 55);
+    ASSERT (result != NULL);
+    ASSERT (strlen (result) >= 3 + 3
+           && strisnan (result, 0, strlen (result) - 3, 0)
+           && strcmp (result + strlen (result) - 3, " 33") == 0);
+    ASSERT (retval == strlen (result));
+    free (result);
+  }
+  /* The isnanl function should recognize Pseudo-NaNs, Pseudo-Infinities,
+     Pseudo-Zeroes, Unnormalized Numbers, and Pseudo-Denormals, as defined in
+       Intel IA-64 Architecture Software Developer's Manual, Volume 1:
+       Application Architecture.
+       Table 5-2 "Floating-Point Register Encodings"
+       Figure 5-6 "Memory to Floating-Point Register Data Translation"
+   */
+  { /* Pseudo-NaN.  */
+    static union { unsigned int word[4]; long double value; } x =
+      { LDBL80_WORDS (0xFFFF, 0x40000001, 0x00000000) };
+    char *result;
+    int retval =
+      my_asprintf (&result, "%Lf %d", x.value, 33, 44, 55);
+    ASSERT (result != NULL);
+    ASSERT (strlen (result) >= 3 + 3
+           && strisnan (result, 0, strlen (result) - 3, 0)
+           && strcmp (result + strlen (result) - 3, " 33") == 0);
+    ASSERT (retval == strlen (result));
+    free (result);
+  }
+  { /* Pseudo-Infinity.  */
+    static union { unsigned int word[4]; long double value; } x =
+      { LDBL80_WORDS (0xFFFF, 0x00000000, 0x00000000) };
+    char *result;
+    int retval =
+      my_asprintf (&result, "%Lf %d", x.value, 33, 44, 55);
+    ASSERT (result != NULL);
+    ASSERT (strlen (result) >= 3 + 3
+           && strisnan (result, 0, strlen (result) - 3, 0)
+           && strcmp (result + strlen (result) - 3, " 33") == 0);
+    ASSERT (retval == strlen (result));
+    free (result);
+  }
+  { /* Pseudo-Zero.  */
+    static union { unsigned int word[4]; long double value; } x =
+      { LDBL80_WORDS (0x4004, 0x00000000, 0x00000000) };
+    char *result;
+    int retval =
+      my_asprintf (&result, "%Lf %d", x.value, 33, 44, 55);
+    ASSERT (result != NULL);
+    ASSERT (strlen (result) >= 3 + 3
+           && strisnan (result, 0, strlen (result) - 3, 0)
+           && strcmp (result + strlen (result) - 3, " 33") == 0);
+    ASSERT (retval == strlen (result));
+    free (result);
+  }
+  { /* Unnormalized number.  */
+    static union { unsigned int word[4]; long double value; } x =
+      { LDBL80_WORDS (0x4000, 0x63333333, 0x00000000) };
+    char *result;
+    int retval =
+      my_asprintf (&result, "%Lf %d", x.value, 33, 44, 55);
+    ASSERT (result != NULL);
+    ASSERT (strlen (result) >= 3 + 3
+           && strisnan (result, 0, strlen (result) - 3, 0)
+           && strcmp (result + strlen (result) - 3, " 33") == 0);
+    ASSERT (retval == strlen (result));
+    free (result);
+  }
+  { /* Pseudo-Denormal.  */
+    static union { unsigned int word[4]; long double value; } x =
+      { LDBL80_WORDS (0x0000, 0x83333333, 0x00000000) };
+    char *result;
+    int retval =
+      my_asprintf (&result, "%Lf %d", x.value, 33, 44, 55);
+    ASSERT (result != NULL);
+    ASSERT (strlen (result) >= 3 + 3
+           && strisnan (result, 0, strlen (result) - 3, 0)
+           && strcmp (result + strlen (result) - 3, " 33") == 0);
+    ASSERT (retval == strlen (result));
+    free (result);
+  }
+#endif
 
   { /* Width.  */
     char *result;
@@ -1281,9 +1543,11 @@ test_function (int (*my_asprintf) (char **, const char *, ...))
     static long double zero = 0.0L;
     char *result;
     int retval =
-      my_asprintf (&result, "%015Lf %d", zero / zero, 33, 44, 55);
+      my_asprintf (&result, "%050Lf %d", zero / zero, 33, 44, 55);
     ASSERT (result != NULL);
-    ASSERT (strcmp (result, "            nan 33") == 0);
+    ASSERT (strlen (result) == 50 + 3
+           && strisnan (result, strspn (result, " "), strlen (result) - 3, 0)
+           && strcmp (result + strlen (result) - 3, " 33") == 0);
     ASSERT (retval == strlen (result));
     free (result);
   }
@@ -1345,7 +1609,8 @@ test_function (int (*my_asprintf) (char **, const char *, ...))
     int retval =
       my_asprintf (&result, "%F %d", -0.0, 33, 44, 55);
     ASSERT (result != NULL);
-    ASSERT (strcmp (result, "-0.000000 33") == 0);
+    if (have_minus_zero ())
+      ASSERT (strcmp (result, "-0.000000 33") == 0);
     ASSERT (retval == strlen (result));
     free (result);
   }
@@ -1377,7 +1642,9 @@ test_function (int (*my_asprintf) (char **, const char *, ...))
     int retval =
       my_asprintf (&result, "%F %d", NaN (), 33, 44, 55);
     ASSERT (result != NULL);
-    ASSERT (strcmp (result, "NAN 33") == 0);
+    ASSERT (strlen (result) >= 3 + 3
+           && strisnan (result, 0, strlen (result) - 3, 1)
+           && strcmp (result + strlen (result) - 3, " 33") == 0);
     ASSERT (retval == strlen (result));
     free (result);
   }
@@ -1458,7 +1725,8 @@ test_function (int (*my_asprintf) (char **, const char *, ...))
     int retval =
       my_asprintf (&result, "%LF %d", -0.0L, 33, 44, 55);
     ASSERT (result != NULL);
-    ASSERT (strcmp (result, "-0.000000 33") == 0);
+    if (have_minus_zero ())
+      ASSERT (strcmp (result, "-0.000000 33") == 0);
     ASSERT (retval == strlen (result));
     free (result);
   }
@@ -1491,7 +1759,9 @@ test_function (int (*my_asprintf) (char **, const char *, ...))
     int retval =
       my_asprintf (&result, "%LF %d", zero / zero, 33, 44, 55);
     ASSERT (result != NULL);
-    ASSERT (strcmp (result, "NAN 33") == 0);
+    ASSERT (strlen (result) >= 3 + 3
+           && strisnan (result, 0, strlen (result) - 3, 1)
+           && strcmp (result + strlen (result) - 3, " 33") == 0);
     ASSERT (retval == strlen (result));
     free (result);
   }
@@ -1534,7 +1804,8 @@ test_function (int (*my_asprintf) (char **, const char *, ...))
     int retval =
       my_asprintf (&result, "%e %d", 12.75, 33, 44, 55);
     ASSERT (result != NULL);
-    ASSERT (strcmp (result, "1.275000e+01 33") == 0);
+    ASSERT (strcmp (result, "1.275000e+01 33") == 0
+           || strcmp (result, "1.275000e+001 33") == 0);
     ASSERT (retval == strlen (result));
     free (result);
   }
@@ -1544,7 +1815,8 @@ test_function (int (*my_asprintf) (char **, const char *, ...))
     int retval =
       my_asprintf (&result, "%e %d", 1234567.0, 33, 44, 55);
     ASSERT (result != NULL);
-    ASSERT (strcmp (result, "1.234567e+06 33") == 0);
+    ASSERT (strcmp (result, "1.234567e+06 33") == 0
+           || strcmp (result, "1.234567e+006 33") == 0);
     ASSERT (retval == strlen (result));
     free (result);
   }
@@ -1633,8 +1905,16 @@ test_function (int (*my_asprintf) (char **, const char *, ...))
        char *result;
        int retval =
          my_asprintf (&result, "%e", data[k].value);
+       const char *expected = data[k].string;
        ASSERT (result != NULL);
-       ASSERT (strmatch (data[k].string, result));
+       ASSERT (strcmp (result, expected) == 0
+               /* Some implementations produce exponents with 3 digits.  */
+               || (strlen (result) == strlen (expected) + 1
+                   && memcmp (result, expected, strlen (expected) - 2) == 0
+                   && result[strlen (expected) - 2] == '0'
+                   && strcmp (result + strlen (expected) - 1,
+                              expected + strlen (expected) - 2)
+                      == 0));
        ASSERT (retval == strlen (result));
        free (result);
       }
@@ -1645,7 +1925,8 @@ test_function (int (*my_asprintf) (char **, const char *, ...))
     int retval =
       my_asprintf (&result, "%e %d", -0.03125, 33, 44, 55);
     ASSERT (result != NULL);
-    ASSERT (strcmp (result, "-3.125000e-02 33") == 0);
+    ASSERT (strcmp (result, "-3.125000e-02 33") == 0
+           || strcmp (result, "-3.125000e-002 33") == 0);
     ASSERT (retval == strlen (result));
     free (result);
   }
@@ -1655,7 +1936,8 @@ test_function (int (*my_asprintf) (char **, const char *, ...))
     int retval =
       my_asprintf (&result, "%e %d", 0.0, 33, 44, 55);
     ASSERT (result != NULL);
-    ASSERT (strcmp (result, "0.000000e+00 33") == 0);
+    ASSERT (strcmp (result, "0.000000e+00 33") == 0
+           || strcmp (result, "0.000000e+000 33") == 0);
     ASSERT (retval == strlen (result));
     free (result);
   }
@@ -1665,7 +1947,9 @@ test_function (int (*my_asprintf) (char **, const char *, ...))
     int retval =
       my_asprintf (&result, "%e %d", -0.0, 33, 44, 55);
     ASSERT (result != NULL);
-    ASSERT (strcmp (result, "-0.000000e+00 33") == 0);
+    if (have_minus_zero ())
+      ASSERT (strcmp (result, "-0.000000e+00 33") == 0
+             || strcmp (result, "-0.000000e+000 33") == 0);
     ASSERT (retval == strlen (result));
     free (result);
   }
@@ -1697,7 +1981,9 @@ test_function (int (*my_asprintf) (char **, const char *, ...))
     int retval =
       my_asprintf (&result, "%e %d", NaN (), 33, 44, 55);
     ASSERT (result != NULL);
-    ASSERT (strcmp (result, "nan 33") == 0);
+    ASSERT (strlen (result) >= 3 + 3
+           && strisnan (result, 0, strlen (result) - 3, 0)
+           && strcmp (result + strlen (result) - 3, " 33") == 0);
     ASSERT (retval == strlen (result));
     free (result);
   }
@@ -1707,7 +1993,8 @@ test_function (int (*my_asprintf) (char **, const char *, ...))
     int retval =
       my_asprintf (&result, "%15e %d", 1.75, 33, 44, 55);
     ASSERT (result != NULL);
-    ASSERT (strcmp (result, "   1.750000e+00 33") == 0);
+    ASSERT (strcmp (result, "   1.750000e+00 33") == 0
+           || strcmp (result, "  1.750000e+000 33") == 0);
     ASSERT (retval == strlen (result));
     free (result);
   }
@@ -1717,7 +2004,8 @@ test_function (int (*my_asprintf) (char **, const char *, ...))
     int retval =
       my_asprintf (&result, "%-15e %d", 1.75, 33, 44, 55);
     ASSERT (result != NULL);
-    ASSERT (strcmp (result, "1.750000e+00    33") == 0);
+    ASSERT (strcmp (result, "1.750000e+00    33") == 0
+           || strcmp (result, "1.750000e+000   33") == 0);
     ASSERT (retval == strlen (result));
     free (result);
   }
@@ -1727,7 +2015,8 @@ test_function (int (*my_asprintf) (char **, const char *, ...))
     int retval =
       my_asprintf (&result, "%+e %d", 1.75, 33, 44, 55);
     ASSERT (result != NULL);
-    ASSERT (strcmp (result, "+1.750000e+00 33") == 0);
+    ASSERT (strcmp (result, "+1.750000e+00 33") == 0
+           || strcmp (result, "+1.750000e+000 33") == 0);
     ASSERT (retval == strlen (result));
     free (result);
   }
@@ -1737,7 +2026,8 @@ test_function (int (*my_asprintf) (char **, const char *, ...))
     int retval =
       my_asprintf (&result, "% e %d", 1.75, 33, 44, 55);
     ASSERT (result != NULL);
-    ASSERT (strcmp (result, " 1.750000e+00 33") == 0);
+    ASSERT (strcmp (result, " 1.750000e+00 33") == 0
+           || strcmp (result, " 1.750000e+000 33") == 0);
     ASSERT (retval == strlen (result));
     free (result);
   }
@@ -1747,7 +2037,8 @@ test_function (int (*my_asprintf) (char **, const char *, ...))
     int retval =
       my_asprintf (&result, "%#e %d", 1.75, 33, 44, 55);
     ASSERT (result != NULL);
-    ASSERT (strcmp (result, "1.750000e+00 33") == 0);
+    ASSERT (strcmp (result, "1.750000e+00 33") == 0
+           || strcmp (result, "1.750000e+000 33") == 0);
     ASSERT (retval == strlen (result));
     free (result);
   }
@@ -1757,7 +2048,8 @@ test_function (int (*my_asprintf) (char **, const char *, ...))
     int retval =
       my_asprintf (&result, "%#.e %d", 1.75, 33, 44, 55);
     ASSERT (result != NULL);
-    ASSERT (strcmp (result, "2.e+00 33") == 0);
+    ASSERT (strcmp (result, "2.e+00 33") == 0
+           || strcmp (result, "2.e+000 33") == 0);
     ASSERT (retval == strlen (result));
     free (result);
   }
@@ -1767,7 +2059,8 @@ test_function (int (*my_asprintf) (char **, const char *, ...))
     int retval =
       my_asprintf (&result, "%#.e %d", 9.75, 33, 44, 55);
     ASSERT (result != NULL);
-    ASSERT (strcmp (result, "1.e+01 33") == 0);
+    ASSERT (strcmp (result, "1.e+01 33") == 0
+           || strcmp (result, "1.e+001 33") == 0);
     ASSERT (retval == strlen (result));
     free (result);
   }
@@ -1777,7 +2070,8 @@ test_function (int (*my_asprintf) (char **, const char *, ...))
     int retval =
       my_asprintf (&result, "%015e %d", 1234.0, 33, 44, 55);
     ASSERT (result != NULL);
-    ASSERT (strcmp (result, "0001.234000e+03 33") == 0);
+    ASSERT (strcmp (result, "0001.234000e+03 33") == 0
+           || strcmp (result, "001.234000e+003 33") == 0);
     ASSERT (retval == strlen (result));
     free (result);
   }
@@ -1796,9 +2090,11 @@ test_function (int (*my_asprintf) (char **, const char *, ...))
   { /* FLAG_ZERO with NaN.  */
     char *result;
     int retval =
-      my_asprintf (&result, "%015e %d", NaN (), 33, 44, 55);
+      my_asprintf (&result, "%050e %d", NaN (), 33, 44, 55);
     ASSERT (result != NULL);
-    ASSERT (strcmp (result, "            nan 33") == 0);
+    ASSERT (strlen (result) == 50 + 3
+           && strisnan (result, strspn (result, " "), strlen (result) - 3, 0)
+           && strcmp (result + strlen (result) - 3, " 33") == 0);
     ASSERT (retval == strlen (result));
     free (result);
   }
@@ -1808,7 +2104,8 @@ test_function (int (*my_asprintf) (char **, const char *, ...))
     int retval =
       my_asprintf (&result, "%.e %d", 1234.0, 33, 44, 55);
     ASSERT (result != NULL);
-    ASSERT (strcmp (result, "1e+03 33") == 0);
+    ASSERT (strcmp (result, "1e+03 33") == 0
+           || strcmp (result, "1e+003 33") == 0);
     ASSERT (retval == strlen (result));
     free (result);
   }
@@ -1918,7 +2215,7 @@ test_function (int (*my_asprintf) (char **, const char *, ...))
        int retval =
          my_asprintf (&result, "%Le", data[k].value);
        ASSERT (result != NULL);
-       ASSERT (strmatch (data[k].string, result));
+       ASSERT (strcmp (result, data[k].string) == 0);
        ASSERT (retval == strlen (result));
        free (result);
       }
@@ -1949,7 +2246,8 @@ test_function (int (*my_asprintf) (char **, const char *, ...))
     int retval =
       my_asprintf (&result, "%Le %d", -0.0L, 33, 44, 55);
     ASSERT (result != NULL);
-    ASSERT (strcmp (result, "-0.000000e+00 33") == 0);
+    if (have_minus_zero ())
+      ASSERT (strcmp (result, "-0.000000e+00 33") == 0);
     ASSERT (retval == strlen (result));
     free (result);
   }
@@ -1982,10 +2280,113 @@ test_function (int (*my_asprintf) (char **, const char *, ...))
     int retval =
       my_asprintf (&result, "%Le %d", zero / zero, 33, 44, 55);
     ASSERT (result != NULL);
-    ASSERT (strcmp (result, "nan 33") == 0);
+    ASSERT (strlen (result) >= 3 + 3
+           && strisnan (result, 0, strlen (result) - 3, 0)
+           && strcmp (result + strlen (result) - 3, " 33") == 0);
     ASSERT (retval == strlen (result));
     free (result);
   }
+#if CHECK_PRINTF_SAFE && ((defined __ia64 && LDBL_MANT_DIG == 64) || (defined __x86_64__ || defined __amd64__) || (defined __i386 || defined __i386__ || defined _I386 || defined _M_IX86 || defined _X86_))
+  { /* Quiet NaN.  */
+    static union { unsigned int word[4]; long double value; } x =
+      { LDBL80_WORDS (0xFFFF, 0xC3333333, 0x00000000) };
+    char *result;
+    int retval =
+      my_asprintf (&result, "%Le %d", x.value, 33, 44, 55);
+    ASSERT (result != NULL);
+    ASSERT (strlen (result) >= 3 + 3
+           && strisnan (result, 0, strlen (result) - 3, 0)
+           && strcmp (result + strlen (result) - 3, " 33") == 0);
+    ASSERT (retval == strlen (result));
+    free (result);
+  }
+  {
+    /* Signalling NaN.  */
+    static union { unsigned int word[4]; long double value; } x =
+      { LDBL80_WORDS (0xFFFF, 0x83333333, 0x00000000) };
+    char *result;
+    int retval =
+      my_asprintf (&result, "%Le %d", x.value, 33, 44, 55);
+    ASSERT (result != NULL);
+    ASSERT (strlen (result) >= 3 + 3
+           && strisnan (result, 0, strlen (result) - 3, 0)
+           && strcmp (result + strlen (result) - 3, " 33") == 0);
+    ASSERT (retval == strlen (result));
+    free (result);
+  }
+  /* The isnanl function should recognize Pseudo-NaNs, Pseudo-Infinities,
+     Pseudo-Zeroes, Unnormalized Numbers, and Pseudo-Denormals, as defined in
+       Intel IA-64 Architecture Software Developer's Manual, Volume 1:
+       Application Architecture.
+       Table 5-2 "Floating-Point Register Encodings"
+       Figure 5-6 "Memory to Floating-Point Register Data Translation"
+   */
+  { /* Pseudo-NaN.  */
+    static union { unsigned int word[4]; long double value; } x =
+      { LDBL80_WORDS (0xFFFF, 0x40000001, 0x00000000) };
+    char *result;
+    int retval =
+      my_asprintf (&result, "%Le %d", x.value, 33, 44, 55);
+    ASSERT (result != NULL);
+    ASSERT (strlen (result) >= 3 + 3
+           && strisnan (result, 0, strlen (result) - 3, 0)
+           && strcmp (result + strlen (result) - 3, " 33") == 0);
+    ASSERT (retval == strlen (result));
+    free (result);
+  }
+  { /* Pseudo-Infinity.  */
+    static union { unsigned int word[4]; long double value; } x =
+      { LDBL80_WORDS (0xFFFF, 0x00000000, 0x00000000) };
+    char *result;
+    int retval =
+      my_asprintf (&result, "%Le %d", x.value, 33, 44, 55);
+    ASSERT (result != NULL);
+    ASSERT (strlen (result) >= 3 + 3
+           && strisnan (result, 0, strlen (result) - 3, 0)
+           && strcmp (result + strlen (result) - 3, " 33") == 0);
+    ASSERT (retval == strlen (result));
+    free (result);
+  }
+  { /* Pseudo-Zero.  */
+    static union { unsigned int word[4]; long double value; } x =
+      { LDBL80_WORDS (0x4004, 0x00000000, 0x00000000) };
+    char *result;
+    int retval =
+      my_asprintf (&result, "%Le %d", x.value, 33, 44, 55);
+    ASSERT (result != NULL);
+    ASSERT (strlen (result) >= 3 + 3
+           && strisnan (result, 0, strlen (result) - 3, 0)
+           && strcmp (result + strlen (result) - 3, " 33") == 0);
+    ASSERT (retval == strlen (result));
+    free (result);
+  }
+  { /* Unnormalized number.  */
+    static union { unsigned int word[4]; long double value; } x =
+      { LDBL80_WORDS (0x4000, 0x63333333, 0x00000000) };
+    char *result;
+    int retval =
+      my_asprintf (&result, "%Le %d", x.value, 33, 44, 55);
+    ASSERT (result != NULL);
+    ASSERT (strlen (result) >= 3 + 3
+           && strisnan (result, 0, strlen (result) - 3, 0)
+           && strcmp (result + strlen (result) - 3, " 33") == 0);
+    ASSERT (retval == strlen (result));
+    free (result);
+  }
+  { /* Pseudo-Denormal.  */
+    static union { unsigned int word[4]; long double value; } x =
+      { LDBL80_WORDS (0x0000, 0x83333333, 0x00000000) };
+    char *result;
+    int retval =
+      my_asprintf (&result, "%Le %d", x.value, 33, 44, 55);
+    ASSERT (result != NULL);
+    ASSERT (strlen (result) >= 3 + 3
+           && strisnan (result, 0, strlen (result) - 3, 0)
+           && strcmp (result + strlen (result) - 3, " 33") == 0);
+    ASSERT (retval == strlen (result));
+    free (result);
+  }
+#endif
 
   { /* Width.  */
     char *result;
@@ -2082,9 +2483,11 @@ test_function (int (*my_asprintf) (char **, const char *, ...))
     static long double zero = 0.0L;
     char *result;
     int retval =
-      my_asprintf (&result, "%015Le %d", zero / zero, 33, 44, 55);
+      my_asprintf (&result, "%050Le %d", zero / zero, 33, 44, 55);
     ASSERT (result != NULL);
-    ASSERT (strcmp (result, "            nan 33") == 0);
+    ASSERT (strlen (result) == 50 + 3
+           && strisnan (result, strspn (result, " "), strlen (result) - 3, 0)
+           && strcmp (result + strlen (result) - 3, " 33") == 0);
     ASSERT (retval == strlen (result));
     free (result);
   }
@@ -2116,7 +2519,8 @@ test_function (int (*my_asprintf) (char **, const char *, ...))
     int retval =
       my_asprintf (&result, "%g %d", 1234567.0, 33, 44, 55);
     ASSERT (result != NULL);
-    ASSERT (strcmp (result, "1.23457e+06 33") == 0);
+    ASSERT (strcmp (result, "1.23457e+06 33") == 0
+           || strcmp (result, "1.23457e+006 33") == 0);
     ASSERT (retval == strlen (result));
     free (result);
   }
@@ -2205,8 +2609,17 @@ test_function (int (*my_asprintf) (char **, const char *, ...))
        char *result;
        int retval =
          my_asprintf (&result, "%g", data[k].value);
+       const char *expected = data[k].string;
        ASSERT (result != NULL);
-       ASSERT (strmatch (data[k].string, result));
+       ASSERT (strcmp (result, expected) == 0
+               /* Some implementations produce exponents with 3 digits.  */
+               || (expected[strlen (expected) - 4] == 'e'
+                   && strlen (result) == strlen (expected) + 1
+                   && memcmp (result, expected, strlen (expected) - 2) == 0
+                   && result[strlen (expected) - 2] == '0'
+                   && strcmp (result + strlen (expected) - 1,
+                              expected + strlen (expected) - 2)
+                      == 0));
        ASSERT (retval == strlen (result));
        free (result);
       }
@@ -2237,7 +2650,8 @@ test_function (int (*my_asprintf) (char **, const char *, ...))
     int retval =
       my_asprintf (&result, "%g %d", -0.0, 33, 44, 55);
     ASSERT (result != NULL);
-    ASSERT (strcmp (result, "-0 33") == 0);
+    if (have_minus_zero ())
+      ASSERT (strcmp (result, "-0 33") == 0);
     ASSERT (retval == strlen (result));
     free (result);
   }
@@ -2269,7 +2683,9 @@ test_function (int (*my_asprintf) (char **, const char *, ...))
     int retval =
       my_asprintf (&result, "%g %d", NaN (), 33, 44, 55);
     ASSERT (result != NULL);
-    ASSERT (strcmp (result, "nan 33") == 0);
+    ASSERT (strlen (result) >= 3 + 3
+           && strisnan (result, 0, strlen (result) - 3, 0)
+           && strcmp (result + strlen (result) - 3, " 33") == 0);
     ASSERT (retval == strlen (result));
     free (result);
   }
@@ -2339,7 +2755,8 @@ test_function (int (*my_asprintf) (char **, const char *, ...))
     int retval =
       my_asprintf (&result, "%#.g %d", 9.75, 33, 44, 55);
     ASSERT (result != NULL);
-    ASSERT (strcmp (result, "1.e+01 33") == 0);
+    ASSERT (strcmp (result, "1.e+01 33") == 0
+           || strcmp (result, "1.e+001 33") == 0);
     ASSERT (retval == strlen (result));
     free (result);
   }
@@ -2368,9 +2785,11 @@ test_function (int (*my_asprintf) (char **, const char *, ...))
   { /* FLAG_ZERO with NaN.  */
     char *result;
     int retval =
-      my_asprintf (&result, "%015g %d", NaN (), 33, 44, 55);
+      my_asprintf (&result, "%050g %d", NaN (), 33, 44, 55);
     ASSERT (result != NULL);
-    ASSERT (strcmp (result, "            nan 33") == 0);
+    ASSERT (strlen (result) == 50 + 3
+           && strisnan (result, strspn (result, " "), strlen (result) - 3, 0)
+           && strcmp (result + strlen (result) - 3, " 33") == 0);
     ASSERT (retval == strlen (result));
     free (result);
   }
@@ -2380,7 +2799,8 @@ test_function (int (*my_asprintf) (char **, const char *, ...))
     int retval =
       my_asprintf (&result, "%.g %d", 1234.0, 33, 44, 55);
     ASSERT (result != NULL);
-    ASSERT (strcmp (result, "1e+03 33") == 0);
+    ASSERT (strcmp (result, "1e+03 33") == 0
+           || strcmp (result, "1e+003 33") == 0);
     ASSERT (retval == strlen (result));
     free (result);
   }
@@ -2490,7 +2910,7 @@ test_function (int (*my_asprintf) (char **, const char *, ...))
        int retval =
          my_asprintf (&result, "%Lg", data[k].value);
        ASSERT (result != NULL);
-       ASSERT (strmatch (data[k].string, result));
+       ASSERT (strcmp (result, data[k].string) == 0);
        ASSERT (retval == strlen (result));
        free (result);
       }
@@ -2521,7 +2941,8 @@ test_function (int (*my_asprintf) (char **, const char *, ...))
     int retval =
       my_asprintf (&result, "%Lg %d", -0.0L, 33, 44, 55);
     ASSERT (result != NULL);
-    ASSERT (strcmp (result, "-0 33") == 0);
+    if (have_minus_zero ())
+      ASSERT (strcmp (result, "-0 33") == 0);
     ASSERT (retval == strlen (result));
     free (result);
   }
@@ -2554,10 +2975,113 @@ test_function (int (*my_asprintf) (char **, const char *, ...))
     int retval =
       my_asprintf (&result, "%Lg %d", zero / zero, 33, 44, 55);
     ASSERT (result != NULL);
-    ASSERT (strcmp (result, "nan 33") == 0);
+    ASSERT (strlen (result) >= 3 + 3
+           && strisnan (result, 0, strlen (result) - 3, 0)
+           && strcmp (result + strlen (result) - 3, " 33") == 0);
+    ASSERT (retval == strlen (result));
+    free (result);
+  }
+#if CHECK_PRINTF_SAFE && ((defined __ia64 && LDBL_MANT_DIG == 64) || (defined __x86_64__ || defined __amd64__) || (defined __i386 || defined __i386__ || defined _I386 || defined _M_IX86 || defined _X86_))
+  { /* Quiet NaN.  */
+    static union { unsigned int word[4]; long double value; } x =
+      { LDBL80_WORDS (0xFFFF, 0xC3333333, 0x00000000) };
+    char *result;
+    int retval =
+      my_asprintf (&result, "%Lg %d", x.value, 33, 44, 55);
+    ASSERT (result != NULL);
+    ASSERT (strlen (result) >= 3 + 3
+           && strisnan (result, 0, strlen (result) - 3, 0)
+           && strcmp (result + strlen (result) - 3, " 33") == 0);
+    ASSERT (retval == strlen (result));
+    free (result);
+  }
+  {
+    /* Signalling NaN.  */
+    static union { unsigned int word[4]; long double value; } x =
+      { LDBL80_WORDS (0xFFFF, 0x83333333, 0x00000000) };
+    char *result;
+    int retval =
+      my_asprintf (&result, "%Lg %d", x.value, 33, 44, 55);
+    ASSERT (result != NULL);
+    ASSERT (strlen (result) >= 3 + 3
+           && strisnan (result, 0, strlen (result) - 3, 0)
+           && strcmp (result + strlen (result) - 3, " 33") == 0);
+    ASSERT (retval == strlen (result));
+    free (result);
+  }
+  /* The isnanl function should recognize Pseudo-NaNs, Pseudo-Infinities,
+     Pseudo-Zeroes, Unnormalized Numbers, and Pseudo-Denormals, as defined in
+       Intel IA-64 Architecture Software Developer's Manual, Volume 1:
+       Application Architecture.
+       Table 5-2 "Floating-Point Register Encodings"
+       Figure 5-6 "Memory to Floating-Point Register Data Translation"
+   */
+  { /* Pseudo-NaN.  */
+    static union { unsigned int word[4]; long double value; } x =
+      { LDBL80_WORDS (0xFFFF, 0x40000001, 0x00000000) };
+    char *result;
+    int retval =
+      my_asprintf (&result, "%Lg %d", x.value, 33, 44, 55);
+    ASSERT (result != NULL);
+    ASSERT (strlen (result) >= 3 + 3
+           && strisnan (result, 0, strlen (result) - 3, 0)
+           && strcmp (result + strlen (result) - 3, " 33") == 0);
+    ASSERT (retval == strlen (result));
+    free (result);
+  }
+  { /* Pseudo-Infinity.  */
+    static union { unsigned int word[4]; long double value; } x =
+      { LDBL80_WORDS (0xFFFF, 0x00000000, 0x00000000) };
+    char *result;
+    int retval =
+      my_asprintf (&result, "%Lg %d", x.value, 33, 44, 55);
+    ASSERT (result != NULL);
+    ASSERT (strlen (result) >= 3 + 3
+           && strisnan (result, 0, strlen (result) - 3, 0)
+           && strcmp (result + strlen (result) - 3, " 33") == 0);
+    ASSERT (retval == strlen (result));
+    free (result);
+  }
+  { /* Pseudo-Zero.  */
+    static union { unsigned int word[4]; long double value; } x =
+      { LDBL80_WORDS (0x4004, 0x00000000, 0x00000000) };
+    char *result;
+    int retval =
+      my_asprintf (&result, "%Lg %d", x.value, 33, 44, 55);
+    ASSERT (result != NULL);
+    ASSERT (strlen (result) >= 3 + 3
+           && strisnan (result, 0, strlen (result) - 3, 0)
+           && strcmp (result + strlen (result) - 3, " 33") == 0);
     ASSERT (retval == strlen (result));
     free (result);
   }
+  { /* Unnormalized number.  */
+    static union { unsigned int word[4]; long double value; } x =
+      { LDBL80_WORDS (0x4000, 0x63333333, 0x00000000) };
+    char *result;
+    int retval =
+      my_asprintf (&result, "%Lg %d", x.value, 33, 44, 55);
+    ASSERT (result != NULL);
+    ASSERT (strlen (result) >= 3 + 3
+           && strisnan (result, 0, strlen (result) - 3, 0)
+           && strcmp (result + strlen (result) - 3, " 33") == 0);
+    ASSERT (retval == strlen (result));
+    free (result);
+  }
+  { /* Pseudo-Denormal.  */
+    static union { unsigned int word[4]; long double value; } x =
+      { LDBL80_WORDS (0x0000, 0x83333333, 0x00000000) };
+    char *result;
+    int retval =
+      my_asprintf (&result, "%Lg %d", x.value, 33, 44, 55);
+    ASSERT (result != NULL);
+    ASSERT (strlen (result) >= 3 + 3
+           && strisnan (result, 0, strlen (result) - 3, 0)
+           && strcmp (result + strlen (result) - 3, " 33") == 0);
+    ASSERT (retval == strlen (result));
+    free (result);
+  }
+#endif
 
   { /* Width.  */
     char *result;
@@ -2654,9 +3178,11 @@ test_function (int (*my_asprintf) (char **, const char *, ...))
     static long double zero = 0.0L;
     char *result;
     int retval =
-      my_asprintf (&result, "%015Lg %d", zero / zero, 33, 44, 55);
+      my_asprintf (&result, "%050Lg %d", zero / zero, 33, 44, 55);
     ASSERT (result != NULL);
-    ASSERT (strcmp (result, "            nan 33") == 0);
+    ASSERT (strlen (result) == 50 + 3
+           && strisnan (result, strspn (result, " "), strlen (result) - 3, 0)
+           && strcmp (result + strlen (result) - 3, " 33") == 0);
     ASSERT (retval == strlen (result));
     free (result);
   }