On Cygwin 3.6.0, I see the test-getlocalename_l test fail: it crashes. Reported at <https://cygwin.com/pipermail/cygwin/2025-March/257715.html>.
This patch provides a workaround: 2025-03-24 Bruno Haible <br...@clisp.org> getlocalename_l-unsafe: Work around Cygwin 3.6.0 bug. * m4/locale_h.m4 (gl_LOCALE_H_DEFAULTS): Initialize REPLACE_GETLOCALENAME_L. * m4/getlocalename_l.m4 (gl_FUNC_GETLOCALENAME_L_UNSAFE): Test whether getlocalename_l works. Set REPLACE_GETLOCALENAME_L. * modules/locale-h (Makefile.am): Substitute REPLACE_GETLOCALENAME_L. * lib/locale.in.h (getlocalename_l): Consider REPLACE_GETLOCALENAME_L. * modules/getlocalename_l-simple (Depends-on, configure.ac): Likewise. * doc/posix-functions/getlocalename_l.texi: Mention two Cygwin bugs. diff --git a/doc/posix-functions/getlocalename_l.texi b/doc/posix-functions/getlocalename_l.texi index dc7b3ed94c..e258cd1df7 100644 --- a/doc/posix-functions/getlocalename_l.texi +++ b/doc/posix-functions/getlocalename_l.texi @@ -14,8 +14,20 @@ glibc 2.41, macOS 14, FreeBSD 14.0, NetBSD 10.0, OpenBSD 7.5, Minix 3.3.0, AIX 7.3.1, HP-UX 11.31, Solaris 11.4, Cygwin 3.5.x, mingw, MSVC 14, Android 9.0. But the gnulib replacement supports only a single locale category: the argument @code{LC_ALL} is unsupported. +@item +This function returns an invalid pointer +when the second argument is @code{LC_GLOBAL_LOCALE}, +on some platforms: +@c https://cygwin.com/pipermail/cygwin/2025-March/257715.html +Cygwin 3.6.0. @end itemize Portability problems not fixed by Gnulib: @itemize +@item +This function supports only a single locale category, +i.e. the argument @code{LC_ALL} is unsupported, +on some platforms: +@c https://cygwin.com/pipermail/cygwin/2025-March/257715.html +Cygwin 3.6.0. @end itemize diff --git a/lib/locale.in.h b/lib/locale.in.h index 5eead0a360..34f8c5b631 100644 --- a/lib/locale.in.h +++ b/lib/locale.in.h @@ -385,13 +385,25 @@ _GL_WARN_ON_USE (freelocale, "freelocale is not portable"); #endif #if @GNULIB_GETLOCALENAME_L@ -# if !@HAVE_GETLOCALENAME_L@ +# if @REPLACE_GETLOCALENAME_L@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef getlocalename_l +# define getlocalename_l rpl_getlocalename_l +# endif +_GL_FUNCDECL_RPL (getlocalename_l, const char *, + (int category, locale_t locale), + _GL_ARG_NONNULL ((2))); +_GL_CXXALIAS_RPL (getlocalename_l, const char *, + (int category, locale_t locale)); +# else +# if !@HAVE_GETLOCALENAME_L@ _GL_FUNCDECL_SYS (getlocalename_l, const char *, (int category, locale_t locale), _GL_ARG_NONNULL ((2))); -# endif +# endif _GL_CXXALIAS_SYS (getlocalename_l, const char *, (int category, locale_t locale)); +# endif # if __GLIBC__ >= 2 _GL_CXXALIASWARN (getlocalename_l); # endif diff --git a/m4/getlocalename_l.m4 b/m4/getlocalename_l.m4 index e434dff5f3..6c9d766ffa 100644 --- a/m4/getlocalename_l.m4 +++ b/m4/getlocalename_l.m4 @@ -1,5 +1,5 @@ # getlocalename_l.m4 -# serial 2 +# serial 3 dnl Copyright (C) 2025 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -27,10 +27,41 @@ AC_DEFUN_ONCE([gl_FUNC_GETLOCALENAME_L_UNSAFE] AC_REQUIRE([gl_FUNC_SETLOCALE_NULL]) AC_CHECK_FUNCS_ONCE([getlocalename_l]) if test $ac_cv_func_getlocalename_l = yes; then - GETLOCALENAME_L_LIB= + dnl Check against the Cygwin 3.6.0 bug: It returns an invalid pointer when + dnl the second argument is LC_GLOBAL_LOCALE. + AC_REQUIRE([AC_CANONICAL_HOST]) + AC_CACHE_CHECK([whether getlocalename_l works], + [gl_cv_func_getlocalename_l_works], + [AC_RUN_IFELSE( + [AC_LANG_SOURCE([[ +#include <locale.h> +#include <string.h> +int main () +{ + const char *ret = getlocalename_l (LC_COLLATE, LC_GLOBAL_LOCALE); + return strlen (ret) == 0; +}]])], + [gl_cv_func_getlocalename_l_works=yes], + [gl_cv_func_getlocalename_l_works=no], + [case "$host_os" in + cygwin*) # Guess no on Cygwin. + gl_cv_func_getlocalename_l_works="guessing no" ;; + *) # Guess yes otherwise. + gl_cv_func_getlocalename_l_works="guessing yes" ;; + esac + ]) + ]) + case "$gl_cv_func_getlocalename_l_works" in + *yes) ;; + *) REPLACE_GETLOCALENAME_L=1 ;; + esac else HAVE_GETLOCALENAME_L=0 + fi + if test $HAVE_GETLOCALENAME_L = 0 || test $REPLACE_GETLOCALENAME_L = 1; then GETLOCALENAME_L_LIB="$SETLOCALE_NULL_LIB" + else + GETLOCALENAME_L_LIB= fi dnl GETLOCALENAME_L_LIB is expected to be '-pthread' or '-lpthread' on AIX dnl with gcc or xlc, and empty otherwise. diff --git a/m4/locale_h.m4 b/m4/locale_h.m4 index 058dc7924b..e1afbc16da 100644 --- a/m4/locale_h.m4 +++ b/m4/locale_h.m4 @@ -1,5 +1,5 @@ # locale_h.m4 -# serial 36 +# serial 37 dnl Copyright (C) 2007, 2009-2025 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -190,15 +190,16 @@ AC_DEFUN([gl_LOCALE_H_REQUIRE_DEFAULTS] AC_DEFUN([gl_LOCALE_H_DEFAULTS], [ dnl Assume proper GNU behavior unless another module says otherwise. - HAVE_NEWLOCALE=1; AC_SUBST([HAVE_NEWLOCALE]) - HAVE_DUPLOCALE=1; AC_SUBST([HAVE_DUPLOCALE]) - HAVE_FREELOCALE=1; AC_SUBST([HAVE_FREELOCALE]) - HAVE_GETLOCALENAME_L=1; AC_SUBST([HAVE_GETLOCALENAME_L]) - REPLACE_LOCALECONV=0; AC_SUBST([REPLACE_LOCALECONV]) - REPLACE_SETLOCALE=0; AC_SUBST([REPLACE_SETLOCALE]) - REPLACE_NEWLOCALE=0; AC_SUBST([REPLACE_NEWLOCALE]) - REPLACE_DUPLOCALE=0; AC_SUBST([REPLACE_DUPLOCALE]) - REPLACE_FREELOCALE=0; AC_SUBST([REPLACE_FREELOCALE]) - REPLACE_STRUCT_LCONV=0; AC_SUBST([REPLACE_STRUCT_LCONV]) + HAVE_NEWLOCALE=1; AC_SUBST([HAVE_NEWLOCALE]) + HAVE_DUPLOCALE=1; AC_SUBST([HAVE_DUPLOCALE]) + HAVE_FREELOCALE=1; AC_SUBST([HAVE_FREELOCALE]) + HAVE_GETLOCALENAME_L=1; AC_SUBST([HAVE_GETLOCALENAME_L]) + REPLACE_LOCALECONV=0; AC_SUBST([REPLACE_LOCALECONV]) + REPLACE_SETLOCALE=0; AC_SUBST([REPLACE_SETLOCALE]) + REPLACE_NEWLOCALE=0; AC_SUBST([REPLACE_NEWLOCALE]) + REPLACE_DUPLOCALE=0; AC_SUBST([REPLACE_DUPLOCALE]) + REPLACE_FREELOCALE=0; AC_SUBST([REPLACE_FREELOCALE]) + REPLACE_GETLOCALENAME_L=0; AC_SUBST([REPLACE_GETLOCALENAME_L]) + REPLACE_STRUCT_LCONV=0; AC_SUBST([REPLACE_STRUCT_LCONV]) LOCALENAME_ENHANCE_LOCALE_FUNCS=0; AC_SUBST([LOCALENAME_ENHANCE_LOCALE_FUNCS]) ]) diff --git a/modules/getlocalename_l-simple b/modules/getlocalename_l-simple index f750146d97..6b9cc9e9ba 100644 --- a/modules/getlocalename_l-simple +++ b/modules/getlocalename_l-simple @@ -9,15 +9,16 @@ m4/getlocalename_l.m4 Depends-on: locale-h extensions -getlocalename_l-unsafe [test $HAVE_GETLOCALENAME_L = 0] -flexmember [test $HAVE_GETLOCALENAME_L = 0] -lock [test $HAVE_GETLOCALENAME_L = 0] -bool [test $HAVE_GETLOCALENAME_L = 0] -thread-optim [test $HAVE_GETLOCALENAME_L = 0] +getlocalename_l-unsafe [test $HAVE_GETLOCALENAME_L = 0 || test $REPLACE_GETLOCALENAME_L = 1] +flexmember [test $HAVE_GETLOCALENAME_L = 0 || test $REPLACE_GETLOCALENAME_L = 1] +lock [test $HAVE_GETLOCALENAME_L = 0 || test $REPLACE_GETLOCALENAME_L = 1] +bool [test $HAVE_GETLOCALENAME_L = 0 || test $REPLACE_GETLOCALENAME_L = 1] +thread-optim [test $HAVE_GETLOCALENAME_L = 0 || test $REPLACE_GETLOCALENAME_L = 1] configure.ac: gl_FUNC_GETLOCALENAME_L_SIMPLE -gl_CONDITIONAL([GL_COND_OBJ_GETLOCALENAME_L], [test $HAVE_GETLOCALENAME_L = 0]) +gl_CONDITIONAL([GL_COND_OBJ_GETLOCALENAME_L], + [test $HAVE_GETLOCALENAME_L = 0 || test $REPLACE_GETLOCALENAME_L = 1]) AM_COND_IF([GL_COND_OBJ_GETLOCALENAME_L], [ gl_PREREQ_GETLOCALENAME_L_SIMPLE ]) diff --git a/modules/locale-h b/modules/locale-h index 00910fde2a..97645b2355 100644 --- a/modules/locale-h +++ b/modules/locale-h @@ -54,6 +54,7 @@ locale.h: locale.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H -e 's|@''REPLACE_NEWLOCALE''@|$(REPLACE_NEWLOCALE)|g' \ -e 's|@''REPLACE_DUPLOCALE''@|$(REPLACE_DUPLOCALE)|g' \ -e 's|@''REPLACE_FREELOCALE''@|$(REPLACE_FREELOCALE)|g' \ + -e 's|@''REPLACE_GETLOCALENAME_L''@|$(REPLACE_GETLOCALENAME_L)|g' \ -e 's|@''REPLACE_STRUCT_LCONV''@|$(REPLACE_STRUCT_LCONV)|g' \ -e 's|@''LOCALENAME_ENHANCE_LOCALE_FUNCS''@|$(LOCALENAME_ENHANCE_LOCALE_FUNCS)|g' \ -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \