X-Git-Url: http://erislabs.net/gitweb/?a=blobdiff_plain;ds=sidebyside;f=tests%2Ftest-vasnprintf-posix.c;h=0162196a0aa03a34fa0c79ab4f4d5b42263c52cd;hb=ce9012b94357c174a846d129fe9b5d556a0a3bf1;hp=3d20a83af1a3905f604ee5e892573303c3066469;hpb=c0fea97ccf33a4e6b6f9116216b1634663f29474;p=gnulib.git diff --git a/tests/test-vasnprintf-posix.c b/tests/test-vasnprintf-posix.c index 3d20a83af..0162196a0 100644 --- a/tests/test-vasnprintf-posix.c +++ b/tests/test-vasnprintf-posix.c @@ -1,10 +1,10 @@ /* Test of POSIX compatible vasnprintf() and asnprintf() functions. - Copyright (C) 2007 Free Software Foundation, Inc. + Copyright (C) 2007-2009 Free Software Foundation, Inc. - This program is free software; you can redistribute it and/or modify + This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -12,8 +12,7 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + along with this program. If not, see . */ /* Written by Bruno Haible , 2007. */ @@ -21,6 +20,7 @@ #include "vasnprintf.h" +#include #include #include #include @@ -28,6 +28,8 @@ #include #include +#include "nan.h" + #define SIZEOF(array) (sizeof (array) / sizeof (array[0])) #define ASSERT(expr) \ do \ @@ -35,32 +37,54 @@ if (!(expr)) \ { \ fprintf (stderr, "%s:%d: assertion failed\n", __FILE__, __LINE__); \ + fflush (stderr); \ abort (); \ } \ } \ while (0) -/* The Compaq (ex-DEC) C 6.4 compiler chokes on the expression 0.0 / 0.0. */ -#ifdef __DECC -static double -NaN () -{ - static double zero = 0.0; - return zero / zero; -} -#else -# 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; + double minus_zero = - plus_zero; return memcmp (&plus_zero, &minus_zero, sizeof (double)) != 0; } +/* HP cc on HP-UX 10.20 has a bug with the constant expression -0.0. + So we use -zerod instead. */ +double zerod = 0.0; + +/* On HP-UX 10.20, negating 0.0L does not yield -0.0L. + So we use minus_zerol instead. + IRIX cc can't put -0.0L into .data, but can compute at runtime. + Note that the expression -LDBL_MIN * LDBL_MIN does not work on other + platforms, such as when cross-compiling to PowerPC on MacOS X 10.5. */ +#if defined __hpux || defined __sgi +static long double +compute_minus_zerol (void) +{ + return -LDBL_MIN * LDBL_MIN; +} +# define minus_zerol compute_minus_zerol () +#else +long double minus_zerol = -0.0L; +#endif + +/* 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) { @@ -92,7 +116,7 @@ strisnan (const char *string, size_t start_index, size_t end_index, int uppercas } return 0; } - + static void test_function (char * (*my_asnprintf) (char *, size_t *, const char *, ...)) { @@ -213,7 +237,7 @@ test_function (char * (*my_asnprintf) (char *, size_t *, const char *, ...)) { /* Negative zero. */ size_t length; char *result = - my_asnprintf (NULL, &length, "%a %d", -0.0, 33, 44, 55); + my_asnprintf (NULL, &length, "%a %d", -zerod, 33, 44, 55); ASSERT (result != NULL); if (have_minus_zero ()) ASSERT (strcmp (result, "-0x0p+0 33") == 0); @@ -244,7 +268,7 @@ test_function (char * (*my_asnprintf) (char *, size_t *, const char *, ...)) { /* NaN. */ size_t length; char *result = - my_asnprintf (NULL, &length, "%a %d", NaN (), 33, 44, 55); + my_asnprintf (NULL, &length, "%a %d", NaNd (), 33, 44, 55); ASSERT (result != NULL); ASSERT (strlen (result) >= 3 + 3 && strisnan (result, 0, strlen (result) - 3, 0) @@ -477,7 +501,7 @@ test_function (char * (*my_asnprintf) (char *, size_t *, const char *, ...)) { /* FLAG_ZERO with NaN. */ size_t length; char *result = - my_asnprintf (NULL, &length, "%050a %d", NaN (), 33, 44, 55); + my_asnprintf (NULL, &length, "%050a %d", NaNd (), 33, 44, 55); ASSERT (result != NULL); /* "0000000nan 33" is not a valid result; see */ @@ -527,7 +551,7 @@ test_function (char * (*my_asnprintf) (char *, size_t *, const char *, ...)) { /* Negative zero. */ size_t length; char *result = - my_asnprintf (NULL, &length, "%La %d", -0.0L, 33, 44, 55); + my_asnprintf (NULL, &length, "%La %d", minus_zerol, 33, 44, 55); ASSERT (result != NULL); if (have_minus_zero ()) ASSERT (strcmp (result, "-0x0p+0 33") == 0); @@ -558,7 +582,107 @@ test_function (char * (*my_asnprintf) (char *, size_t *, const char *, ...)) { /* NaN. */ size_t length; char *result = - my_asnprintf (NULL, &length, "%La %d", 0.0L / 0.0L, 33, 44, 55); + my_asnprintf (NULL, &length, "%La %d", NaNl (), 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 (length == 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) }; + size_t length; + char *result = + my_asnprintf (NULL, &length, "%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 (length == strlen (result)); + free (result); + } + { + /* Signalling NaN. */ + static union { unsigned int word[4]; long double value; } x = + { LDBL80_WORDS (0xFFFF, 0x83333333, 0x00000000) }; + size_t length; + char *result = + my_asnprintf (NULL, &length, "%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 (length == 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) }; + size_t length; + char *result = + my_asnprintf (NULL, &length, "%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 (length == strlen (result)); + free (result); + } + { /* Pseudo-Infinity. */ + static union { unsigned int word[4]; long double value; } x = + { LDBL80_WORDS (0xFFFF, 0x00000000, 0x00000000) }; + size_t length; + char *result = + my_asnprintf (NULL, &length, "%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 (length == strlen (result)); + free (result); + } + { /* Pseudo-Zero. */ + static union { unsigned int word[4]; long double value; } x = + { LDBL80_WORDS (0x4004, 0x00000000, 0x00000000) }; + size_t length; + char *result = + my_asnprintf (NULL, &length, "%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 (length == strlen (result)); + free (result); + } + { /* Unnormalized number. */ + static union { unsigned int word[4]; long double value; } x = + { LDBL80_WORDS (0x4000, 0x63333333, 0x00000000) }; + size_t length; + char *result = + my_asnprintf (NULL, &length, "%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 (length == strlen (result)); + free (result); + } + { /* Pseudo-Denormal. */ + static union { unsigned int word[4]; long double value; } x = + { LDBL80_WORDS (0x0000, 0x83333333, 0x00000000) }; + size_t length; + char *result = + my_asnprintf (NULL, &length, "%La %d", x.value, 33, 44, 55); ASSERT (result != NULL); ASSERT (strlen (result) >= 3 + 3 && strisnan (result, 0, strlen (result) - 3, 0) @@ -566,6 +690,7 @@ test_function (char * (*my_asnprintf) (char *, size_t *, const char *, ...)) ASSERT (length == strlen (result)); free (result); } +#endif { /* Rounding near the decimal point. */ size_t length; @@ -792,7 +917,7 @@ test_function (char * (*my_asnprintf) (char *, size_t *, const char *, ...)) { /* FLAG_ZERO with NaN. */ size_t length; char *result = - my_asnprintf (NULL, &length, "%050La %d", 0.0L / 0.0L, 33, 44, 55); + my_asnprintf (NULL, &length, "%050La %d", NaNl (), 33, 44, 55); ASSERT (result != NULL); /* "0000000nan 33" is not a valid result; see */ @@ -939,7 +1064,7 @@ test_function (char * (*my_asnprintf) (char *, size_t *, const char *, ...)) { /* Negative zero. */ size_t length; char *result = - my_asnprintf (NULL, &length, "%f %d", -0.0, 33, 44, 55); + my_asnprintf (NULL, &length, "%f %d", -zerod, 33, 44, 55); ASSERT (result != NULL); if (have_minus_zero ()) ASSERT (strcmp (result, "-0.000000 33") == 0); @@ -972,7 +1097,7 @@ test_function (char * (*my_asnprintf) (char *, size_t *, const char *, ...)) { /* NaN. */ size_t length; char *result = - my_asnprintf (NULL, &length, "%f %d", NaN (), 33, 44, 55); + my_asnprintf (NULL, &length, "%f %d", NaNd (), 33, 44, 55); ASSERT (result != NULL); ASSERT (strlen (result) >= 3 + 3 && strisnan (result, 0, strlen (result) - 3, 0) @@ -1065,7 +1190,7 @@ test_function (char * (*my_asnprintf) (char *, size_t *, const char *, ...)) { /* FLAG_ZERO with NaN. */ size_t length; char *result = - my_asnprintf (NULL, &length, "%050f %d", NaN (), 33, 44, 55); + my_asnprintf (NULL, &length, "%050f %d", NaNd (), 33, 44, 55); ASSERT (result != NULL); ASSERT (strlen (result) == 50 + 3 && strisnan (result, strspn (result, " "), strlen (result) - 3, 0) @@ -1084,6 +1209,26 @@ test_function (char * (*my_asnprintf) (char *, size_t *, const char *, ...)) free (result); } + { /* Precision with no rounding. */ + size_t length; + char *result = + my_asnprintf (NULL, &length, "%.2f %d", 999.951, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, "999.95 33") == 0); + ASSERT (length == strlen (result)); + free (result); + } + + { /* Precision with rounding. */ + size_t length; + char *result = + my_asnprintf (NULL, &length, "%.2f %d", 999.996, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, "1000.00 33") == 0); + ASSERT (length == strlen (result)); + free (result); + } + { /* A positive number. */ size_t length; char *result = @@ -1218,7 +1363,7 @@ test_function (char * (*my_asnprintf) (char *, size_t *, const char *, ...)) { /* Negative zero. */ size_t length; char *result = - my_asnprintf (NULL, &length, "%Lf %d", -0.0L, 33, 44, 55); + my_asnprintf (NULL, &length, "%Lf %d", minus_zerol, 33, 44, 55); ASSERT (result != NULL); if (have_minus_zero ()) ASSERT (strcmp (result, "-0.000000 33") == 0); @@ -1249,10 +1394,109 @@ test_function (char * (*my_asnprintf) (char *, size_t *, const char *, ...)) } { /* NaN. */ - static long double zero = 0.0L; size_t length; char *result = - my_asnprintf (NULL, &length, "%Lf %d", zero / zero, 33, 44, 55); + my_asnprintf (NULL, &length, "%Lf %d", NaNl (), 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 (length == 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) }; + size_t length; + char *result = + my_asnprintf (NULL, &length, "%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 (length == strlen (result)); + free (result); + } + { + /* Signalling NaN. */ + static union { unsigned int word[4]; long double value; } x = + { LDBL80_WORDS (0xFFFF, 0x83333333, 0x00000000) }; + size_t length; + char *result = + my_asnprintf (NULL, &length, "%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 (length == 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) }; + size_t length; + char *result = + my_asnprintf (NULL, &length, "%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 (length == strlen (result)); + free (result); + } + { /* Pseudo-Infinity. */ + static union { unsigned int word[4]; long double value; } x = + { LDBL80_WORDS (0xFFFF, 0x00000000, 0x00000000) }; + size_t length; + char *result = + my_asnprintf (NULL, &length, "%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 (length == strlen (result)); + free (result); + } + { /* Pseudo-Zero. */ + static union { unsigned int word[4]; long double value; } x = + { LDBL80_WORDS (0x4004, 0x00000000, 0x00000000) }; + size_t length; + char *result = + my_asnprintf (NULL, &length, "%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 (length == strlen (result)); + free (result); + } + { /* Unnormalized number. */ + static union { unsigned int word[4]; long double value; } x = + { LDBL80_WORDS (0x4000, 0x63333333, 0x00000000) }; + size_t length; + char *result = + my_asnprintf (NULL, &length, "%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 (length == strlen (result)); + free (result); + } + { /* Pseudo-Denormal. */ + static union { unsigned int word[4]; long double value; } x = + { LDBL80_WORDS (0x0000, 0x83333333, 0x00000000) }; + size_t length; + char *result = + my_asnprintf (NULL, &length, "%Lf %d", x.value, 33, 44, 55); ASSERT (result != NULL); ASSERT (strlen (result) >= 3 + 3 && strisnan (result, 0, strlen (result) - 3, 0) @@ -1260,6 +1504,7 @@ test_function (char * (*my_asnprintf) (char *, size_t *, const char *, ...)) ASSERT (length == strlen (result)); free (result); } +#endif { /* Width. */ size_t length; @@ -1343,10 +1588,9 @@ test_function (char * (*my_asnprintf) (char *, size_t *, const char *, ...)) } { /* FLAG_ZERO with NaN. */ - static long double zero = 0.0L; size_t length; char *result = - my_asnprintf (NULL, &length, "%050Lf %d", zero / zero, 33, 44, 55); + my_asnprintf (NULL, &length, "%050Lf %d", NaNl (), 33, 44, 55); ASSERT (result != NULL); ASSERT (strlen (result) == 50 + 3 && strisnan (result, strspn (result, " "), strlen (result) - 3, 0) @@ -1365,6 +1609,26 @@ test_function (char * (*my_asnprintf) (char *, size_t *, const char *, ...)) free (result); } + { /* Precision with no rounding. */ + size_t length; + char *result = + my_asnprintf (NULL, &length, "%.2Lf %d", 999.951L, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, "999.95 33") == 0); + ASSERT (length == strlen (result)); + free (result); + } + + { /* Precision with rounding. */ + size_t length; + char *result = + my_asnprintf (NULL, &length, "%.2Lf %d", 999.996L, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, "1000.00 33") == 0); + ASSERT (length == strlen (result)); + free (result); + } + /* Test the support of the %F format directive. */ { /* A positive number. */ @@ -1410,7 +1674,7 @@ test_function (char * (*my_asnprintf) (char *, size_t *, const char *, ...)) { /* Negative zero. */ size_t length; char *result = - my_asnprintf (NULL, &length, "%F %d", -0.0, 33, 44, 55); + my_asnprintf (NULL, &length, "%F %d", -zerod, 33, 44, 55); ASSERT (result != NULL); if (have_minus_zero ()) ASSERT (strcmp (result, "-0.000000 33") == 0); @@ -1443,7 +1707,7 @@ test_function (char * (*my_asnprintf) (char *, size_t *, const char *, ...)) { /* NaN. */ size_t length; char *result = - my_asnprintf (NULL, &length, "%F %d", NaN (), 33, 44, 55); + my_asnprintf (NULL, &length, "%F %d", NaNd (), 33, 44, 55); ASSERT (result != NULL); ASSERT (strlen (result) >= 3 + 3 && strisnan (result, 0, strlen (result) - 3, 1) @@ -1483,6 +1747,26 @@ test_function (char * (*my_asnprintf) (char *, size_t *, const char *, ...)) free (result); } + { /* Precision with no rounding. */ + size_t length; + char *result = + my_asnprintf (NULL, &length, "%.2F %d", 999.951, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, "999.95 33") == 0); + ASSERT (length == strlen (result)); + free (result); + } + + { /* Precision with rounding. */ + size_t length; + char *result = + my_asnprintf (NULL, &length, "%.2F %d", 999.996, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, "1000.00 33") == 0); + ASSERT (length == strlen (result)); + free (result); + } + { /* A positive number. */ size_t length; char *result = @@ -1526,7 +1810,7 @@ test_function (char * (*my_asnprintf) (char *, size_t *, const char *, ...)) { /* Negative zero. */ size_t length; char *result = - my_asnprintf (NULL, &length, "%LF %d", -0.0L, 33, 44, 55); + my_asnprintf (NULL, &length, "%LF %d", minus_zerol, 33, 44, 55); ASSERT (result != NULL); if (have_minus_zero ()) ASSERT (strcmp (result, "-0.000000 33") == 0); @@ -1557,10 +1841,9 @@ test_function (char * (*my_asnprintf) (char *, size_t *, const char *, ...)) } { /* NaN. */ - static long double zero = 0.0L; size_t length; char *result = - my_asnprintf (NULL, &length, "%LF %d", zero / zero, 33, 44, 55); + my_asnprintf (NULL, &length, "%LF %d", NaNl (), 33, 44, 55); ASSERT (result != NULL); ASSERT (strlen (result) >= 3 + 3 && strisnan (result, 0, strlen (result) - 3, 1) @@ -1600,6 +1883,26 @@ test_function (char * (*my_asnprintf) (char *, size_t *, const char *, ...)) free (result); } + { /* Precision with no rounding. */ + size_t length; + char *result = + my_asnprintf (NULL, &length, "%.2LF %d", 999.951L, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, "999.95 33") == 0); + ASSERT (length == strlen (result)); + free (result); + } + + { /* Precision with rounding. */ + size_t length; + char *result = + my_asnprintf (NULL, &length, "%.2LF %d", 999.996L, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, "1000.00 33") == 0); + ASSERT (length == strlen (result)); + free (result); + } + /* Test the support of the %e format directive. */ { /* A positive number. */ @@ -1748,7 +2051,7 @@ test_function (char * (*my_asnprintf) (char *, size_t *, const char *, ...)) { /* Negative zero. */ size_t length; char *result = - my_asnprintf (NULL, &length, "%e %d", -0.0, 33, 44, 55); + my_asnprintf (NULL, &length, "%e %d", -zerod, 33, 44, 55); ASSERT (result != NULL); if (have_minus_zero ()) ASSERT (strcmp (result, "-0.000000e+00 33") == 0 @@ -1782,7 +2085,7 @@ test_function (char * (*my_asnprintf) (char *, size_t *, const char *, ...)) { /* NaN. */ size_t length; char *result = - my_asnprintf (NULL, &length, "%e %d", NaN (), 33, 44, 55); + my_asnprintf (NULL, &length, "%e %d", NaNd (), 33, 44, 55); ASSERT (result != NULL); ASSERT (strlen (result) >= 3 + 3 && strisnan (result, 0, strlen (result) - 3, 0) @@ -1893,7 +2196,7 @@ test_function (char * (*my_asnprintf) (char *, size_t *, const char *, ...)) { /* FLAG_ZERO with NaN. */ size_t length; char *result = - my_asnprintf (NULL, &length, "%050e %d", NaN (), 33, 44, 55); + my_asnprintf (NULL, &length, "%050e %d", NaNd (), 33, 44, 55); ASSERT (result != NULL); ASSERT (strlen (result) == 50 + 3 && strisnan (result, strspn (result, " "), strlen (result) - 3, 0) @@ -1913,12 +2216,35 @@ test_function (char * (*my_asnprintf) (char *, size_t *, const char *, ...)) free (result); } + { /* Precision with no rounding. */ + size_t length; + char *result = + my_asnprintf (NULL, &length, "%.4e %d", 999.951, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, "9.9995e+02 33") == 0 + || strcmp (result, "9.9995e+002 33") == 0); + ASSERT (length == strlen (result)); + free (result); + } + + { /* Precision with rounding. */ + size_t length; + char *result = + my_asnprintf (NULL, &length, "%.4e %d", 999.996, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, "1.0000e+03 33") == 0 + || strcmp (result, "1.0000e+003 33") == 0); + ASSERT (length == strlen (result)); + free (result); + } + { /* A positive number. */ size_t length; char *result = my_asnprintf (NULL, &length, "%Le %d", 12.75L, 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 (length == strlen (result)); free (result); } @@ -1928,7 +2254,8 @@ test_function (char * (*my_asnprintf) (char *, size_t *, const char *, ...)) char *result = my_asnprintf (NULL, &length, "%Le %d", 1234567.0L, 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 (length == strlen (result)); free (result); } @@ -2017,8 +2344,16 @@ test_function (char * (*my_asnprintf) (char *, size_t *, const char *, ...)) size_t length; char *result = my_asnprintf (NULL, &length, "%Le", data[k].value); + const char *expected = data[k].string; ASSERT (result != NULL); - ASSERT (strcmp (result, data[k].string) == 0); + 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 (length == strlen (result)); free (result); } @@ -2029,7 +2364,8 @@ test_function (char * (*my_asnprintf) (char *, size_t *, const char *, ...)) char *result = my_asnprintf (NULL, &length, "%Le %d", -0.03125L, 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 (length == strlen (result)); free (result); } @@ -2039,7 +2375,8 @@ test_function (char * (*my_asnprintf) (char *, size_t *, const char *, ...)) char *result = my_asnprintf (NULL, &length, "%Le %d", 0.0L, 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 (length == strlen (result)); free (result); } @@ -2047,10 +2384,11 @@ test_function (char * (*my_asnprintf) (char *, size_t *, const char *, ...)) { /* Negative zero. */ size_t length; char *result = - my_asnprintf (NULL, &length, "%Le %d", -0.0L, 33, 44, 55); + my_asnprintf (NULL, &length, "%Le %d", minus_zerol, 33, 44, 55); ASSERT (result != NULL); if (have_minus_zero ()) - ASSERT (strcmp (result, "-0.000000e+00 33") == 0); + ASSERT (strcmp (result, "-0.000000e+00 33") == 0 + || strcmp (result, "-0.000000e+000 33") == 0); ASSERT (length == strlen (result)); free (result); } @@ -2078,10 +2416,9 @@ test_function (char * (*my_asnprintf) (char *, size_t *, const char *, ...)) } { /* NaN. */ - static long double zero = 0.0L; size_t length; char *result = - my_asnprintf (NULL, &length, "%Le %d", zero / zero, 33, 44, 55); + my_asnprintf (NULL, &length, "%Le %d", NaNl (), 33, 44, 55); ASSERT (result != NULL); ASSERT (strlen (result) >= 3 + 3 && strisnan (result, 0, strlen (result) - 3, 0) @@ -2089,43 +2426,148 @@ test_function (char * (*my_asnprintf) (char *, size_t *, const char *, ...)) ASSERT (length == strlen (result)); free (result); } - - { /* Width. */ +#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) }; size_t length; char *result = - my_asnprintf (NULL, &length, "%15Le %d", 1.75L, 33, 44, 55); + my_asnprintf (NULL, &length, "%Le %d", x.value, 33, 44, 55); ASSERT (result != NULL); - ASSERT (strcmp (result, " 1.750000e+00 33") == 0); + ASSERT (strlen (result) >= 3 + 3 + && strisnan (result, 0, strlen (result) - 3, 0) + && strcmp (result + strlen (result) - 3, " 33") == 0); ASSERT (length == strlen (result)); free (result); } - - { /* FLAG_LEFT. */ + { + /* Signalling NaN. */ + static union { unsigned int word[4]; long double value; } x = + { LDBL80_WORDS (0xFFFF, 0x83333333, 0x00000000) }; size_t length; char *result = - my_asnprintf (NULL, &length, "%-15Le %d", 1.75L, 33, 44, 55); + my_asnprintf (NULL, &length, "%Le %d", x.value, 33, 44, 55); ASSERT (result != NULL); - ASSERT (strcmp (result, "1.750000e+00 33") == 0); + ASSERT (strlen (result) >= 3 + 3 + && strisnan (result, 0, strlen (result) - 3, 0) + && strcmp (result + strlen (result) - 3, " 33") == 0); ASSERT (length == strlen (result)); free (result); } - - { /* FLAG_SHOWSIGN. */ + /* 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) }; size_t length; char *result = - my_asnprintf (NULL, &length, "%+Le %d", 1.75L, 33, 44, 55); + my_asnprintf (NULL, &length, "%Le %d", x.value, 33, 44, 55); ASSERT (result != NULL); - ASSERT (strcmp (result, "+1.750000e+00 33") == 0); + ASSERT (strlen (result) >= 3 + 3 + && strisnan (result, 0, strlen (result) - 3, 0) + && strcmp (result + strlen (result) - 3, " 33") == 0); ASSERT (length == strlen (result)); free (result); } - - { /* FLAG_SPACE. */ + { /* Pseudo-Infinity. */ + static union { unsigned int word[4]; long double value; } x = + { LDBL80_WORDS (0xFFFF, 0x00000000, 0x00000000) }; + size_t length; + char *result = + my_asnprintf (NULL, &length, "%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 (length == strlen (result)); + free (result); + } + { /* Pseudo-Zero. */ + static union { unsigned int word[4]; long double value; } x = + { LDBL80_WORDS (0x4004, 0x00000000, 0x00000000) }; + size_t length; + char *result = + my_asnprintf (NULL, &length, "%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 (length == strlen (result)); + free (result); + } + { /* Unnormalized number. */ + static union { unsigned int word[4]; long double value; } x = + { LDBL80_WORDS (0x4000, 0x63333333, 0x00000000) }; + size_t length; + char *result = + my_asnprintf (NULL, &length, "%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 (length == strlen (result)); + free (result); + } + { /* Pseudo-Denormal. */ + static union { unsigned int word[4]; long double value; } x = + { LDBL80_WORDS (0x0000, 0x83333333, 0x00000000) }; + size_t length; + char *result = + my_asnprintf (NULL, &length, "%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 (length == strlen (result)); + free (result); + } +#endif + + { /* Width. */ + size_t length; + char *result = + my_asnprintf (NULL, &length, "%15Le %d", 1.75L, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, " 1.750000e+00 33") == 0 + || strcmp (result, " 1.750000e+000 33") == 0); + ASSERT (length == strlen (result)); + free (result); + } + + { /* FLAG_LEFT. */ + size_t length; + char *result = + my_asnprintf (NULL, &length, "%-15Le %d", 1.75L, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, "1.750000e+00 33") == 0 + || strcmp (result, "1.750000e+000 33") == 0); + ASSERT (length == strlen (result)); + free (result); + } + + { /* FLAG_SHOWSIGN. */ + size_t length; + char *result = + my_asnprintf (NULL, &length, "%+Le %d", 1.75L, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, "+1.750000e+00 33") == 0 + || strcmp (result, "+1.750000e+000 33") == 0); + ASSERT (length == strlen (result)); + free (result); + } + + { /* FLAG_SPACE. */ size_t length; char *result = my_asnprintf (NULL, &length, "% Le %d", 1.75L, 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 (length == strlen (result)); free (result); } @@ -2135,7 +2577,8 @@ test_function (char * (*my_asnprintf) (char *, size_t *, const char *, ...)) char *result = my_asnprintf (NULL, &length, "%#Le %d", 1.75L, 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 (length == strlen (result)); free (result); } @@ -2145,7 +2588,8 @@ test_function (char * (*my_asnprintf) (char *, size_t *, const char *, ...)) char *result = my_asnprintf (NULL, &length, "%#.Le %d", 1.75L, 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 (length == strlen (result)); free (result); } @@ -2155,7 +2599,8 @@ test_function (char * (*my_asnprintf) (char *, size_t *, const char *, ...)) char *result = my_asnprintf (NULL, &length, "%#.Le %d", 9.75L, 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 (length == strlen (result)); free (result); } @@ -2165,7 +2610,8 @@ test_function (char * (*my_asnprintf) (char *, size_t *, const char *, ...)) char *result = my_asnprintf (NULL, &length, "%015Le %d", 1234.0L, 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 (length == strlen (result)); free (result); } @@ -2182,10 +2628,9 @@ test_function (char * (*my_asnprintf) (char *, size_t *, const char *, ...)) } { /* FLAG_ZERO with NaN. */ - static long double zero = 0.0L; size_t length; char *result = - my_asnprintf (NULL, &length, "%050Le %d", zero / zero, 33, 44, 55); + my_asnprintf (NULL, &length, "%050Le %d", NaNl (), 33, 44, 55); ASSERT (result != NULL); ASSERT (strlen (result) == 50 + 3 && strisnan (result, strspn (result, " "), strlen (result) - 3, 0) @@ -2199,7 +2644,30 @@ test_function (char * (*my_asnprintf) (char *, size_t *, const char *, ...)) char *result = my_asnprintf (NULL, &length, "%.Le %d", 1234.0L, 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 (length == strlen (result)); + free (result); + } + + { /* Precision with no rounding. */ + size_t length; + char *result = + my_asnprintf (NULL, &length, "%.4Le %d", 999.951L, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, "9.9995e+02 33") == 0 + || strcmp (result, "9.9995e+002 33") == 0); + ASSERT (length == strlen (result)); + free (result); + } + + { /* Precision with rounding. */ + size_t length; + char *result = + my_asnprintf (NULL, &length, "%.4Le %d", 999.996L, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, "1.0000e+03 33") == 0 + || strcmp (result, "1.0000e+003 33") == 0); ASSERT (length == strlen (result)); free (result); } @@ -2350,7 +2818,7 @@ test_function (char * (*my_asnprintf) (char *, size_t *, const char *, ...)) { /* Negative zero. */ size_t length; char *result = - my_asnprintf (NULL, &length, "%g %d", -0.0, 33, 44, 55); + my_asnprintf (NULL, &length, "%g %d", -zerod, 33, 44, 55); ASSERT (result != NULL); if (have_minus_zero ()) ASSERT (strcmp (result, "-0 33") == 0); @@ -2383,7 +2851,7 @@ test_function (char * (*my_asnprintf) (char *, size_t *, const char *, ...)) { /* NaN. */ size_t length; char *result = - my_asnprintf (NULL, &length, "%g %d", NaN (), 33, 44, 55); + my_asnprintf (NULL, &length, "%g %d", NaNd (), 33, 44, 55); ASSERT (result != NULL); ASSERT (strlen (result) >= 3 + 3 && strisnan (result, 0, strlen (result) - 3, 0) @@ -2487,7 +2955,7 @@ test_function (char * (*my_asnprintf) (char *, size_t *, const char *, ...)) { /* FLAG_ZERO with NaN. */ size_t length; char *result = - my_asnprintf (NULL, &length, "%050g %d", NaN (), 33, 44, 55); + my_asnprintf (NULL, &length, "%050g %d", NaNd (), 33, 44, 55); ASSERT (result != NULL); ASSERT (strlen (result) == 50 + 3 && strisnan (result, strspn (result, " "), strlen (result) - 3, 0) @@ -2507,6 +2975,26 @@ test_function (char * (*my_asnprintf) (char *, size_t *, const char *, ...)) free (result); } + { /* Precision with no rounding. */ + size_t length; + char *result = + my_asnprintf (NULL, &length, "%.5g %d", 999.951, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, "999.95 33") == 0); + ASSERT (length == strlen (result)); + free (result); + } + + { /* Precision with rounding. */ + size_t length; + char *result = + my_asnprintf (NULL, &length, "%.5g %d", 999.996, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, "1000 33") == 0); + ASSERT (length == strlen (result)); + free (result); + } + { /* A positive number. */ size_t length; char *result = @@ -2522,7 +3010,8 @@ test_function (char * (*my_asnprintf) (char *, size_t *, const char *, ...)) char *result = my_asnprintf (NULL, &length, "%Lg %d", 1234567.0L, 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 (length == strlen (result)); free (result); } @@ -2611,8 +3100,17 @@ test_function (char * (*my_asnprintf) (char *, size_t *, const char *, ...)) size_t length; char *result = my_asnprintf (NULL, &length, "%Lg", data[k].value); + const char *expected = data[k].string; ASSERT (result != NULL); - ASSERT (strcmp (result, data[k].string) == 0); + 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 (length == strlen (result)); free (result); } @@ -2641,7 +3139,7 @@ test_function (char * (*my_asnprintf) (char *, size_t *, const char *, ...)) { /* Negative zero. */ size_t length; char *result = - my_asnprintf (NULL, &length, "%Lg %d", -0.0L, 33, 44, 55); + my_asnprintf (NULL, &length, "%Lg %d", minus_zerol, 33, 44, 55); ASSERT (result != NULL); if (have_minus_zero ()) ASSERT (strcmp (result, "-0 33") == 0); @@ -2672,10 +3170,109 @@ test_function (char * (*my_asnprintf) (char *, size_t *, const char *, ...)) } { /* NaN. */ - static long double zero = 0.0L; size_t length; char *result = - my_asnprintf (NULL, &length, "%Lg %d", zero / zero, 33, 44, 55); + my_asnprintf (NULL, &length, "%Lg %d", NaNl (), 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 (length == 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) }; + size_t length; + char *result = + my_asnprintf (NULL, &length, "%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 (length == strlen (result)); + free (result); + } + { + /* Signalling NaN. */ + static union { unsigned int word[4]; long double value; } x = + { LDBL80_WORDS (0xFFFF, 0x83333333, 0x00000000) }; + size_t length; + char *result = + my_asnprintf (NULL, &length, "%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 (length == 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) }; + size_t length; + char *result = + my_asnprintf (NULL, &length, "%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 (length == strlen (result)); + free (result); + } + { /* Pseudo-Infinity. */ + static union { unsigned int word[4]; long double value; } x = + { LDBL80_WORDS (0xFFFF, 0x00000000, 0x00000000) }; + size_t length; + char *result = + my_asnprintf (NULL, &length, "%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 (length == strlen (result)); + free (result); + } + { /* Pseudo-Zero. */ + static union { unsigned int word[4]; long double value; } x = + { LDBL80_WORDS (0x4004, 0x00000000, 0x00000000) }; + size_t length; + char *result = + my_asnprintf (NULL, &length, "%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 (length == strlen (result)); + free (result); + } + { /* Unnormalized number. */ + static union { unsigned int word[4]; long double value; } x = + { LDBL80_WORDS (0x4000, 0x63333333, 0x00000000) }; + size_t length; + char *result = + my_asnprintf (NULL, &length, "%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 (length == strlen (result)); + free (result); + } + { /* Pseudo-Denormal. */ + static union { unsigned int word[4]; long double value; } x = + { LDBL80_WORDS (0x0000, 0x83333333, 0x00000000) }; + size_t length; + char *result = + my_asnprintf (NULL, &length, "%Lg %d", x.value, 33, 44, 55); ASSERT (result != NULL); ASSERT (strlen (result) >= 3 + 3 && strisnan (result, 0, strlen (result) - 3, 0) @@ -2683,6 +3280,7 @@ test_function (char * (*my_asnprintf) (char *, size_t *, const char *, ...)) ASSERT (length == strlen (result)); free (result); } +#endif { /* Width. */ size_t length; @@ -2749,7 +3347,8 @@ test_function (char * (*my_asnprintf) (char *, size_t *, const char *, ...)) char *result = my_asnprintf (NULL, &length, "%#.Lg %d", 9.75L, 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 (length == strlen (result)); free (result); } @@ -2776,10 +3375,9 @@ test_function (char * (*my_asnprintf) (char *, size_t *, const char *, ...)) } { /* FLAG_ZERO with NaN. */ - static long double zero = 0.0L; size_t length; char *result = - my_asnprintf (NULL, &length, "%050Lg %d", zero / zero, 33, 44, 55); + my_asnprintf (NULL, &length, "%050Lg %d", NaNl (), 33, 44, 55); ASSERT (result != NULL); ASSERT (strlen (result) == 50 + 3 && strisnan (result, strspn (result, " "), strlen (result) - 3, 0) @@ -2793,7 +3391,28 @@ test_function (char * (*my_asnprintf) (char *, size_t *, const char *, ...)) char *result = my_asnprintf (NULL, &length, "%.Lg %d", 1234.0L, 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 (length == strlen (result)); + free (result); + } + + { /* Precision with no rounding. */ + size_t length; + char *result = + my_asnprintf (NULL, &length, "%.5Lg %d", 999.951L, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, "999.95 33") == 0); + ASSERT (length == strlen (result)); + free (result); + } + + { /* Precision with rounding. */ + size_t length; + char *result = + my_asnprintf (NULL, &length, "%.5Lg %d", 999.996L, 33, 44, 55); + ASSERT (result != NULL); + ASSERT (strcmp (result, "1000 33") == 0); ASSERT (length == strlen (result)); free (result); } @@ -2835,6 +3454,201 @@ test_function (char * (*my_asnprintf) (char *, size_t *, const char *, ...)) ASSERT (length == strlen (result)); free (result); } + + /* Test the support of the left-adjust flag. */ + + { + size_t length; + char *result = + my_asnprintf (NULL, &length, "a%*sc", -3, "b"); + ASSERT (result != NULL); + ASSERT (strcmp (result, "ab c") == 0); + ASSERT (length == strlen (result)); + free (result); + } + + { + size_t length; + char *result = + my_asnprintf (NULL, &length, "a%-*sc", 3, "b"); + ASSERT (result != NULL); + ASSERT (strcmp (result, "ab c") == 0); + ASSERT (length == strlen (result)); + free (result); + } + + { + size_t length; + char *result = + my_asnprintf (NULL, &length, "a%-*sc", -3, "b"); + ASSERT (result != NULL); + ASSERT (strcmp (result, "ab c") == 0); + ASSERT (length == strlen (result)); + free (result); + } + + /* Test the support of large precision. */ + + { + size_t length; + char *result = + my_asnprintf (NULL, &length, "%.4000d %d", 1234567, 99); + size_t i; + ASSERT (result != NULL); + for (i = 0; i < 4000 - 7; i++) + ASSERT (result[i] == '0'); + ASSERT (strcmp (result + 4000 - 7, "1234567 99") == 0); + ASSERT (length == strlen (result)); + free (result); + } + + { + size_t length; + char *result = + my_asnprintf (NULL, &length, "%.*d %d", 4000, 1234567, 99); + size_t i; + ASSERT (result != NULL); + for (i = 0; i < 4000 - 7; i++) + ASSERT (result[i] == '0'); + ASSERT (strcmp (result + 4000 - 7, "1234567 99") == 0); + ASSERT (length == strlen (result)); + free (result); + } + + { + size_t length; + char *result = + my_asnprintf (NULL, &length, "%.4000d %d", -1234567, 99); + size_t i; + ASSERT (result != NULL); + ASSERT (result[0] == '-'); + for (i = 0; i < 4000 - 7; i++) + ASSERT (result[1 + i] == '0'); + ASSERT (strcmp (result + 1 + 4000 - 7, "1234567 99") == 0); + ASSERT (length == strlen (result)); + free (result); + } + + { + size_t length; + char *result = + my_asnprintf (NULL, &length, "%.4000u %d", 1234567, 99); + size_t i; + ASSERT (result != NULL); + for (i = 0; i < 4000 - 7; i++) + ASSERT (result[i] == '0'); + ASSERT (strcmp (result + 4000 - 7, "1234567 99") == 0); + ASSERT (length == strlen (result)); + free (result); + } + + { + size_t length; + char *result = + my_asnprintf (NULL, &length, "%.4000o %d", 1234567, 99); + size_t i; + ASSERT (result != NULL); + for (i = 0; i < 4000 - 7; i++) + ASSERT (result[i] == '0'); + ASSERT (strcmp (result + 4000 - 7, "4553207 99") == 0); + ASSERT (length == strlen (result)); + free (result); + } + + { + size_t length; + char *result = + my_asnprintf (NULL, &length, "%.4000x %d", 1234567, 99); + size_t i; + ASSERT (result != NULL); + for (i = 0; i < 4000 - 6; i++) + ASSERT (result[i] == '0'); + ASSERT (strcmp (result + 4000 - 6, "12d687 99") == 0); + ASSERT (length == strlen (result)); + free (result); + } + + { + size_t length; + char *result = + my_asnprintf (NULL, &length, "%#.4000x %d", 1234567, 99); + size_t i; + ASSERT (result != NULL); + ASSERT (result[0] == '0'); + ASSERT (result[1] == 'x'); + for (i = 0; i < 4000 - 6; i++) + ASSERT (result[2 + i] == '0'); + ASSERT (strcmp (result + 2 + 4000 - 6, "12d687 99") == 0); + ASSERT (length == strlen (result)); + free (result); + } + + { + char input[5000]; + size_t length; + char *result; + size_t i; + + for (i = 0; i < sizeof (input) - 1; i++) + input[i] = 'a' + ((1000000 / (i + 1)) % 26); + input[i] = '\0'; + result = my_asnprintf (NULL, &length, "%.4000s %d", input, 99); + ASSERT (result != NULL); + ASSERT (memcmp (result, input, 4000) == 0); + ASSERT (strcmp (result + 4000, " 99") == 0); + ASSERT (length == strlen (result)); + free (result); + } + + /* Test the support of the %s format directive. */ + + /* To verify that these tests succeed, it is necessary to run them under + a tool that checks against invalid memory accesses, such as ElectricFence + or "valgrind --tool=memcheck". */ + { + size_t i; + + for (i = 1; i <= 8; i++) + { + char *block; + size_t length; + char *result; + + block = (char *) malloc (i); + memcpy (block, "abcdefgh", i); + result = my_asnprintf (NULL, &length, "%.*s", (int) i, block); + ASSERT (result != NULL); + ASSERT (memcmp (result, block, i) == 0); + ASSERT (result[i] == '\0'); + ASSERT (length == strlen (result)); + free (result); + free (block); + } + } +#if HAVE_WCHAR_T + { + size_t i; + + for (i = 1; i <= 8; i++) + { + wchar_t *block; + size_t j; + size_t length; + char *result; + + block = (wchar_t *) malloc (i * sizeof (wchar_t)); + for (j = 0; j < i; j++) + block[j] = "abcdefgh"[j]; + result = my_asnprintf (NULL, &length, "%.*ls", (int) i, block); + ASSERT (result != NULL); + ASSERT (memcmp (result, "abcdefgh", i) == 0); + ASSERT (result[i] == '\0'); + ASSERT (length == strlen (result)); + free (result); + free (block); + } + } +#endif } static char *