From 0a0fb288072ce33e602886f232493731b86a2574 Mon Sep 17 00:00:00 2001 From: Bruno Haible Date: Fri, 7 Apr 2023 23:54:24 +0200 Subject: vasnwprintf-posix: Work around %La bug in glibc 2.15 and Haiku. * m4/printf.m4 (gl_SWPRINTF_DIRECTIVE_LA): New macro. * m4/vasnprintf.m4 (gl_PREREQ_VASNWPRINTF): Invoke gl_SWPRINTF_DIRECTIVE_LA and define NEED_WPRINTF_DIRECTIVE_LA accordingly. * lib/vasnprintf.c: When compiling vasnwprintf, if NEED_WPRINTF_DIRECTIVE_LA, handle the %La and %LA directives ourselves. * doc/posix-functions/swprintf.texi: Mention the %La bug. --- ChangeLog | 11 +++ doc/posix-functions/swprintf.texi | 6 ++ lib/vasnprintf.c | 14 ++-- m4/printf.m4 | 145 +++++++++++++++++++++++++++----------- m4/vasnprintf.m4 | 11 ++- 5 files changed, 137 insertions(+), 50 deletions(-) diff --git a/ChangeLog b/ChangeLog index 2c802cb369..f6550f336c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2023-04-07 Bruno Haible + + vasnwprintf-posix: Work around %La bug in glibc 2.15 and Haiku. + * m4/printf.m4 (gl_SWPRINTF_DIRECTIVE_LA): New macro. + * m4/vasnprintf.m4 (gl_PREREQ_VASNWPRINTF): Invoke + gl_SWPRINTF_DIRECTIVE_LA and define NEED_WPRINTF_DIRECTIVE_LA + accordingly. + * lib/vasnprintf.c: When compiling vasnwprintf, if + NEED_WPRINTF_DIRECTIVE_LA, handle the %La and %LA directives ourselves. + * doc/posix-functions/swprintf.texi: Mention the %La bug. + 2023-04-07 Bruno Haible stdio: Fix compilation error in C++ mode on macOS. diff --git a/doc/posix-functions/swprintf.texi b/doc/posix-functions/swprintf.texi index cd20d0e702..fe36bc215a 100644 --- a/doc/posix-functions/swprintf.texi +++ b/doc/posix-functions/swprintf.texi @@ -36,6 +36,12 @@ accommodate all Unicode characters. @item On Windows, this function does not take a buffer size as second argument. @item +This function produces wrong values for the @samp{La} directive +on some platforms: +glibc 2.15, +@c https://dev.haiku-os.org/ticket/18353 +Haiku. +@item This function does not support size specifiers as in C23 (@code{w8}, @code{w16}, @code{w32}, @code{w64}, @code{wf8}, @code{wf16}, @code{wf32}, @code{wf64}) on some platforms: diff --git a/lib/vasnprintf.c b/lib/vasnprintf.c index 6eb056d0e9..efd610ebe4 100644 --- a/lib/vasnprintf.c +++ b/lib/vasnprintf.c @@ -103,7 +103,7 @@ #include "attribute.h" -#if NEED_PRINTF_DOUBLE || NEED_PRINTF_LONG_DOUBLE +#if NEED_PRINTF_DOUBLE || NEED_PRINTF_LONG_DOUBLE || (NEED_WPRINTF_DIRECTIVE_LA && WIDE_CHAR_VERSION) # include # include "float+.h" #endif @@ -113,7 +113,7 @@ # include "isnand-nolibm.h" #endif -#if NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE +#if NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE || (NEED_WPRINTF_DIRECTIVE_LA && WIDE_CHAR_VERSION) # include # include "isnanl-nolibm.h" # include "fpucw.h" @@ -125,7 +125,7 @@ # include "printf-frexp.h" #endif -#if NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_LONG_DOUBLE +#if NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_LONG_DOUBLE || (NEED_WPRINTF_DIRECTIVE_LA && WIDE_CHAR_VERSION) # include # include "isnanl-nolibm.h" # include "printf-frexpl.h" @@ -357,7 +357,7 @@ local_wctomb (char *s, wchar_t wc) # endif #endif -#if NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE || NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE +#if NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_INFINITE_LONG_DOUBLE || NEED_PRINTF_DOUBLE || NEED_PRINTF_INFINITE_DOUBLE || (NEED_WPRINTF_DIRECTIVE_LA && WIDE_CHAR_VERSION) /* Determine the decimal-point character according to the current locale. */ # ifndef decimal_point_char_defined # define decimal_point_char_defined 1 @@ -3929,14 +3929,14 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, length += count; } #endif -#if NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_DOUBLE +#if NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_LONG_DOUBLE || NEED_PRINTF_DOUBLE || (NEED_WPRINTF_DIRECTIVE_LA && WIDE_CHAR_VERSION) else if ((dp->conversion == 'a' || dp->conversion == 'A') # if !(NEED_PRINTF_DIRECTIVE_A || (NEED_PRINTF_LONG_DOUBLE && NEED_PRINTF_DOUBLE)) && (0 # if NEED_PRINTF_DOUBLE || a.arg[dp->arg_index].type == TYPE_DOUBLE # endif -# if NEED_PRINTF_LONG_DOUBLE +# if NEED_PRINTF_LONG_DOUBLE || (NEED_WPRINTF_DIRECTIVE_LA && WIDE_CHAR_VERSION) || a.arg[dp->arg_index].type == TYPE_LONGDOUBLE # endif ) @@ -4056,7 +4056,7 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp, p = tmp; if (type == TYPE_LONGDOUBLE) { -# if NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_LONG_DOUBLE +# if NEED_PRINTF_DIRECTIVE_A || NEED_PRINTF_LONG_DOUBLE || (NEED_WPRINTF_DIRECTIVE_LA && WIDE_CHAR_VERSION) long double arg = a.arg[dp->arg_index].a.a_longdouble; if (isnanl (arg)) diff --git a/m4/printf.m4 b/m4/printf.m4 index cf4e225cfe..f513da0c84 100644 --- a/m4/printf.m4 +++ b/m4/printf.m4 @@ -1,4 +1,4 @@ -# printf.m4 serial 80 +# printf.m4 serial 81 dnl Copyright (C) 2003, 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, @@ -1950,6 +1950,65 @@ int main() ]) ]) +dnl Test whether the *wprintf family of functions supports the 'a' and 'A' +dnl conversion specifier for hexadecimal output of 'long double' numbers. +dnl (ISO C99, POSIX:2001) +dnl Result is gl_cv_func_swprintf_directive_la. + +AC_DEFUN([gl_SWPRINTF_DIRECTIVE_LA], +[ + AC_REQUIRE([AC_PROG_CC]) + AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles + AC_CACHE_CHECK([whether swprintf supports the 'La' and 'LA' directives], + [gl_cv_func_swprintf_directive_la], + [ + AC_RUN_IFELSE( + [AC_LANG_SOURCE([[ +#include +#include +static wchar_t buf[100]; +int main () +{ + int result = 0; + /* This catches a glibc 2.15 and Haiku 2022 bug. */ + if (swprintf (buf, sizeof (buf) / sizeof (wchar_t), + L"%La %d", 3.1416015625L, 33, 44, 55) < 0 + || (wcscmp (buf, L"0x1.922p+1 33") != 0 + && wcscmp (buf, L"0x3.244p+0 33") != 0 + && wcscmp (buf, L"0x6.488p-1 33") != 0 + && wcscmp (buf, L"0xc.91p-2 33") != 0)) + result |= 1; + return result; +}]])], + [gl_cv_func_swprintf_directive_la=yes], + [gl_cv_func_swprintf_directive_la=no], + [case "$host_os" in + # Guess yes on glibc >= 2.17 systems. + *-gnu* | gnu*) + AC_EGREP_CPP([Unlucky], [ + #include + #ifdef __GNU_LIBRARY__ + #if ((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 17) || (__GLIBC__ > 2)) && !defined __UCLIBC__ + Unlucky + #endif + #endif + ], + [gl_cv_func_swprintf_directive_la="guessing yes"], + [gl_cv_func_swprintf_directive_la="guessing no"]) + ;; + # Guess yes on musl systems. + *-musl* | midipix*) gl_cv_func_swprintf_directive_la="guessing yes";; + # Guess yes on Android. + linux*-android*) gl_cv_func_swprintf_directive_la="guessing no";; + # Guess yes on native Windows. + mingw*) gl_cv_func_swprintf_directive_la="guessing no";; + # If we don't know, obey --enable-cross-guesses. + *) gl_cv_func_swprintf_directive_la="$gl_cross_guess_normal";; + esac + ]) + ]) +]) + dnl The results of these tests on various platforms are: dnl dnl 1 = gl_PRINTF_SIZES_C99 @@ -1977,6 +2036,7 @@ dnl 22 = gl_SNPRINTF_DIRECTIVE_N dnl 23 = gl_SNPRINTF_SIZE1 dnl 24 = gl_VSNPRINTF_ZEROSIZE_C99 dnl 25 = gl_SWPRINTF_WORKS +dnl 26 = gl_SWPRINTF_DIRECTIVE_LA dnl dnl 1 = checking whether printf supports size specifiers as in C99... dnl 2 = checking whether printf supports size specifiers as in C23... @@ -2003,47 +2063,48 @@ dnl 22 = checking whether snprintf fully supports the 'n' directive... dnl 23 = checking whether snprintf respects a size of 1... dnl 24 = checking whether vsnprintf respects a zero size as in C99... dnl 25 = checking whether swprintf works... +dnl 26 = checking whether swprintf supports the 'La' and 'LA' directives... dnl dnl . = yes, # = no. dnl -dnl 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 -dnl musl libc 1.2.3 . # . . . . # # . . . . . . . . . . . . . . . . # -dnl glibc 2.35 . # . . . . . . . . . # . . . . . . . . . . . . . -dnl glibc 2.5 . # . . . . # # . . . # . . . . . . . . . . . . ? -dnl glibc 2.3.6 . # . . . # # # . . . # . . . . . . . . . . . . ? -dnl FreeBSD 13.0 . # . . . # # # . . . # . . . . . # . . . . . . # -dnl FreeBSD 5.4, 6.1 . # . . . # # # . . . # . . . # . # . . . . . . # -dnl Mac OS X 10.13.5 . # . . # # # # . # . # . . . . . . . . . # . . # -dnl Mac OS X 10.5.8 . # . . # # # # . . . # . . . # . . . . . . . . # -dnl Mac OS X 10.3.9 . # . . . # # # . . . # . . . # . # . . . . . . # -dnl OpenBSD 6.0, 6.7 . # . . . # # # . . . # . . . . . # . . . . . . # -dnl OpenBSD 3.9, 4.0 . # . # # # # # # . # # . # . # . # . . . . . . # -dnl Cygwin 1.7.0 (2009) . # . . # . # # . . ? ? . . . . . ? . . . . . . ? -dnl Cygwin 1.5.25 (2008) . # . . # # # # . . # ? . . . . . # . . . . . . ? -dnl Cygwin 1.5.19 (2006) # # . . # # # # # . # ? . # . # # # . . . . . . ? -dnl Solaris 11.4 . # . # # # # # . . # # . . . # . . . . . . . . . -dnl Solaris 11.3 . # . . . # # # . . # # . . . . . . . . . . . . . -dnl Solaris 11.0 . # . # # # # # . . # # . . . # . . . . . . . . ? -dnl Solaris 10 . # . # # # # # . . # # . . . # # . . . . . . . ? -dnl Solaris 2.6 ... 9 # # . # # # # # # . # # . . . # # . . . # . . . ? -dnl Solaris 2.5.1 # # . # # # # # # . # # . . . # . . # # # # # # ? -dnl AIX 7.1 . # . # # # # # . . . # . . . # # . . . . . . . # -dnl AIX 5.2 . # . # # # # # . . . # . . . # . . . . . . . . # -dnl AIX 4.3.2, 5.1 # # . # # # # # # . . # . . . # . . . . # . . . # -dnl HP-UX 11.31 . # . . . # # # . . . ? . . . # . . . . # # . . ? -dnl HP-UX 11.{00,11,23} # # . . . # # # # . . ? . . . # . . . . # # . # ? -dnl HP-UX 10.20 # # . # . # # # # . ? ? . . # # . . . . # # ? # ? -dnl IRIX 6.5 # # . # # # # # # . # # . . . # . . . . # . . . # -dnl OSF/1 5.1 # # . # # # # # # . . ? . . . # . . . . # . . # ? -dnl OSF/1 4.0d # # . # # # # # # . . ? . . . # . . # # # # # # ? -dnl NetBSD 9.0 . # . . . # # # . . . # . . . . . . . . . . . . # -dnl NetBSD 5.0 . # . . # # # # . . . # . . . # . # . . . . . . # -dnl NetBSD 4.0 . # ? ? ? ? # # ? . ? # . ? ? ? ? ? . . . ? ? ? # -dnl NetBSD 3.0 . # . . . # # # # . ? # # # ? # . # . . . . . . # -dnl Haiku . # . . # # # # # . # ? . . . . . ? . . ? . . . ? -dnl BeOS # # # . # # # # # . ? ? # . ? . # ? . . ? . . . ? -dnl Android 4.3 . # . # # # # # # # # ? . # . # . # . . . # . . ? -dnl old mingw / msvcrt # # # # # # # # # . . ? # # . # # ? . # # # . . # -dnl MSVC 9 # # # # # # # # # # . ? # # . # # ? # # # # . . # -dnl mingw 2009-2011 . # # . # . # # . . . ? # # . . . ? . . . . . . # -dnl mingw-w64 2011 # # # # # # # # # . . ? # # . # # ? . # # # . . # +dnl 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 +dnl musl libc 1.2.3 . # . . . . # # . . . . . . . . . . . . . . . . # . +dnl glibc 2.35 . # . . . . . . . . . # . . . . . . . . . . . . . . +dnl glibc 2.5 . # . . . . # # . . . # . . . . . . . . . . . . . # +dnl glibc 2.3.6 . # . . . # # # . . . # . . . . . . . . . . . . . # +dnl FreeBSD 13.0 . # . . . # # # . . . # . . . . . # . . . . . . # . +dnl FreeBSD 5.4, 6.1 . # . . . # # # . . . # . . . # . # . . . . . . # ? +dnl Mac OS X 10.13.5 . # . . # # # # . # . # . . . . . . . . . # . . # ? +dnl Mac OS X 10.5.8 . # . . # # # # . . . # . . . # . . . . . . . . # ? +dnl Mac OS X 10.3.9 . # . . . # # # . . . # . . . # . # . . . . . . # ? +dnl OpenBSD 6.0, 6.7 . # . . . # # # . . . # . . . . . # . . . . . . # . +dnl OpenBSD 3.9, 4.0 . # . # # # # # # . # # . # . # . # . . . . . . # ? +dnl Cygwin 1.7.0 (2009) . # . . # . # # . . ? ? . . . . . ? . . . . . . ? ? +dnl Cygwin 1.5.25 (2008) . # . . # # # # . . # ? . . . . . # . . . . . . ? ? +dnl Cygwin 1.5.19 (2006) # # . . # # # # # . # ? . # . # # # . . . . . . ? ? +dnl Solaris 11.4 . # . # # # # # . . # # . . . # . . . . . . . . . ? +dnl Solaris 11.3 . # . . . # # # . . # # . . . . . . . . . . . . . ? +dnl Solaris 11.0 . # . # # # # # . . # # . . . # . . . . . . . . ? ? +dnl Solaris 10 . # . # # # # # . . # # . . . # # . . . . . . . ? ? +dnl Solaris 2.6 ... 9 # # . # # # # # # . # # . . . # # . . . # . . . ? ? +dnl Solaris 2.5.1 # # . # # # # # # . # # . . . # . . # # # # # # ? ? +dnl AIX 7.1 . # . # # # # # . . . # . . . # # . . . . . . . # . +dnl AIX 5.2 . # . # # # # # . . . # . . . # . . . . . . . . # ? +dnl AIX 4.3.2, 5.1 # # . # # # # # # . . # . . . # . . . . # . . . # ? +dnl HP-UX 11.31 . # . . . # # # . . . ? . . . # . . . . # # . . ? ? +dnl HP-UX 11.{00,11,23} # # . . . # # # # . . ? . . . # . . . . # # . # ? ? +dnl HP-UX 10.20 # # . # . # # # # . ? ? . . # # . . . . # # ? # ? ? +dnl IRIX 6.5 # # . # # # # # # . # # . . . # . . . . # . . . # ? +dnl OSF/1 5.1 # # . # # # # # # . . ? . . . # . . . . # . . # ? ? +dnl OSF/1 4.0d # # . # # # # # # . . ? . . . # . . # # # # # # ? ? +dnl NetBSD 9.0 . # . . . # # # . . . # . . . . . . . . . . . . # . +dnl NetBSD 5.0 . # . . # # # # . . . # . . . # . # . . . . . . # ? +dnl NetBSD 4.0 . # ? ? ? ? # # ? . ? # . ? ? ? ? ? . . . ? ? ? # ? +dnl NetBSD 3.0 . # . . . # # # # . ? # # # ? # . # . . . . . . # ? +dnl Haiku . # . . # # # # # . # ? . . . . . ? . . ? . . . . # +dnl BeOS # # # . # # # # # . ? ? # . ? . # ? . . ? . . . ? ? +dnl Android 4.3 . # . # # # # # # # # ? . # . # . # . . . # . . ? ? +dnl old mingw / msvcrt # # # # # # # # # . . ? # # . # # ? . # # # . . # ? +dnl MSVC 9 # # # # # # # # # # . ? # # . # # ? # # # # . . # ? +dnl mingw 2009-2011 . # # . # . # # . . . ? # # . . . ? . . . . . . # ? +dnl mingw-w64 2011 # # # # # # # # # . . ? # # . # # ? . # # # . . # ? diff --git a/m4/vasnprintf.m4 b/m4/vasnprintf.m4 index 86133b30b1..ca14ce49b4 100644 --- a/m4/vasnprintf.m4 +++ b/m4/vasnprintf.m4 @@ -1,4 +1,4 @@ -# vasnprintf.m4 serial 48 +# vasnprintf.m4 serial 49 dnl Copyright (C) 2002-2004, 2006-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, @@ -114,6 +114,15 @@ AC_DEFUN_ONCE([gl_PREREQ_VASNWPRINTF], the 'c' directive.]) ;; esac + gl_SWPRINTF_DIRECTIVE_LA + case "$gl_cv_func_printf_directive_a" in + *yes) ;; + *) + AC_DEFINE([NEED_WPRINTF_DIRECTIVE_LA], [1], + [Define if the vasnwprintf implementation needs special code for + the 'a' directive with 'long double' arguments.]) + ;; + esac gl_MUSL_LIBC gl_PREREQ_VASNXPRINTF ]) -- cgit v1.2.1