+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.
@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:
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:
# 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 "
# 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,
[
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], [
:
# 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,
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])
])
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
])
-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)' \