bug-gnulib
[Top][All Lists]
Advanced

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

stdio: ISO C 23: Define _PRINTF_NAN_LEN_MAX


From: Bruno Haible
Subject: stdio: ISO C 23: Define _PRINTF_NAN_LEN_MAX
Date: Sat, 25 Mar 2023 19:50:04 +0100

ISO C 23 specifies a new macro, to be defined in <stdio.h>: _PRINTF_NAN_LEN_MAX.

This patch implements it.


2023-03-25  Bruno Haible  <bruno@clisp.org>

        stdio: ISO C 23: Define _PRINTF_NAN_LEN_MAX.
        * lib/stdio.in.h (_PRINTF_NAN_LEN_MAX): New macro.
        * m4/stdio_h.m4 (gl_STDIO_H): Invoke gl_MUSL_LIBC.
        * modules/stdio (Files): Add m4/musl.m4.
        * tests/test-stdio.c: Check that _PRINTF_NAN_LEN_MAX is defined.
        Include nan.h, macros.h.
        (main): Check the value of _PRINTF_NAN_LEN_MAX.
        * modules/stdio-tests (Files): Add tests/nan.h, tests/macros.h,
        m4/exponentd.m4.
        (configure.ac): Invoke gl_DOUBLE_EXPONENT_LOCATION.

diff --git a/lib/stdio.in.h b/lib/stdio.in.h
index 098f841738..0ed3e7595c 100644
--- a/lib/stdio.in.h
+++ b/lib/stdio.in.h
@@ -204,6 +204,37 @@
 # undef putc_unlocked
 #endif
 
+
+/* Maximum number of characters produced by printing a NaN value.  */
+#ifndef _PRINTF_NAN_LEN_MAX
+# if defined __FreeBSD__ || defined __DragonFly__ \
+     || defined __NetBSD__ \
+     || defined __OpenBSD__ \
+     || (defined __APPLE__ && defined __MACH__)
+/* On BSD systems, a NaN value prints as just "nan", without a sign.  */
+#  define _PRINTF_NAN_LEN_MAX 3
+# elif (__GLIBC__ >= 2) || MUSL_LIBC || defined __sun || defined __CYGWIN__
+/* glibc, musl libc, Solaris libc, and Cygwin produce "[-]nan".  */
+#  define _PRINTF_NAN_LEN_MAX 4
+# elif defined _AIX
+/* AIX produces "[-]NaNQ".  */
+#  define _PRINTF_NAN_LEN_MAX 5
+# elif defined _WIN32 && !defined __CYGWIN__
+/* On native Windows, the output can be:
+   - with MSVC ucrt: "[-]nan" or "[-]nan(ind)" or "[-]nan(snan)",
+   - with mingw: "[-]1.#IND" or "[-]1.#QNAN".  */
+#  define _PRINTF_NAN_LEN_MAX 10
+# elif defined __sgi
+/* On IRIX, the output typically is "[-]nan0xNNNNNNNN" with 8 hexadecimal
+   digits.  */
+#  define _PRINTF_NAN_LEN_MAX 14
+# else
+/* We don't know, but 32 should be a safe maximum.  */
+#  define _PRINTF_NAN_LEN_MAX 32
+# endif
+#endif
+
+
 #if @GNULIB_DPRINTF@
 # if @REPLACE_DPRINTF@
 #  if !(defined __cplusplus && defined GNULIB_NAMESPACE)
diff --git a/m4/stdio_h.m4 b/m4/stdio_h.m4
index 07569961f8..342b7d1f20 100644
--- a/m4/stdio_h.m4
+++ b/m4/stdio_h.m4
@@ -1,4 +1,4 @@
-# stdio_h.m4 serial 61
+# stdio_h.m4 serial 62
 dnl Copyright (C) 2007-2023 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -40,6 +40,9 @@ AC_DEFUN_ONCE([gl_STDIO_H]
        attribute "__gnu_printf__" instead of "__printf__"])
   fi
 
+  dnl For defining _PRINTF_NAN_LEN_MAX.
+  gl_MUSL_LIBC
+
   dnl This ifdef is an optimization, to avoid performing a configure check 
whose
   dnl result is not used. But it does not make the test of
   dnl GNULIB_STDIO_H_NONBLOCKING or GNULIB_NONBLOCKING redundant.
diff --git a/modules/stdio b/modules/stdio
index b8662ef0a9..b4d866df9d 100644
--- a/modules/stdio
+++ b/modules/stdio
@@ -6,6 +6,7 @@ lib/stdio.in.h
 lib/stdio-read.c
 lib/stdio-write.c
 m4/stdio_h.m4
+m4/musl.m4
 
 Depends-on:
 extensions
diff --git a/modules/stdio-tests b/modules/stdio-tests
index 5368a2c64c..52b753e2f7 100644
--- a/modules/stdio-tests
+++ b/modules/stdio-tests
@@ -1,5 +1,8 @@
 Files:
 tests/test-stdio.c
+tests/nan.h
+tests/macros.h
+m4/exponentd.m4
 
 Depends-on:
 assert-h
@@ -10,6 +13,7 @@ fread-tests
 fwrite-tests
 
 configure.ac:
+gl_DOUBLE_EXPONENT_LOCATION
 
 Makefile.am:
 TESTS += test-stdio
diff --git a/tests/test-stdio.c b/tests/test-stdio.c
index a3b0a3e2ba..9794f4d856 100644
--- a/tests/test-stdio.c
+++ b/tests/test-stdio.c
@@ -23,6 +23,9 @@
 /* Check that the various SEEK_* macros are defined.  */
 int sk[] = { SEEK_CUR, SEEK_END, SEEK_SET };
 
+/* Check that the _PRINTF_NAN_LEN_MAX macro is defined.  */
+int pnlm[] = { _PRINTF_NAN_LEN_MAX };
+
 /* Check that NULL can be passed through varargs as a pointer type,
    per POSIX 2008.  */
 static_assert (sizeof NULL == sizeof (void *));
@@ -34,8 +37,37 @@ size_t t3;
 ssize_t t4;
 va_list t5;
 
+#include <string.h>
+
+#include "nan.h"
+#include "macros.h"
+
 int
 main (void)
 {
+#if defined DBL_EXPBIT0_WORD && defined DBL_EXPBIT0_BIT
+  /* Check the value of _PRINTF_NAN_LEN_MAX.  */
+  {
+    #define NWORDS \
+      ((sizeof (double) + sizeof (unsigned int) - 1) / sizeof (unsigned int))
+    typedef union { double value; unsigned int word[NWORDS]; } memory_double;
+
+    double value1;
+    memory_double value2;
+    char buf[64];
+
+    value1 = NaNd();
+    sprintf (buf, "%g", value1);
+    ASSERT (strlen (buf) <= _PRINTF_NAN_LEN_MAX);
+
+    value2.value = NaNd ();
+    #if DBL_EXPBIT0_BIT == 20
+    value2.word[DBL_EXPBIT0_WORD] ^= 0x54321;
+    #endif
+    sprintf (buf, "%g", value2.value);
+    ASSERT (strlen (buf) <= _PRINTF_NAN_LEN_MAX);
+  }
+#endif
+
   return 0;
 }






reply via email to

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