For many years, I know about the Java functions String.startsWith and
String.endsWith and how easy they are to use, compared to the 3-argument
strncmp. And nevertheless I thought that in C, we are all expert programmers,
we don't need one-liner abstractions.

And now I see that six years ago, I wrote code like this:

                   (strlen (term) > 8
                    && strcmp (term + strlen (term) - 8, "-direct") == 0))

Code that doesn't work. Obviously? No, not obviously. The one-liner
abstractions would have avoided this mistake.

Let me add these functions to Gnulib, so we can make some of these idioms
more maintainable.

Regarding the function names: Some packages use 'strstartswith' and
'strendswith'. I believe the added underscore makes the function name
slightly more readable.


2025-01-03  Bruno Haible  <br...@clisp.org>

        tests: Use str_endswith.
        * tests/test-canonicalize.c (main): Use str_endswith.
        * tests/test-canonicalize-lgpl.c (main): Likewise.
        * tests/test-setlocale-w32utf8.c (main): Likewise.
        * modules/canonicalize-tests (Depends-on): Add str_endswith.
        * modules/canonicalize-lgpl-tests (Depends-on): Likewise.
        * modules/setlocale-tests (Depends-on): Likewise.

        gen-uni-tables, get-rusage-data, isatty: Use str_endswith.
        * lib/gen-uni-tables.c (fill_attributes): Use str_endswith.
        * lib/get-rusage-data.c (get_rusage_data_via_setrlimit): Likewise.
        * lib/isatty.c (IsCygwinConsoleHandle): Likewise.
        * modules/gen-uni-tables (Depends-on): Add str_endswith.
        * modules/get-rusage-data (Depends-on): Likewise.
        * modules/isatty (Depends-on): Likewise.

2025-01-03  Bruno Haible  <br...@clisp.org>

        tests: Use str_startswith.
        * tests/test-environ.c (main): Use str_startswith.
        * tests/test-getprogname.c (main): Likewise.
        * tests/test-libtextstyle.c (main): Likewise.
        * tests/test-strsignal.c (ASSERT_DESCRIPTION): Likewise.
        * modules/environ-tests (Depends-on): Add str_startswith.
        * modules/getprogname-tests (Depends-on): Likewise.
        * modules/libtextstyle-optional-tests (Depends-on): Likewise.
        * modules/strsignal-tests (Depends-on): Likewise.

        git-merge-changelog, gen-uni-tables: Use str_startswith.
        * lib/git-merge-changelog.c (main): Use str_startswith.
        * lib/gen-uni-tables.c (output_predicate, is_property_composite,
        is_nonspacing): Likewise.
        * modules/git-merge-changelog (Depends-on): Add str_startswith.
        * modules/gen-uni-tables (Depends-on): Likewise.

2025-01-03  Bruno Haible  <br...@clisp.org>

        str_endswith: Add tests.
        * tests/test-str_endswith.c: New file.
        * modules/str_endswith-tests: New file.

        str_endswith: New module.
        * lib/string.in.h (str_endswith): New declaration.
        * lib/str_endswith.c: New file.
        * m4/string_h.m4 (gl_STRING_H_REQUIRE_DEFAULTS): Initialize
        GNULIB_STR_ENDSWITH.
        * modules/string-h (Makefile.am): Substitute GNULIB_STR_ENDSWITH.
        * modules/str_endswith: New file.

2025-01-03  Bruno Haible  <br...@clisp.org>

        str_startswith: Add tests.
        * tests/test-str_startswith.c: New file.
        * modules/str_startswith-tests: New file.

        str_startswith: New module.
        * lib/string.in.h (str_startswith): New declaration.
        * lib/str_startswith.c: New file.
        * m4/string_h.m4 (gl_STRING_H_REQUIRE_DEFAULTS): Initialize
        GNULIB_STR_STARTSWITH.
        * modules/string-h (Makefile.am): Substitute GNULIB_STR_STARTSWITH.
        * modules/str_startswith: New file.

>From 24010120fab36721caaf92be076655571e44da07 Mon Sep 17 00:00:00 2001
From: Bruno Haible <br...@clisp.org>
Date: Fri, 3 Jan 2025 09:26:14 +0100
Subject: [PATCH 1/8] str_startswith: New module.

* lib/string.in.h (str_startswith): New declaration.
* lib/str_startswith.c: New file.
* m4/string_h.m4 (gl_STRING_H_REQUIRE_DEFAULTS): Initialize
GNULIB_STR_STARTSWITH.
* modules/string-h (Makefile.am): Substitute GNULIB_STR_STARTSWITH.
* modules/str_startswith: New file.
---
 ChangeLog              | 10 ++++++++++
 lib/str_startswith.c   | 29 +++++++++++++++++++++++++++++
 lib/string.in.h        |  8 ++++++++
 m4/string_h.m4         |  3 ++-
 modules/str_startswith | 23 +++++++++++++++++++++++
 modules/string-h       |  1 +
 6 files changed, 73 insertions(+), 1 deletion(-)
 create mode 100644 lib/str_startswith.c
 create mode 100644 modules/str_startswith

diff --git a/ChangeLog b/ChangeLog
index 8853983620..be756cd8ee 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2025-01-03  Bruno Haible  <br...@clisp.org>
+
+	str_startswith: New module.
+	* lib/string.in.h (str_startswith): New declaration.
+	* lib/str_startswith.c: New file.
+	* m4/string_h.m4 (gl_STRING_H_REQUIRE_DEFAULTS): Initialize
+	GNULIB_STR_STARTSWITH.
+	* modules/string-h (Makefile.am): Substitute GNULIB_STR_STARTSWITH.
+	* modules/str_startswith: New file.
+
 2025-01-02  Bruno Haible  <br...@clisp.org>
 
 	gnulib-l10n: Clarify the license of the POT file.
diff --git a/lib/str_startswith.c b/lib/str_startswith.c
new file mode 100644
index 0000000000..381236ec2a
--- /dev/null
+++ b/lib/str_startswith.c
@@ -0,0 +1,29 @@
+/* str_startswith function.
+   Copyright (C) 2025 Free Software Foundation, Inc.
+
+   This file is free software: you can redistribute it and/or modify
+   it under the terms of the GNU Lesser General Public License as
+   published by the Free Software Foundation, either version 3 of the
+   License, or (at your option) any later version.
+
+   This file is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public License
+   along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
+
+/* Written by Bruno Haible <br...@clisp.org>, 2025.  */
+
+#include "config.h"
+
+/* Specification.  */
+#include <string.h>
+
+
+int
+str_startswith (const char *string, const char *prefix)
+{
+  return strncmp (string, prefix, strlen (prefix)) == 0;
+}
diff --git a/lib/string.in.h b/lib/string.in.h
index 1bae32ad46..b8b388abad 100644
--- a/lib/string.in.h
+++ b/lib/string.in.h
@@ -1077,6 +1077,14 @@ _GL_WARN_ON_USE (strtok_r, "strtok_r is unportable - "
 /* The following functions are not specified by POSIX.  They are gnulib
    extensions.  */
 
+#if @GNULIB_STR_STARTSWITH@
+/* Returns true if STRING starts with PREFIX.
+   Returns false otherwise.  */
+_GL_EXTERN_C int str_startswith (const char *string, const char *prefix)
+     _GL_ATTRIBUTE_PURE
+     _GL_ARG_NONNULL ((1, 2));
+#endif
+
 #if @GNULIB_MBSLEN@
 /* Return the number of multibyte characters in the character string STRING.
    This considers multibyte characters, unlike strlen, which counts bytes.  */
diff --git a/m4/string_h.m4 b/m4/string_h.m4
index a07738479d..bda7894cfe 100644
--- a/m4/string_h.m4
+++ b/m4/string_h.m4
@@ -1,5 +1,5 @@
 # string_h.m4
-# serial 39
+# serial 40
 dnl Copyright (C) 2007-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,
@@ -70,6 +70,7 @@ AC_DEFUN([gl_STRING_H_REQUIRE_DEFAULTS]
     gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_STRSTR])
     gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_STRCASESTR])
     gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_STRTOK_R])
+    gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_STR_STARTSWITH])
     gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_MBSLEN])
     gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_MBSNLEN])
     gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_MBSCHR])
diff --git a/modules/str_startswith b/modules/str_startswith
new file mode 100644
index 0000000000..4b1754e341
--- /dev/null
+++ b/modules/str_startswith
@@ -0,0 +1,23 @@
+Description:
+str_startswith() function: test whether a string starts with a given prefix.
+
+Files:
+lib/str_startswith.c
+
+Depends-on:
+string-h
+
+configure.ac:
+gl_STRING_MODULE_INDICATOR([str_startswith])
+
+Makefile.am:
+lib_SOURCES += str_startswith.c
+
+Include:
+<string.h>
+
+License:
+LGPLv2+
+
+Maintainer:
+all
diff --git a/modules/string-h b/modules/string-h
index 0dfa096cc8..2dba436c7e 100644
--- a/modules/string-h
+++ b/modules/string-h
@@ -69,6 +69,7 @@ string.h: string.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H
 	      -e 's/@''GNULIB_STRSTR''@/$(GNULIB_STRSTR)/g' \
 	      -e 's/@''GNULIB_STRCASESTR''@/$(GNULIB_STRCASESTR)/g' \
 	      -e 's/@''GNULIB_STRTOK_R''@/$(GNULIB_STRTOK_R)/g' \
+	      -e 's/@''GNULIB_STR_STARTSWITH''@/$(GNULIB_STR_STARTSWITH)/g' \
 	      -e 's/@''GNULIB_STRERROR''@/$(GNULIB_STRERROR)/g' \
 	      -e 's/@''GNULIB_STRERROR_R''@/$(GNULIB_STRERROR_R)/g' \
 	      -e 's/@''GNULIB_STRERRORNAME_NP''@/$(GNULIB_STRERRORNAME_NP)/g' \
-- 
2.43.0

>From 2508f39d60797ab024c69b0f5bb2fcaa67ab3e42 Mon Sep 17 00:00:00 2001
From: Bruno Haible <br...@clisp.org>
Date: Fri, 3 Jan 2025 09:33:01 +0100
Subject: [PATCH 2/8] str_startswith: Add tests.

* tests/test-str_startswith.c: New file.
* modules/str_startswith-tests: New file.
---
 ChangeLog                    |  4 ++++
 modules/str_startswith-tests | 11 +++++++++
 tests/test-str_startswith.c  | 43 ++++++++++++++++++++++++++++++++++++
 3 files changed, 58 insertions(+)
 create mode 100644 modules/str_startswith-tests
 create mode 100644 tests/test-str_startswith.c

diff --git a/ChangeLog b/ChangeLog
index be756cd8ee..d4a2721715 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,9 @@
 2025-01-03  Bruno Haible  <br...@clisp.org>
 
+	str_startswith: Add tests.
+	* tests/test-str_startswith.c: New file.
+	* modules/str_startswith-tests: New file.
+
 	str_startswith: New module.
 	* lib/string.in.h (str_startswith): New declaration.
 	* lib/str_startswith.c: New file.
diff --git a/modules/str_startswith-tests b/modules/str_startswith-tests
new file mode 100644
index 0000000000..9239b55a42
--- /dev/null
+++ b/modules/str_startswith-tests
@@ -0,0 +1,11 @@
+Files:
+tests/test-str_startswith.c
+tests/macros.h
+
+Depends-on:
+
+configure.ac:
+
+Makefile.am:
+TESTS += test-str_startswith
+check_PROGRAMS += test-str_startswith
diff --git a/tests/test-str_startswith.c b/tests/test-str_startswith.c
new file mode 100644
index 0000000000..5dd741ae4c
--- /dev/null
+++ b/tests/test-str_startswith.c
@@ -0,0 +1,43 @@
+/* Test of str_startswith() function.
+   Copyright (C) 2025 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+
+/* Specification.  */
+#include <string.h>
+
+#include "macros.h"
+
+int
+main ()
+{
+  ASSERT (str_startswith ("", ""));
+  ASSERT (str_startswith ("abc", ""));
+
+  ASSERT (!str_startswith ("", "a"));
+  ASSERT (!str_startswith ("x", "a"));
+  ASSERT (str_startswith ("a", "a"));
+  ASSERT (str_startswith ("abc", "a"));
+
+  ASSERT (!str_startswith ("", "xyz"));
+  ASSERT (!str_startswith ("x", "xyz"));
+  ASSERT (!str_startswith ("a", "xyz"));
+  ASSERT (!str_startswith ("abc", "xyz"));
+  ASSERT (str_startswith ("xyz", "xyz"));
+  ASSERT (str_startswith ("xyzzy", "xyz"));
+
+  return test_exit_status;
+}
-- 
2.43.0

>From d89ac9373d9748f7601babf52c9129fcbcf0c907 Mon Sep 17 00:00:00 2001
From: Bruno Haible <br...@clisp.org>
Date: Fri, 3 Jan 2025 09:54:14 +0100
Subject: [PATCH 3/8] str_endswith: New module.

* lib/string.in.h (str_endswith): New declaration.
* lib/str_endswith.c: New file.
* m4/string_h.m4 (gl_STRING_H_REQUIRE_DEFAULTS): Initialize
GNULIB_STR_ENDSWITH.
* modules/string-h (Makefile.am): Substitute GNULIB_STR_ENDSWITH.
* modules/str_endswith: New file.
---
 ChangeLog            | 10 ++++++++++
 lib/str_endswith.c   | 31 +++++++++++++++++++++++++++++++
 lib/string.in.h      |  8 ++++++++
 m4/string_h.m4       |  3 ++-
 modules/str_endswith | 23 +++++++++++++++++++++++
 modules/string-h     |  1 +
 6 files changed, 75 insertions(+), 1 deletion(-)
 create mode 100644 lib/str_endswith.c
 create mode 100644 modules/str_endswith

diff --git a/ChangeLog b/ChangeLog
index d4a2721715..3172894f30 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2025-01-03  Bruno Haible  <br...@clisp.org>
+
+	str_endswith: New module.
+	* lib/string.in.h (str_endswith): New declaration.
+	* lib/str_endswith.c: New file.
+	* m4/string_h.m4 (gl_STRING_H_REQUIRE_DEFAULTS): Initialize
+	GNULIB_STR_ENDSWITH.
+	* modules/string-h (Makefile.am): Substitute GNULIB_STR_ENDSWITH.
+	* modules/str_endswith: New file.
+
 2025-01-03  Bruno Haible  <br...@clisp.org>
 
 	str_startswith: Add tests.
diff --git a/lib/str_endswith.c b/lib/str_endswith.c
new file mode 100644
index 0000000000..f33ac6997c
--- /dev/null
+++ b/lib/str_endswith.c
@@ -0,0 +1,31 @@
+/* str_endswith function.
+   Copyright (C) 2025 Free Software Foundation, Inc.
+
+   This file is free software: you can redistribute it and/or modify
+   it under the terms of the GNU Lesser General Public License as
+   published by the Free Software Foundation, either version 3 of the
+   License, or (at your option) any later version.
+
+   This file is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public License
+   along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
+
+/* Written by Bruno Haible <br...@clisp.org>, 2025.  */
+
+#include "config.h"
+
+/* Specification.  */
+#include <string.h>
+
+
+int
+str_endswith (const char *string, const char *suffix)
+{
+  size_t len = strlen (string);
+  size_t n = strlen (suffix);
+  return len >= n && strcmp (string + len - n, suffix) == 0;
+}
diff --git a/lib/string.in.h b/lib/string.in.h
index b8b388abad..f11b8f5706 100644
--- a/lib/string.in.h
+++ b/lib/string.in.h
@@ -1085,6 +1085,14 @@ _GL_EXTERN_C int str_startswith (const char *string, const char *prefix)
      _GL_ARG_NONNULL ((1, 2));
 #endif
 
+#if @GNULIB_STR_ENDSWITH@
+/* Returns true if STRING ends with SUFFIX.
+   Returns false otherwise.  */
+_GL_EXTERN_C int str_endswith (const char *string, const char *prefix)
+     _GL_ATTRIBUTE_PURE
+     _GL_ARG_NONNULL ((1, 2));
+#endif
+
 #if @GNULIB_MBSLEN@
 /* Return the number of multibyte characters in the character string STRING.
    This considers multibyte characters, unlike strlen, which counts bytes.  */
diff --git a/m4/string_h.m4 b/m4/string_h.m4
index bda7894cfe..d2adb95bad 100644
--- a/m4/string_h.m4
+++ b/m4/string_h.m4
@@ -1,5 +1,5 @@
 # string_h.m4
-# serial 40
+# serial 41
 dnl Copyright (C) 2007-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,
@@ -71,6 +71,7 @@ AC_DEFUN([gl_STRING_H_REQUIRE_DEFAULTS]
     gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_STRCASESTR])
     gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_STRTOK_R])
     gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_STR_STARTSWITH])
+    gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_STR_ENDSWITH])
     gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_MBSLEN])
     gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_MBSNLEN])
     gl_MODULE_INDICATOR_INIT_VARIABLE([GNULIB_MBSCHR])
diff --git a/modules/str_endswith b/modules/str_endswith
new file mode 100644
index 0000000000..c04b2c8eb0
--- /dev/null
+++ b/modules/str_endswith
@@ -0,0 +1,23 @@
+Description:
+str_endswith() function: test whether a string ends with a given suffix.
+
+Files:
+lib/str_endswith.c
+
+Depends-on:
+string-h
+
+configure.ac:
+gl_STRING_MODULE_INDICATOR([str_endswith])
+
+Makefile.am:
+lib_SOURCES += str_endswith.c
+
+Include:
+<string.h>
+
+License:
+LGPLv2+
+
+Maintainer:
+all
diff --git a/modules/string-h b/modules/string-h
index 2dba436c7e..0897afe206 100644
--- a/modules/string-h
+++ b/modules/string-h
@@ -69,6 +69,7 @@ string.h: string.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H
 	      -e 's/@''GNULIB_STRSTR''@/$(GNULIB_STRSTR)/g' \
 	      -e 's/@''GNULIB_STRCASESTR''@/$(GNULIB_STRCASESTR)/g' \
 	      -e 's/@''GNULIB_STRTOK_R''@/$(GNULIB_STRTOK_R)/g' \
+	      -e 's/@''GNULIB_STR_ENDSWITH''@/$(GNULIB_STR_ENDSWITH)/g' \
 	      -e 's/@''GNULIB_STR_STARTSWITH''@/$(GNULIB_STR_STARTSWITH)/g' \
 	      -e 's/@''GNULIB_STRERROR''@/$(GNULIB_STRERROR)/g' \
 	      -e 's/@''GNULIB_STRERROR_R''@/$(GNULIB_STRERROR_R)/g' \
-- 
2.43.0

>From 5a50792e2f1f5fe83c4df68f62819a4b7c9e0fa1 Mon Sep 17 00:00:00 2001
From: Bruno Haible <br...@clisp.org>
Date: Fri, 3 Jan 2025 09:59:56 +0100
Subject: [PATCH 4/8] str_endswith: Add tests.

* tests/test-str_endswith.c: New file.
* modules/str_endswith-tests: New file.
---
 ChangeLog                  |  4 ++++
 modules/str_endswith-tests | 11 ++++++++++
 tests/test-str_endswith.c  | 43 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 58 insertions(+)
 create mode 100644 modules/str_endswith-tests
 create mode 100644 tests/test-str_endswith.c

diff --git a/ChangeLog b/ChangeLog
index 3172894f30..b57ea5cae1 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,9 @@
 2025-01-03  Bruno Haible  <br...@clisp.org>
 
+	str_endswith: Add tests.
+	* tests/test-str_endswith.c: New file.
+	* modules/str_endswith-tests: New file.
+
 	str_endswith: New module.
 	* lib/string.in.h (str_endswith): New declaration.
 	* lib/str_endswith.c: New file.
diff --git a/modules/str_endswith-tests b/modules/str_endswith-tests
new file mode 100644
index 0000000000..ef8990c026
--- /dev/null
+++ b/modules/str_endswith-tests
@@ -0,0 +1,11 @@
+Files:
+tests/test-str_endswith.c
+tests/macros.h
+
+Depends-on:
+
+configure.ac:
+
+Makefile.am:
+TESTS += test-str_endswith
+check_PROGRAMS += test-str_endswith
diff --git a/tests/test-str_endswith.c b/tests/test-str_endswith.c
new file mode 100644
index 0000000000..fc1ec0abfc
--- /dev/null
+++ b/tests/test-str_endswith.c
@@ -0,0 +1,43 @@
+/* Test of str_endswith() function.
+   Copyright (C) 2025 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+
+/* Specification.  */
+#include <string.h>
+
+#include "macros.h"
+
+int
+main ()
+{
+  ASSERT (str_endswith ("", ""));
+  ASSERT (str_endswith ("abc", ""));
+
+  ASSERT (!str_endswith ("", "c"));
+  ASSERT (!str_endswith ("x", "c"));
+  ASSERT (str_endswith ("c", "c"));
+  ASSERT (str_endswith ("abc", "c"));
+
+  ASSERT (!str_endswith ("", "xyz"));
+  ASSERT (!str_endswith ("x", "xyz"));
+  ASSERT (!str_endswith ("a", "xyz"));
+  ASSERT (!str_endswith ("abc", "xyz"));
+  ASSERT (str_endswith ("xyz", "xyz"));
+  ASSERT (str_endswith ("yxxyz", "xyz"));
+
+  return test_exit_status;
+}
-- 
2.43.0

>From b20e8f40ea47cb80ef2f6f01dd34093b4eaca23b Mon Sep 17 00:00:00 2001
From: Bruno Haible <br...@clisp.org>
Date: Fri, 3 Jan 2025 10:12:08 +0100
Subject: [PATCH 5/8] git-merge-changelog, gen-uni-tables: Use str_startswith.

* lib/git-merge-changelog.c (main): Use str_startswith.
* lib/gen-uni-tables.c (output_predicate, is_property_composite,
is_nonspacing): Likewise.
* modules/git-merge-changelog (Depends-on): Add str_startswith.
* modules/gen-uni-tables (Depends-on): Likewise.
---
 ChangeLog                   | 9 +++++++++
 lib/gen-uni-tables.c        | 6 +++---
 lib/git-merge-changelog.c   | 4 ++--
 modules/gen-uni-tables      | 1 +
 modules/git-merge-changelog | 1 +
 5 files changed, 16 insertions(+), 5 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index b57ea5cae1..1355aa2361 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2025-01-03  Bruno Haible  <br...@clisp.org>
+
+	git-merge-changelog, gen-uni-tables: Use str_startswith.
+	* lib/git-merge-changelog.c (main): Use str_startswith.
+	* lib/gen-uni-tables.c (output_predicate, is_property_composite,
+	is_nonspacing): Likewise.
+	* modules/git-merge-changelog (Depends-on): Add str_startswith.
+	* modules/gen-uni-tables (Depends-on): Likewise.
+
 2025-01-03  Bruno Haible  <br...@clisp.org>
 
 	str_endswith: Add tests.
diff --git a/lib/gen-uni-tables.c b/lib/gen-uni-tables.c
index ff515854e0..c676660b07 100644
--- a/lib/gen-uni-tables.c
+++ b/lib/gen-uni-tables.c
@@ -776,7 +776,7 @@ output_predicate (const char *filename, bool (*predicate) (unsigned int), const
   fprintf (stream, "\n");
   output_library_license (stream,
                           strcmp (filename, "unictype/categ_M.h") == 0
-                          || strncmp (filename, "unictype/ctype_", 15) == 0
+                          || str_startswith (filename, "unictype/ctype_")
                           || strcmp (filename, "uniwidth/width2.h") == 0);
   fprintf (stream, "\n");
 
@@ -3883,7 +3883,7 @@ is_property_composite (unsigned int ch)
           if (decomp[0] == ' ')
             decomp++;
         }
-      return strchr (decomp, ' ') != NULL && strncmp (decomp, "0020 ", 5) != 0;
+      return strchr (decomp, ' ') != NULL && str_startswith (decomp, "0020 ");
     }
   return false;
 }
@@ -6827,7 +6827,7 @@ is_nonspacing (unsigned int ch)
               || is_category_Cc (ch)
               || (is_category_Cf (ch)
                   && !is_property_prepended_concatenation_mark (ch))
-              || strncmp (unicode_attributes[ch].name, "ZERO WIDTH ", 11) == 0
+              || str_startswith (unicode_attributes[ch].name, "ZERO WIDTH ")
               || (ch >= 0x1160 && ch <= 0x11A7) || (ch >= 0xD7B0 && ch <= 0xD7C6) /* jungseong */
               || (ch >= 0x11A8 && ch <= 0x11FF) || (ch >= 0xD7CB && ch <= 0xD7FB) /* jongseong */
          )   );
diff --git a/lib/git-merge-changelog.c b/lib/git-merge-changelog.c
index 74b6a5b63a..190dafc140 100644
--- a/lib/git-merge-changelog.c
+++ b/lib/git-merge-changelog.c
@@ -1163,9 +1163,9 @@ There is NO WARRANTY, to the extent permitted by law.\n\
               printf ("GIT_REFLOG_ACTION=|%s|\n", var);
               #endif
               if (var != NULL
-                  && ((strncmp (var, "pull", 4) == 0
+                  && ((str_startswith (var, "pull")
                        && c_strstr (var, " --rebase") == NULL)
-                      || strncmp (var, "merge origin", 12) == 0))
+                      || str_startswith (var, "merge origin")))
                 downstream = true;
               else
                 {
diff --git a/modules/gen-uni-tables b/modules/gen-uni-tables
index c61d34194c..561a39690b 100644
--- a/modules/gen-uni-tables
+++ b/modules/gen-uni-tables
@@ -12,6 +12,7 @@ memcmp
 bool
 strdup
 strstr-simple
+str_startswith
 
 configure.ac:
 AC_REQUIRE([AC_C_INLINE])
diff --git a/modules/git-merge-changelog b/modules/git-merge-changelog
index 1ef3e1102f..9ff56dcc86 100644
--- a/modules/git-merge-changelog
+++ b/modules/git-merge-changelog
@@ -22,6 +22,7 @@ xalloc
 xmalloca
 fstrcmp
 minmax
+str_startswith
 c-strstr
 fwriteerror
 memchr
-- 
2.43.0

>From e93bde59d27c491f1e6c7e3cef633d11cdd4a1d5 Mon Sep 17 00:00:00 2001
From: Bruno Haible <br...@clisp.org>
Date: Fri, 3 Jan 2025 10:23:56 +0100
Subject: [PATCH 6/8] tests: Use str_startswith.

* tests/test-environ.c (main): Use str_startswith.
* tests/test-getprogname.c (main): Likewise.
* tests/test-libtextstyle.c (main): Likewise.
* tests/test-strsignal.c (ASSERT_DESCRIPTION): Likewise.
* modules/environ-tests (Depends-on): Add str_startswith.
* modules/getprogname-tests (Depends-on): Likewise.
* modules/libtextstyle-optional-tests (Depends-on): Likewise.
* modules/strsignal-tests (Depends-on): Likewise.
---
 ChangeLog                           | 10 ++++++++++
 modules/environ-tests               |  1 +
 modules/getprogname-tests           |  1 +
 modules/libtextstyle-optional-tests |  1 +
 modules/strsignal-tests             |  1 +
 tests/test-environ.c                |  2 +-
 tests/test-getprogname.c            |  2 +-
 tests/test-libtextstyle.c           |  4 ++--
 tests/test-strsignal.c              |  2 +-
 9 files changed, 19 insertions(+), 5 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 1355aa2361..50b3f2e22e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,15 @@
 2025-01-03  Bruno Haible  <br...@clisp.org>
 
+	tests: Use str_startswith.
+	* tests/test-environ.c (main): Use str_startswith.
+	* tests/test-getprogname.c (main): Likewise.
+	* tests/test-libtextstyle.c (main): Likewise.
+	* tests/test-strsignal.c (ASSERT_DESCRIPTION): Likewise.
+	* modules/environ-tests (Depends-on): Add str_startswith.
+	* modules/getprogname-tests (Depends-on): Likewise.
+	* modules/libtextstyle-optional-tests (Depends-on): Likewise.
+	* modules/strsignal-tests (Depends-on): Likewise.
+
 	git-merge-changelog, gen-uni-tables: Use str_startswith.
 	* lib/git-merge-changelog.c (main): Use str_startswith.
 	* lib/gen-uni-tables.c (output_predicate, is_property_composite,
diff --git a/modules/environ-tests b/modules/environ-tests
index c4fe0fd11f..056096baa5 100644
--- a/modules/environ-tests
+++ b/modules/environ-tests
@@ -2,6 +2,7 @@ Files:
 tests/test-environ.c
 
 Depends-on:
+str_startswith
 
 configure.ac:
 
diff --git a/modules/getprogname-tests b/modules/getprogname-tests
index bd7137f8ea..1b1bc0a53a 100644
--- a/modules/getprogname-tests
+++ b/modules/getprogname-tests
@@ -3,6 +3,7 @@ tests/test-getprogname.c
 
 Depends-on:
 string-h
+str_startswith
 
 configure.ac:
 
diff --git a/modules/libtextstyle-optional-tests b/modules/libtextstyle-optional-tests
index e930a00fbe..e4dbd5d220 100644
--- a/modules/libtextstyle-optional-tests
+++ b/modules/libtextstyle-optional-tests
@@ -5,6 +5,7 @@ tests/test-libtextstyle-default.css
 Depends-on:
 c99
 isatty
+str_startswith
 
 configure.ac:
 gl_LIBTEXTSTYLE_OPTIONAL
diff --git a/modules/strsignal-tests b/modules/strsignal-tests
index ab67eb1b69..531451c4cd 100644
--- a/modules/strsignal-tests
+++ b/modules/strsignal-tests
@@ -4,6 +4,7 @@ tests/signature.h
 tests/macros.h
 
 Depends-on:
+str_startswith
 
 configure.ac:
 
diff --git a/tests/test-environ.c b/tests/test-environ.c
index a5c74ced79..21641b894c 100644
--- a/tests/test-environ.c
+++ b/tests/test-environ.c
@@ -35,7 +35,7 @@ main ()
 
   for (; (string = *remaining_variables) != NULL; remaining_variables++)
     {
-      if (strncmp (string, "PATH=", 5) == 0)
+      if (str_startswith (string, "PATH="))
         /* Found the PATH environment variable.  */
         return 0;
     }
diff --git a/tests/test-getprogname.c b/tests/test-getprogname.c
index 088561cf30..e1e8cb5350 100644
--- a/tests/test-getprogname.c
+++ b/tests/test-getprogname.c
@@ -36,7 +36,7 @@ main (void)
      with "lt-" (depends on the platform).  But the name of the temporary
      executable is a detail that should not be visible to the end user and to
      the test suite.  Remove this "lt-" prefix here.  */
-  if (strncmp (p, "lt-", 3) == 0)
+  if (str_startswith (p, "lt-"))
     p += 3;
 
   /* Note: You can make this test fail
diff --git a/tests/test-libtextstyle.c b/tests/test-libtextstyle.c
index e992daf1f2..6545a00223 100644
--- a/tests/test-libtextstyle.c
+++ b/tests/test-libtextstyle.c
@@ -34,9 +34,9 @@ main (int argc, char *argv[])
   for (i = 1; i < argc; i++)
     {
       const char *arg = argv[i];
-      if (strncmp (arg, "--color=", 8) == 0)
+      if (str_startswith (arg, "--color="))
         handle_color_option (arg + 8);
-      else if (strncmp (arg, "--style=", 8) == 0)
+      else if (str_startswith (arg, "--style="))
         handle_style_option (arg + 8);
       else if (arg[0] == '-')
         {
diff --git a/tests/test-strsignal.c b/tests/test-strsignal.c
index 6c44203734..4ed4cc3e23 100644
--- a/tests/test-strsignal.c
+++ b/tests/test-strsignal.c
@@ -33,7 +33,7 @@ SIGNATURE_CHECK (strsignal, char *, (int));
 /* In this case, we can guarantee some signal descriptions.
    But allow the actual result to be longer than the expected result.  */
 # define ASSERT_DESCRIPTION(actual, expected) \
-   ASSERT (strncmp (actual, expected, strlen (expected)) == 0)
+   ASSERT (str_startswith (actual, expected))
 #endif
 
 int
-- 
2.43.0

>From 26a37f80ead11e2e69dddf8d66aa34e0432a145e Mon Sep 17 00:00:00 2001
From: Bruno Haible <br...@clisp.org>
Date: Fri, 3 Jan 2025 10:38:58 +0100
Subject: [PATCH 7/8] gen-uni-tables, get-rusage-data, isatty: Use
 str_endswith.

* lib/gen-uni-tables.c (fill_attributes): Use str_endswith.
* lib/get-rusage-data.c (get_rusage_data_via_setrlimit): Likewise.
* lib/isatty.c (IsCygwinConsoleHandle): Likewise.
* modules/gen-uni-tables (Depends-on): Add str_endswith.
* modules/get-rusage-data (Depends-on): Likewise.
* modules/isatty (Depends-on): Likewise.
---
 ChangeLog               | 10 ++++++++++
 lib/gen-uni-tables.c    |  4 ++--
 lib/get-rusage-data.c   |  5 ++---
 lib/isatty.c            |  3 +--
 modules/gen-uni-tables  |  1 +
 modules/get-rusage-data |  1 +
 modules/isatty          |  1 +
 7 files changed, 18 insertions(+), 7 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 50b3f2e22e..b6a71b15e2 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2025-01-03  Bruno Haible  <br...@clisp.org>
+
+	gen-uni-tables, get-rusage-data, isatty: Use str_endswith.
+	* lib/gen-uni-tables.c (fill_attributes): Use str_endswith.
+	* lib/get-rusage-data.c (get_rusage_data_via_setrlimit): Likewise.
+	* lib/isatty.c (IsCygwinConsoleHandle): Likewise.
+	* modules/gen-uni-tables (Depends-on): Add str_endswith.
+	* modules/get-rusage-data (Depends-on): Likewise.
+	* modules/isatty (Depends-on): Likewise.
+
 2025-01-03  Bruno Haible  <br...@clisp.org>
 
 	tests: Use str_startswith.
diff --git a/lib/gen-uni-tables.c b/lib/gen-uni-tables.c
index c676660b07..2bac68c2da 100644
--- a/lib/gen-uni-tables.c
+++ b/lib/gen-uni-tables.c
@@ -219,7 +219,7 @@ fill_attributes (const char *unicodedata_filename)
       i = strtoul (field0, NULL, 16);
       if (field1[0] == '<'
           && strlen (field1) >= 9
-          && strcmp (field1 + strlen (field1) - 8, ", First>") == 0)
+          && str_endswith (field1, ", First>"))
         {
           /* Deal with a range. */
           lineno++;
@@ -246,7 +246,7 @@ fill_attributes (const char *unicodedata_filename)
             }
           if (!(field1[0] == '<'
                 && strlen (field1) >= 8
-                && strcmp (field1 + strlen (field1) - 7, ", Last>") == 0))
+                && str_endswith (field1, ", Last>")))
             {
               fprintf (stderr, "missing end range in '%s':%d\n",
                        unicodedata_filename, lineno);
diff --git a/lib/get-rusage-data.c b/lib/get-rusage-data.c
index b4df73f766..0fafc75a20 100644
--- a/lib/get-rusage-data.c
+++ b/lib/get-rusage-data.c
@@ -174,9 +174,8 @@ get_rusage_data_via_setrlimit (void)
     struct utsname buf;
 
     if (uname (&buf) == 0
-        && strlen (buf.release) >= 5
-        && (strcmp (buf.release + strlen (buf.release) - 5, "11.00") == 0
-            || strcmp (buf.release + strlen (buf.release) - 5, "11.11") == 0))
+        && (str_endswith (buf.release, "11.00")
+            || str_endswith (buf.release, "11.11")))
       return 0;
   }
 #  endif
diff --git a/lib/isatty.c b/lib/isatty.c
index 69371af607..23e3ab8f6d 100644
--- a/lib/isatty.c
+++ b/lib/isatty.c
@@ -130,8 +130,7 @@ static BOOL IsCygwinConsoleHandle (HANDLE h)
              or higher.  */
           if (QueryFullProcessImageNameFunc (processHandle, 0, buf, &bufsize))
             {
-              if (strlen (buf) >= 11
-                  && strcmp (buf + strlen (buf) - 11, "\\mintty.exe") == 0)
+              if (str_endswith (buf, "\\mintty.exe"))
                 result = TRUE;
             }
           CloseHandle (processHandle);
diff --git a/modules/gen-uni-tables b/modules/gen-uni-tables
index 561a39690b..5808aef3ad 100644
--- a/modules/gen-uni-tables
+++ b/modules/gen-uni-tables
@@ -13,6 +13,7 @@ bool
 strdup
 strstr-simple
 str_startswith
+str_endswith
 
 configure.ac:
 AC_REQUIRE([AC_C_INLINE])
diff --git a/modules/get-rusage-data b/modules/get-rusage-data
index 1a7bf89903..8d9110ac16 100644
--- a/modules/get-rusage-data
+++ b/modules/get-rusage-data
@@ -12,6 +12,7 @@ unistd-h
 extensions
 getpagesize
 vma-iter
+str_endswith
 
 configure.ac:
 AC_CHECK_FUNCS_ONCE([sbrk setrlimit])
diff --git a/modules/isatty b/modules/isatty
index e2fd7f09cd..7499b53933 100644
--- a/modules/isatty
+++ b/modules/isatty
@@ -9,6 +9,7 @@ Depends-on:
 unistd-h
 msvc-inval      [test $REPLACE_ISATTY = 1]
 msvc-nothrow    [test $REPLACE_ISATTY = 1]
+str_endswith    [test $REPLACE_ISATTY = 1]
 
 configure.ac:
 gl_FUNC_ISATTY
-- 
2.43.0

>From f2b0e184b5ac0182b545fad57ea7bec2cb4b621d Mon Sep 17 00:00:00 2001
From: Bruno Haible <br...@clisp.org>
Date: Fri, 3 Jan 2025 10:43:15 +0100
Subject: [PATCH 8/8] tests: Use str_endswith.

* tests/test-canonicalize.c (main): Use str_endswith.
* tests/test-canonicalize-lgpl.c (main): Likewise.
* tests/test-setlocale-w32utf8.c (main): Likewise.
* modules/canonicalize-tests (Depends-on): Add str_endswith.
* modules/canonicalize-lgpl-tests (Depends-on): Likewise.
* modules/setlocale-tests (Depends-on): Likewise.
---
 ChangeLog                       |  8 ++++++++
 modules/canonicalize-lgpl-tests |  1 +
 modules/canonicalize-tests      |  1 +
 modules/setlocale-tests         |  1 +
 tests/test-canonicalize-lgpl.c  |  6 ++----
 tests/test-canonicalize.c       | 17 ++++++-----------
 tests/test-setlocale-w32utf8.c  |  2 +-
 7 files changed, 20 insertions(+), 16 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index b6a71b15e2..300538b682 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,13 @@
 2025-01-03  Bruno Haible  <br...@clisp.org>
 
+	tests: Use str_endswith.
+	* tests/test-canonicalize.c (main): Use str_endswith.
+	* tests/test-canonicalize-lgpl.c (main): Likewise.
+	* tests/test-setlocale-w32utf8.c (main): Likewise.
+	* modules/canonicalize-tests (Depends-on): Add str_endswith.
+	* modules/canonicalize-lgpl-tests (Depends-on): Likewise.
+	* modules/setlocale-tests (Depends-on): Likewise.
+
 	gen-uni-tables, get-rusage-data, isatty: Use str_endswith.
 	* lib/gen-uni-tables.c (fill_attributes): Use str_endswith.
 	* lib/get-rusage-data.c (get_rusage_data_via_setrlimit): Likewise.
diff --git a/modules/canonicalize-lgpl-tests b/modules/canonicalize-lgpl-tests
index 73a0e32abb..d2b864842a 100644
--- a/modules/canonicalize-lgpl-tests
+++ b/modules/canonicalize-lgpl-tests
@@ -8,6 +8,7 @@ Depends-on:
 ignore-value
 same-inode
 symlink
+str_endswith
 
 configure.ac:
 
diff --git a/modules/canonicalize-tests b/modules/canonicalize-tests
index e043a8daca..5984f665bb 100644
--- a/modules/canonicalize-tests
+++ b/modules/canonicalize-tests
@@ -7,6 +7,7 @@ Depends-on:
 ignore-value
 same-inode
 symlink
+str_endswith
 
 configure.ac:
 
diff --git a/modules/setlocale-tests b/modules/setlocale-tests
index 23cc6ddd17..bd85353d61 100644
--- a/modules/setlocale-tests
+++ b/modules/setlocale-tests
@@ -18,6 +18,7 @@ m4/windows-rc.m4
 
 Depends-on:
 strdup
+str_endswith
 test-xfail
 
 configure.ac:
diff --git a/tests/test-canonicalize-lgpl.c b/tests/test-canonicalize-lgpl.c
index 2a4f5e2ecd..5450bb9b14 100644
--- a/tests/test-canonicalize-lgpl.c
+++ b/tests/test-canonicalize-lgpl.c
@@ -178,8 +178,7 @@ main (void)
     ASSERT (result1 != NULL);
     ASSERT (result2 != NULL);
     ASSERT (strcmp (result1, result2) == 0);
-    ASSERT (strcmp (result1 + strlen (result1) - strlen ("/" BASE "/tra"),
-                    "/" BASE "/tra") == 0);
+    ASSERT (str_endswith (result1, "/" BASE "/tra"));
     free (result1);
     free (result2);
   }
@@ -194,8 +193,7 @@ main (void)
     ASSERT (result3 != NULL);
     ASSERT (strcmp (result1, result2) == 0);
     ASSERT (strcmp (result2, result3) == 0);
-    ASSERT (strcmp (result1 + strlen (result1) - strlen ("/" BASE "/lum"),
-                    "/" BASE "/lum") == 0);
+    ASSERT (str_endswith (result1, "/" BASE "/lum"));
     free (result1);
     free (result2);
     free (result3);
diff --git a/tests/test-canonicalize.c b/tests/test-canonicalize.c
index 0f69f98714..083bf1703a 100644
--- a/tests/test-canonicalize.c
+++ b/tests/test-canonicalize.c
@@ -204,8 +204,7 @@ main (void)
   {
     char *result1 = canonicalize_filename_mode (BASE "/huk", CAN_NOLINKS);
     ASSERT (result1 != NULL);
-    ASSERT (strcmp (result1 + strlen (result1) - strlen ("/" BASE "/huk"),
-                    "/" BASE "/huk") == 0);
+    ASSERT (str_endswith (result1, "/" BASE "/huk"));
     free (result1);
   }
 
@@ -219,8 +218,7 @@ main (void)
     ASSERT (result3 != NULL);
     ASSERT (strcmp (result1, result2) == 0);
     ASSERT (strcmp (result2, result3) == 0);
-    ASSERT (strcmp (result1 + strlen (result1) - strlen ("/" BASE "/tra"),
-                    "/" BASE "/tra") == 0);
+    ASSERT (str_endswith (result1, "/" BASE "/tra"));
     free (result1);
     free (result2);
     free (result3);
@@ -239,8 +237,7 @@ main (void)
     ASSERT (strcmp (result1, result2) == 0);
     ASSERT (strcmp (result2, result3) == 0);
     ASSERT (strcmp (result3, result4) == 0);
-    ASSERT (strcmp (result1 + strlen (result1) - strlen ("/" BASE "/lum"),
-                    "/" BASE "/lum") == 0);
+    ASSERT (str_endswith (result1, "/" BASE "/lum"));
     free (result1);
     free (result2);
     free (result3);
@@ -330,8 +327,7 @@ main (void)
     ASSERT (strcmp (result1, result2) == 0);
     ASSERT (strcmp (result2, result3) == 0);
     ASSERT (strcmp (result3, result4) == 0);
-    ASSERT (strcmp (result1 + strlen (result1) - strlen ("/" BASE "/zzz"),
-                    "/" BASE "/zzz") == 0);
+    ASSERT (str_endswith (result1, "/" BASE "/zzz"));
     free (result1);
     free (result2);
     free (result3);
@@ -351,8 +347,7 @@ main (void)
     ASSERT (strcmp (result1, result2) == 0);
     ASSERT (strcmp (result2, result3) == 0);
     ASSERT (strcmp (result3, result4) == 0);
-    ASSERT (strcmp (result1 + strlen (result1) - strlen ("/" BASE "/wum"),
-                    "/" BASE "/wum") == 0);
+    ASSERT (str_endswith (result1, "/" BASE "/wum"));
     free (result1);
     free (result2);
     free (result3);
@@ -365,7 +360,7 @@ main (void)
     char *result2 = canonicalize_filename_mode ("t-can.zzz/zzz", CAN_MISSING);
     ASSERT (result1 == NULL);
     ASSERT (result2 != NULL);
-    ASSERT (strcmp (result2 + strlen (result2) - 14, "/t-can.zzz/zzz") == 0);
+    ASSERT (str_endswith (result2, "/t-can.zzz/zzz"));
     free (result2);
   }
 
diff --git a/tests/test-setlocale-w32utf8.c b/tests/test-setlocale-w32utf8.c
index 92156c7c01..51828db18e 100644
--- a/tests/test-setlocale-w32utf8.c
+++ b/tests/test-setlocale-w32utf8.c
@@ -41,7 +41,7 @@ main (void)
   /* With the legacy system settings, expect some mixed locale, due to the
      limitations of the native setlocale().
      With the modern system settings, expect some "ll_CC.UTF-8" name.  */
-  if (!((strlen (name) > 6 && strcmp (name + strlen (name) - 6, ".UTF-8") == 0)
+  if (!((strlen (name) > 6 && str_endswith (name, ".UTF-8"))
         || strcmp (name, "LC_COLLATE=English_United States.65001;"
                          "LC_CTYPE=English_United States.65001;"
                          "LC_MONETARY=English_United States.65001;"
-- 
2.43.0

Reply via email to