]> Savannah Git Hosting - gnulib.git/commitdiff
strcasecmp: Work around Solaris, Cygwin bug.
authorBruno Haible <bruno@clisp.org>
Sun, 16 Feb 2025 16:59:48 +0000 (17:59 +0100)
committerBruno Haible <bruno@clisp.org>
Sun, 16 Feb 2025 16:59:48 +0000 (17:59 +0100)
* 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
doc/posix-functions/strcasecmp.texi
lib/strings.in.h
m4/strcasecmp.m4
m4/strings_h.m4
modules/strcasecmp
modules/strings-h

index 9669e2210d9d9ade152fae9796974d95fbf7b0f5..bf5e91746b7146871576e0fdec275602fd00fddf 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+2025-02-16  Bruno Haible  <bruno@clisp.org>
+
+       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  <bruno@clisp.org>
 
        strcasecmp, strncasecmp: Fix header reference.
index af640589d9b23b2afbe39481b9aab294f5d73f2f..8c07af89e93980c7798e286a40fa29601d964507 100644 (file)
@@ -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:
index cad01dc34b6ced0e05ed0460568470d8cd6a1bb6..b356115181f10836cd217d8ce3335a0eb6997618 100644 (file)
@@ -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 "
index 0bbcc5ebe223908e065cb3a6cdb7040270b19cb5..e40ee5d14a5489027529bc433a5f1c7212b03d23 100644 (file)
@@ -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 <stdio.h>
+#include <ctype.h>
+#include <locale.h>
+#include <strings.h>
+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], [
   :
index 25596aa445cbdf416d48a7dab9d28f5ee97625b3..b88e1105fbd4c83be43d067edacd0a881941435f 100644 (file)
@@ -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])
 ])
index b226990b2ace89a1affd6d4c70b7c11bc0f3901e..34d3050374cf6a74de9f9fa18952671d6f6a40a0 100644 (file)
@@ -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
 ])
index 7b3cc6ad441a0dc4cdc2cc8367e8a3f3f5e566f6..5c6c6736c291d7de1cb92e8782d26fa07ed3b669 100644 (file)
@@ -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)' \