From 9980b9e526d3436524fb148fc8ed8ebbd15e76dc Mon Sep 17 00:00:00 2001 From: Bruno Haible Date: Sun, 16 Feb 2025 17:59:48 +0100 Subject: [PATCH] strcasecmp: Work around Solaris, Cygwin bug. * lib/strings.in.h (strcasecmp): Consider REPLACE_STRCASECMP. Use the usual idioms. * m4/strings_h.m4 (gl_STRINGS_H_DEFAULTS): Initialize REPLACE_STRCASECMP. * m4/strcasecmp.m4 (gl_STRCASECMP_WORKS): New macro. (gl_FUNC_STRCASECMP): Invoke it. Set REPLACE_STRCASECMP. * modules/strcasecmp (configure.ac): Consider REPLACE_STRCASECMP. * modules/strings-h (Makefile.am): Substitute REPLACE_STRCASECMP. * doc/posix-functions/strcasecmp.texi: Mention the Solaris, Cygwin bug. --- ChangeLog | 13 ++++++++ doc/posix-functions/strcasecmp.texi | 5 +++ lib/strings.in.h | 22 ++++++++++--- m4/strcasecmp.m4 | 50 +++++++++++++++++++++++++++-- m4/strings_h.m4 | 3 +- modules/strcasecmp | 3 +- modules/strings-h | 1 + 7 files changed, 89 insertions(+), 8 deletions(-) diff --git a/ChangeLog b/ChangeLog index 9669e2210d..bf5e91746b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +2025-02-16 Bruno Haible + + strcasecmp: Work around Solaris, Cygwin bug. + * lib/strings.in.h (strcasecmp): Consider REPLACE_STRCASECMP. Use the + usual idioms. + * m4/strings_h.m4 (gl_STRINGS_H_DEFAULTS): Initialize + REPLACE_STRCASECMP. + * m4/strcasecmp.m4 (gl_STRCASECMP_WORKS): New macro. + (gl_FUNC_STRCASECMP): Invoke it. Set REPLACE_STRCASECMP. + * modules/strcasecmp (configure.ac): Consider REPLACE_STRCASECMP. + * modules/strings-h (Makefile.am): Substitute REPLACE_STRCASECMP. + * doc/posix-functions/strcasecmp.texi: Mention the Solaris, Cygwin bug. + 2025-02-16 Bruno Haible strcasecmp, strncasecmp: Fix header reference. diff --git a/doc/posix-functions/strcasecmp.texi b/doc/posix-functions/strcasecmp.texi index af640589d9..8c07af89e9 100644 --- a/doc/posix-functions/strcasecmp.texi +++ b/doc/posix-functions/strcasecmp.texi @@ -12,6 +12,11 @@ Portability problems fixed by Gnulib: @item This function is missing on some platforms: MSVC 14. +@item +This function uses the case mappings of a wrong locale on some platforms: +Solaris 11.4, +@c https://sourceware.org/pipermail/cygwin/2025-February/257347.html +Cygwin 3.5.6. @end itemize Portability problems not fixed by Gnulib: diff --git a/lib/strings.in.h b/lib/strings.in.h index cad01dc34b..b356115181 100644 --- a/lib/strings.in.h +++ b/lib/strings.in.h @@ -77,9 +77,23 @@ _GL_WARN_ON_USE (ffs, "ffs is not portable - use the ffs module"); greater than zero if S1 is lexicographically less than, equal to or greater than S2. Note: This function does not work in multibyte locales. */ -# if ! @HAVE_STRCASECMP@ -extern int strcasecmp (char const *s1, char const *s2) - _GL_ARG_NONNULL ((1, 2)); +# if @REPLACE_STRCASECMP@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef strcasecmp +# define strcasecmp rpl_strcasecmp +# endif +_GL_FUNCDECL_RPL (strcasecmp, int, (const char *, const char *), + _GL_ARG_NONNULL ((1, 2))); +_GL_CXXALIAS_RPL (strcasecmp, int, (const char *, const char *)); +# else +# if !@HAVE_STRCASECMP@ +_GL_FUNCDECL_SYS (strcasecmp, int, (const char *, const char *), + _GL_ARG_NONNULL ((1, 2))); +# endif +_GL_CXXALIAS_SYS (strcasecmp, int, (const char *, const char *)); +# endif +# if __GLIBC__ >= 2 +_GL_CXXALIASWARN (strcasecmp); # endif #elif defined GNULIB_POSIXCHECK /* strcasecmp() does not work with multibyte strings: @@ -88,7 +102,7 @@ extern int strcasecmp (char const *s1, char const *s2) # undef strcasecmp # if HAVE_RAW_DECL_STRCASECMP _GL_WARN_ON_USE (strcasecmp, "strcasecmp cannot work correctly on character " - "strings in multibyte locales - " + "strings in multibyte locales and is unportable - " "use mbscasecmp if you care about " "internationalization, or use c_strcasecmp " "(gnulib module c-strcasecmp) if you want a locale " diff --git a/m4/strcasecmp.m4 b/m4/strcasecmp.m4 index 0bbcc5ebe2..e40ee5d14a 100644 --- a/m4/strcasecmp.m4 +++ b/m4/strcasecmp.m4 @@ -1,5 +1,5 @@ # strcasecmp.m4 -# serial 1 +# serial 2 dnl Copyright (C) 2002-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, @@ -10,11 +10,57 @@ AC_DEFUN([gl_FUNC_STRCASECMP], [ AC_REQUIRE([gl_STRINGS_H_DEFAULTS]) AC_CHECK_FUNCS([strcasecmp]) - if test $ac_cv_func_strcasecmp = no; then + if test $ac_cv_func_strcasecmp = yes; then + gl_STRCASECMP_WORKS + case "$gl_cv_func_strcasecmp_works" in + *yes) ;; + *) REPLACE_STRCASECMP=1 ;; + esac + else HAVE_STRCASECMP=0 fi ]) +AC_DEFUN([gl_STRCASECMP_WORKS], +[ + AC_REQUIRE([AC_CANONICAL_HOST]) + AC_CACHE_CHECK([whether strcasecmp works], + [gl_cv_func_strcasecmp_works], + [dnl Prepare a guess, used when cross-compiling or when specific locales + dnl are not available. + case "$host_os" in + solaris* | cygwin*) + gl_cv_func_strcasecmp_works="guessing no" ;; + *) + gl_cv_func_strcasecmp_works="guessing yes" ;; + esac + AC_RUN_IFELSE( + [AC_LANG_SOURCE([[ +#include +#include +#include +#include +int main () +{ + if (setlocale (LC_ALL, "fr_FR.ISO-8859-1") != NULL + || setlocale (LC_ALL, "fr_FR.ISO8859-1") != NULL) + { + int c1 = (unsigned char) '\311'; + int c2 = (unsigned char) '\351'; + if (tolower (c1) == c2 && toupper (c2) == c1) + return strcasecmp ("Fej\311r", "Fej\351r") != 0; + } + return 2; +}]])], + [gl_cv_func_strcasecmp_works=yes], + [if test $? = 1; then + gl_cv_func_strcasecmp_works=no + fi + ], + []) + ]) +]) + # Prerequisites of lib/strcasecmp.c. AC_DEFUN([gl_PREREQ_STRCASECMP], [ : diff --git a/m4/strings_h.m4 b/m4/strings_h.m4 index 25596aa445..b88e1105fb 100644 --- a/m4/strings_h.m4 +++ b/m4/strings_h.m4 @@ -1,5 +1,5 @@ # strings_h.m4 -# serial 10 +# serial 11 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, @@ -63,4 +63,5 @@ AC_DEFUN([gl_STRINGS_H_DEFAULTS], HAVE_FFS=1; AC_SUBST([HAVE_FFS]) HAVE_STRCASECMP=1; AC_SUBST([HAVE_STRCASECMP]) HAVE_DECL_STRNCASECMP=1; AC_SUBST([HAVE_DECL_STRNCASECMP]) + REPLACE_STRCASECMP=1; AC_SUBST([REPLACE_STRCASECMP]) ]) diff --git a/modules/strcasecmp b/modules/strcasecmp index b226990b2a..34d3050374 100644 --- a/modules/strcasecmp +++ b/modules/strcasecmp @@ -10,7 +10,8 @@ strings-h configure.ac: gl_FUNC_STRCASECMP -gl_CONDITIONAL([GL_COND_OBJ_STRCASECMP], [test $HAVE_STRCASECMP = 0]) +gl_CONDITIONAL([GL_COND_OBJ_STRCASECMP], + [test $HAVE_STRCASECMP = 0 || test $REPLACE_STRCASECMP = 1]) AM_COND_IF([GL_COND_OBJ_STRCASECMP], [ gl_PREREQ_STRCASECMP ]) diff --git a/modules/strings-h b/modules/strings-h index 7b3cc6ad44..5c6c6736c2 100644 --- a/modules/strings-h +++ b/modules/strings-h @@ -38,6 +38,7 @@ strings.h: strings.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(WARN_ON_USE -e 's|@''HAVE_FFS''@|$(HAVE_FFS)|g' \ -e 's|@''HAVE_STRCASECMP''@|$(HAVE_STRCASECMP)|g' \ -e 's|@''HAVE_DECL_STRNCASECMP''@|$(HAVE_DECL_STRNCASECMP)|g' \ + -e 's|@''REPLACE_STRCASECMP''@|$(REPLACE_STRCASECMP)|g' \ -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \ -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \ -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \ -- 2.39.5