On Android (Termux environment), I see a test failure of the
test-getlocalename_l test.

The problem is two-fold:

1) The newlocale() function is fake in the same sense as on OpenBSD >= 6.2.
   The fix is to set the macro LOCALENAME_ENHANCE_LOCALE_FUNCS, like on OpenBSD.

2) The setlocale() function does not store the arguments that were passed
   to it, anywhere. This is similar to the problem on native Windows, where
   the LC_MESSAGES category's name is not stored; but here it affects all
   categories. The solution is similar: to provide a place where these
   category names can be stored, in a module that is dependency of
   'setlocale' and 'getlocalename_l-unsafe' and that acts as an enhancement
   of 'setlocale-null'.


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

        getlocalename_l-unsafe: Add Android workaround, like on OpenBSD.
        * m4/intl-thread-locale.m4 (gt_INTL_THREAD_LOCALE_NAME): Set
        gt_cv_locale_fake to yes also on Android.

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

        setlocale-messages: Rename to setlocale-fixes and add Android support.
        * lib/setlocale-fixes.h: Renamed from lib/setlocale-messages.h.
        (setlocale_fixed, setlocale_fixed_null): New declarations.
        * lib/setlocale-fixes.c: Renamed from lib/setlocale-messages.h.
        (lc_cat_name): New variable.
        (cat_to_index, index_to_cat): New macro.
        (lc_all_name): New variable.
        (cat_names): New constant.
        (fill_lc_all_name, extract_single_name, setlocale_fixed,
        setlocale_fixed_null): New functions.
        * m4/setlocale.m4 (gl_FUNC_SETLOCALE): Set NEED_SETLOCALE_IMPROVED to 1
        on Android.
        * lib/setlocale.c: Include setlocale-fixes.h instead of
        setlocale-messages.h.
        (setlocale_unixlike) [__ANDROID__]: Use setlocale_fixed instead of
        setlocale_mtsafe.
        (setlocale_improved): On Android, use setlocale_fixed_null instead of
        setlocale.
        * lib/getlocalename_l-unsafe.c: Include setlocale-fixes.h instead of
        setlocale-messages.h.
        (getlocalename_l_unsafe): On Android, use setlocale_fixed_null instead
        of setlocale_null.
        * modules/setlocale-fixes: Renamed from modules/setlocale-messages.
        (Files): Update.
        (configure.ac): Compile the .c file also on Android.
        (Include): Include setlocale-fixes.h instead of setlocale-messages.h.
        * modules/setlocale (Depends-on): Add setlocale-fixes. Remove
        setlocale-messages.
        * modules/getlocalename_l-unsafe (Depends-on): Likewise.
        * doc/posix-functions/setlocale.texi: Mention the Android problem.

From 40b7c218d7ee1cadd78de79a2dcc7b32a9d92850 Mon Sep 17 00:00:00 2001
From: Bruno Haible <br...@clisp.org>
Date: Sat, 22 Mar 2025 13:03:43 +0100
Subject: [PATCH 1/2] setlocale-messages: Rename to setlocale-fixes and add
 Android support.

* lib/setlocale-fixes.h: Renamed from lib/setlocale-messages.h.
(setlocale_fixed, setlocale_fixed_null): New declarations.
* lib/setlocale-fixes.c: Renamed from lib/setlocale-messages.h.
(lc_cat_name): New variable.
(cat_to_index, index_to_cat): New macro.
(lc_all_name): New variable.
(cat_names): New constant.
(fill_lc_all_name, extract_single_name, setlocale_fixed,
setlocale_fixed_null): New functions.
* m4/setlocale.m4 (gl_FUNC_SETLOCALE): Set NEED_SETLOCALE_IMPROVED to 1
on Android.
* lib/setlocale.c: Include setlocale-fixes.h instead of
setlocale-messages.h.
(setlocale_unixlike) [__ANDROID__]: Use setlocale_fixed instead of
setlocale_mtsafe.
(setlocale_improved): On Android, use setlocale_fixed_null instead of
setlocale.
* lib/getlocalename_l-unsafe.c: Include setlocale-fixes.h instead of
setlocale-messages.h.
(getlocalename_l_unsafe): On Android, use setlocale_fixed_null instead
of setlocale_null.
* modules/setlocale-fixes: Renamed from modules/setlocale-messages.
(Files): Update.
(configure.ac): Compile the .c file also on Android.
(Include): Include setlocale-fixes.h instead of setlocale-messages.h.
* modules/setlocale (Depends-on): Add setlocale-fixes. Remove
setlocale-messages.
* modules/getlocalename_l-unsafe (Depends-on): Likewise.
* doc/posix-functions/setlocale.texi: Mention the Android problem.
---
 ChangeLog                                     |  33 +++
 doc/posix-functions/setlocale.texi            |   3 +
 lib/getlocalename_l-unsafe.c                  |   8 +-
 lib/setlocale-fixes.c                         | 241 ++++++++++++++++++
 ...setlocale-messages.h => setlocale-fixes.h} |  38 ++-
 lib/setlocale-messages.c                      |  45 ----
 lib/setlocale.c                               |   6 +-
 m4/setlocale.m4                               |  31 +--
 modules/getlocalename_l-unsafe                |   2 +-
 modules/setlocale                             |   2 +-
 modules/setlocale-fixes                       |  27 ++
 modules/setlocale-messages                    |  27 --
 12 files changed, 351 insertions(+), 112 deletions(-)
 create mode 100644 lib/setlocale-fixes.c
 rename lib/{setlocale-messages.h => setlocale-fixes.h} (54%)
 delete mode 100644 lib/setlocale-messages.c
 create mode 100644 modules/setlocale-fixes
 delete mode 100644 modules/setlocale-messages

diff --git a/ChangeLog b/ChangeLog
index ff0cc03ec9..4b4c2e8a45 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,36 @@
+2025-03-22  Bruno Haible  <br...@clisp.org>
+
+	setlocale-messages: Rename to setlocale-fixes and add Android support.
+	* lib/setlocale-fixes.h: Renamed from lib/setlocale-messages.h.
+	(setlocale_fixed, setlocale_fixed_null): New declarations.
+	* lib/setlocale-fixes.c: Renamed from lib/setlocale-messages.h.
+	(lc_cat_name): New variable.
+	(cat_to_index, index_to_cat): New macro.
+	(lc_all_name): New variable.
+	(cat_names): New constant.
+	(fill_lc_all_name, extract_single_name, setlocale_fixed,
+	setlocale_fixed_null): New functions.
+	* m4/setlocale.m4 (gl_FUNC_SETLOCALE): Set NEED_SETLOCALE_IMPROVED to 1
+	on Android.
+	* lib/setlocale.c: Include setlocale-fixes.h instead of
+	setlocale-messages.h.
+	(setlocale_unixlike) [__ANDROID__]: Use setlocale_fixed instead of
+	setlocale_mtsafe.
+	(setlocale_improved): On Android, use setlocale_fixed_null instead of
+	setlocale.
+	* lib/getlocalename_l-unsafe.c: Include setlocale-fixes.h instead of
+	setlocale-messages.h.
+	(getlocalename_l_unsafe): On Android, use setlocale_fixed_null instead
+	of setlocale_null.
+	* modules/setlocale-fixes: Renamed from modules/setlocale-messages.
+	(Files): Update.
+	(configure.ac): Compile the .c file also on Android.
+	(Include): Include setlocale-fixes.h instead of setlocale-messages.h.
+	* modules/setlocale (Depends-on): Add setlocale-fixes. Remove
+	setlocale-messages.
+	* modules/getlocalename_l-unsafe (Depends-on): Likewise.
+	* doc/posix-functions/setlocale.texi: Mention the Android problem.
+
 2025-03-21  Bruno Haible  <br...@clisp.org>
 
 	getloadavg: Improve Linux and Android support.
diff --git a/doc/posix-functions/setlocale.texi b/doc/posix-functions/setlocale.texi
index 21b04b6553..48ea614ad5 100644
--- a/doc/posix-functions/setlocale.texi
+++ b/doc/posix-functions/setlocale.texi
@@ -23,6 +23,9 @@
 locale names, that are not based on ISO 639 language names and ISO 3166 country
 names.
 @item
+On Android 5.0 and newer, setting any category other than @code{LC_CTYPE} of
+the global locale affects the @code{LC_CTYPE} category as well.
+@item
 On Android < 5.0, which doesn't have locales, the @code{setlocale} function
 always fails.  The replacement, however, supports only the locale names
 @code{"C"} and @code{"POSIX"}.
diff --git a/lib/getlocalename_l-unsafe.c b/lib/getlocalename_l-unsafe.c
index 627434fc24..1f24f82ddb 100644
--- a/lib/getlocalename_l-unsafe.c
+++ b/lib/getlocalename_l-unsafe.c
@@ -25,8 +25,8 @@
 #include <stdlib.h>
 #include <string.h>
 
-#if LC_MESSAGES == 1729
-# include "setlocale-messages.h"
+#if LC_MESSAGES == 1729 || defined __ANDROID__
+# include "setlocale-fixes.h"
 #endif
 #include "setlocale_null.h"
 
@@ -668,7 +668,11 @@ getlocalename_l_unsafe (int category, locale_t locale)
         name = setlocale_messages_null ();
       else
 #endif
+#if defined __ANDROID__
+        name = setlocale_fixed_null (category);
+#else
         name = setlocale_null (category);
+#endif
       if (name != NULL)
         return (struct string_with_storage) { name, STORAGE_GLOBAL };
       else
diff --git a/lib/setlocale-fixes.c b/lib/setlocale-fixes.c
new file mode 100644
index 0000000000..771ffe15cf
--- /dev/null
+++ b/lib/setlocale-fixes.c
@@ -0,0 +1,241 @@
+/* Make the global locale minimally POSIX compliant.
+   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 2.1 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/>.  */
+
+#include <config.h>
+
+/* Specification.  */
+#include "setlocale-fixes.h"
+
+
+#if defined _WIN32 && !defined __CYGWIN__
+
+# include <stddef.h>
+# include <string.h>
+
+/* The system does not store an LC_MESSAGES locale category.  Do it here.  */
+static char lc_messages_name[64] = "C";
+
+const char *
+setlocale_messages (const char *name)
+{
+  if (name != NULL)
+    {
+      lc_messages_name[sizeof (lc_messages_name) - 1] = '\0';
+      strncpy (lc_messages_name, name, sizeof (lc_messages_name) - 1);
+    }
+  return lc_messages_name;
+}
+
+const char *
+setlocale_messages_null (void)
+{
+  /* This implementation is multithread-safe, assuming no other thread changes
+     the LC_MESSAGES locale category.  */
+  return lc_messages_name;
+}
+
+#endif
+
+
+#if defined __ANDROID__
+
+# include <stddef.h>
+# include <stdlib.h>
+# include <locale.h>
+# include <string.h>
+
+/* Use the system's setlocale() function, not the gnulib override, here.  */
+# undef setlocale
+
+/* Storage for the name of each category of the global locale.
+   Regarding the size, cf. SETLOCALE_NULL_MAX.  */
+static char lc_cat_name[12][256+1] =
+  { "C", "C", "C", "C", "C", "C", "C", "C", "C", "C", "C", "C" };
+/* Mapping from the valid categories to the indices 0..12-1.  */
+#define cat_to_index(cat) ((cat) - ((cat) >= LC_ALL))
+/* Mapping from the indicess 0..12-1 to the valid categories.  */
+#define index_to_cat(i) ((i) + ((i) >= LC_ALL))
+
+/* Storage for the name of the entire global locale.
+   For mixed locales, use the syntax from glibc:
+   LC_CTYPE=...;LC_NUMERIC=...;......;LC_IDENTIFICATION=...
+   Regarding the size, cf. SETLOCALE_NULL_ALL_MAX.  */
+static char lc_all_name[148+12*256+1];
+
+/* Category names.  */
+static const char cat_names[12][17+1] =
+  {
+    [cat_to_index (LC_CTYPE)]          = "LC_CTYPE",
+    [cat_to_index (LC_NUMERIC)]        = "LC_NUMERIC",
+    [cat_to_index (LC_TIME)]           = "LC_TIME",
+    [cat_to_index (LC_COLLATE)]        = "LC_COLLATE",
+    [cat_to_index (LC_MONETARY)]       = "LC_MONETARY",
+    [cat_to_index (LC_MESSAGES)]       = "LC_MESSAGES",
+    [cat_to_index (LC_PAPER)]          = "LC_PAPER",
+    [cat_to_index (LC_NAME)]           = "LC_NAME",
+    [cat_to_index (LC_ADDRESS)]        = "LC_ADDRESS",
+    [cat_to_index (LC_TELEPHONE)]      = "LC_TELEPHONE",
+    [cat_to_index (LC_MEASUREMENT)]    = "LC_MEASUREMENT",
+    [cat_to_index (LC_IDENTIFICATION)] = "LC_IDENTIFICATION",
+  };
+
+/* Combines the contents of all lc_cat_name[], filling lc_all_name.  */
+static void
+fill_lc_all_name (void)
+{
+  bool all_same = true;
+  for (size_t i = 1; i < 12; i++)
+    if (strcmp (lc_cat_name[i], lc_cat_name[0]) != 0)
+      {
+        all_same = false;
+        break;
+      }
+  if (all_same)
+    /* Produce a simple locale name.  */
+    strcpy (lc_all_name, lc_cat_name[0]);
+  else
+    {
+      /* Produce a mixed locale name.  */
+      size_t i;
+      char *q;
+      for (i = 0, q = lc_all_name; i < 12; i++)
+        {
+          const char *p = cat_names[i];
+          size_t n = strlen (p);
+          memcpy (q, p, n); q += n;
+          *q++ = '=';
+          p = lc_cat_name[i];
+          n = strlen (p);
+          memcpy (q, p, n); q += n;
+          *q++ = ';';
+        }
+      *--q = '\0';
+    }
+}
+
+/* Extracts the name of a single category from NAME and stores it in
+   SINGLE_NAME.  CATEGORY must be a valid category name != LC_ALL.
+   This is basically the opposite of fill_lc_all_name.  */
+static int
+extract_single_name (char single_name[256+1], int category, const char *name)
+{
+  if (strchr (name, ';') != NULL)
+    {
+      /* A mixed locale name.  */
+      const char *cat_name = cat_names[cat_to_index (category)];
+      size_t cat_name_len = strlen (cat_name);
+      const char *p = name;
+      for (;;)
+        {
+          const char *q = strchr (p, ';');
+          if (strncmp (p, cat_name, cat_name_len) == 0
+              && p[cat_name_len] == '=')
+            {
+              p += cat_name_len + 1;
+              size_t n = (q == NULL ? strlen (p) : q - p);
+              if (n >= 256+1)
+                n = 256;
+              memcpy (single_name, p, n);
+              single_name[n] = '\0';
+              return 0;
+            }
+          if (q == NULL)
+            break;
+          p = q + 1;
+        }
+      return -1;
+    }
+  else
+    {
+      /* A simple locale name.  */
+      size_t n = strlen (name);
+      if (n >= 256+1)
+        n = 256;
+      memcpy (single_name, name, n);
+      single_name[n] = '\0';
+      return 0;
+    }
+}
+
+const char *
+setlocale_fixed (int category, const char *name)
+{
+  if (category == LC_ALL)
+    {
+      if (name != NULL)
+        {
+          char single_name[256+1];
+          int i;
+
+          /* Test whether NAME is valid.  */
+          for (i = 12-1; i >= 0; i--)
+            if (extract_single_name (single_name, index_to_cat (i), name) < 0)
+              return NULL;
+          /* Now single_name contains the one for the index 0,
+             i.e. for LC_CTYPE.  */
+          if (setlocale (LC_CTYPE, single_name) == NULL)
+            return NULL;
+
+          /* Fill lc_cat_name[].  */
+          for (i = 12-1; i >= 0; i--)
+            {
+              if (extract_single_name (single_name, index_to_cat (i), name) < 0)
+                abort ();
+              strcpy (lc_cat_name[i], single_name);
+            }
+          /* Update lc_all_name.  */
+          fill_lc_all_name ();
+        }
+
+      return lc_all_name;
+    }
+  if (category >= LC_CTYPE && category <= LC_IDENTIFICATION)
+    {
+      if (name != NULL)
+        {
+          char single_name[256+1];
+
+          /* Test whether NAME is valid.  */
+          if (extract_single_name (single_name, category, name) < 0)
+            return NULL;
+          if (category == LC_CTYPE)
+            if (setlocale (category, single_name) == NULL)
+              return NULL;
+
+          /* Fill lc_cat_name[].  */
+          strcpy (lc_cat_name[cat_to_index (category)], single_name);
+          /* Update lc_all_name.  */
+          fill_lc_all_name ();
+        }
+
+      return lc_cat_name[cat_to_index (category)];
+    }
+  return NULL;
+}
+
+const char *
+setlocale_fixed_null (int category)
+{
+  /* This implementation is multithread-safe, assuming no other thread changes
+     any locale category.  */
+  if (category == LC_ALL)
+    return lc_all_name;
+  if (category >= LC_CTYPE && category <= LC_IDENTIFICATION)
+    return lc_cat_name[cat_to_index (category)];
+  return NULL;
+}
+
+#endif
diff --git a/lib/setlocale-messages.h b/lib/setlocale-fixes.h
similarity index 54%
rename from lib/setlocale-messages.h
rename to lib/setlocale-fixes.h
index 06c7a8dd41..d3cd247700 100644
--- a/lib/setlocale-messages.h
+++ b/lib/setlocale-fixes.h
@@ -1,4 +1,4 @@
-/* Extension of the global locale with LC_MESSAGES.
+/* Make the global locale minimally POSIX compliant.
    Copyright (C) 2025 Free Software Foundation, Inc.
 
    This file is free software: you can redistribute it and/or modify
@@ -16,16 +16,19 @@
 
 /* Written by Bruno Haible <br...@clisp.org>, 2025.  */
 
-#ifndef _SETLOCALE_MESSAGES_H
-#define _SETLOCALE_MESSAGES_H
-
-/* This file is only relevant on platforms that lack LC_MESSAGES, namely
-   native Windows.  */
+#ifndef _SETLOCALE_FIXES_H
+#define _SETLOCALE_FIXES_H
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
+
+#if defined _WIN32 && !defined __CYGWIN__
+
+/* This section is only relevant on platforms that lack LC_MESSAGES, namely
+   native Windows.  */
+
 /* setlocale_messages (NAME) is like setlocale (LC_MESSAGES, NAME).  */
 extern const char *setlocale_messages (const char *name);
 
@@ -33,8 +36,29 @@ extern const char *setlocale_messages (const char *name);
    it is guaranteed to be multithread-safe.  */
 extern const char *setlocale_messages_null (void);
 
+#endif
+
+
+#if defined __ANDROID__
+
+/* This section is only relevant on Android.
+   While OpenBSD ??? 6.2 and Android API level >= 21 have a fake locale_t type,
+   regarding the global locale, OpenBSD at least stores the name of each
+   category of the global locale.  Android doesn't do this, and additionally
+   has a bug: setting any category != LC_CTYPE of the global locale affects
+   the LC_CTYPE category as well.  */
+
+/* Like setlocale (CATEGORY, NAME), but fixes these two Android bugs.  */
+extern const char *setlocale_fixed (int category, const char *name);
+
+/* Like setlocale_null (CATEGORY), but consistent with setlocale_fixed.  */
+extern const char *setlocale_fixed_null (int category);
+
+#endif
+
+
 #ifdef __cplusplus
 }
 #endif
 
-#endif /* _SETLOCALE_MESSAGES_H */
+#endif /* _SETLOCALE_FIXES_H */
diff --git a/lib/setlocale-messages.c b/lib/setlocale-messages.c
deleted file mode 100644
index 857236ee59..0000000000
--- a/lib/setlocale-messages.c
+++ /dev/null
@@ -1,45 +0,0 @@
-/* Extension of the global locale with LC_MESSAGES.
-   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 2.1 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/>.  */
-
-#include <config.h>
-
-/* Specification.  */
-#include "setlocale-messages.h"
-
-#include <stddef.h>
-#include <string.h>
-
-/* The system does not store an LC_MESSAGES locale category.  Do it here.  */
-static char lc_messages_name[64] = "C";
-
-const char *
-setlocale_messages (const char *name)
-{
-  if (name != NULL)
-    {
-      lc_messages_name[sizeof (lc_messages_name) - 1] = '\0';
-      strncpy (lc_messages_name, name, sizeof (lc_messages_name) - 1);
-    }
-  return lc_messages_name;
-}
-
-const char *
-setlocale_messages_null (void)
-{
-  /* This implementation is multithread-safe, assuming no other thread changes
-     the LC_MESSAGES locale category.  */
-  return lc_messages_name;
-}
diff --git a/lib/setlocale.c b/lib/setlocale.c
index 5095eddb64..b5a9bdf89c 100644
--- a/lib/setlocale.c
+++ b/lib/setlocale.c
@@ -33,7 +33,7 @@
 #include <stdlib.h>
 #include <string.h>
 
-#include "setlocale-messages.h"
+#include "setlocale-fixes.h"
 #include "localename.h"
 
 #if HAVE_CFLOCALECOPYPREFERREDLANGUAGES || HAVE_CFPREFERENCESCOPYAPPVALUE
@@ -873,7 +873,7 @@ setlocale_unixlike (int category, const char *locale)
 static char *
 setlocale_unixlike (int category, const char *locale)
 {
-  char *result = setlocale_mtsafe (category, locale);
+  char *result = setlocale_fixed (category, locale);
   if (result == NULL)
     switch (category)
       {
@@ -1805,6 +1805,8 @@ setlocale_improved (int category, const char *locale)
         return resultbuf;
       }
   }
+#  elif defined __ANDROID__
+  return setlocale_fixed_null (LC_ALL);
 #  else
   return setlocale (LC_ALL, NULL);
 #  endif
diff --git a/m4/setlocale.m4 b/m4/setlocale.m4
index 6c033ddea4..16413cec36 100644
--- a/m4/setlocale.m4
+++ b/m4/setlocale.m4
@@ -1,5 +1,5 @@
 # setlocale.m4
-# serial 10
+# serial 11
 dnl Copyright (C) 2011-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,
@@ -18,6 +18,9 @@ AC_DEFUN([gl_FUNC_SETLOCALE]
     dnl On native Windows systems, setlocale(category,NULL) does not look at
     dnl the environment variables LC_ALL, category, and LANG.
     mingw* | windows*) NEED_SETLOCALE_IMPROVED=1 ;;
+    dnl On Android, setlocale(category,name) treats all categories as equivalent
+    dnl to LC_CTYPE. And on Android 4.3, setlocale(category,"C") always fails.
+    *-android*) NEED_SETLOCALE_IMPROVED=1 ;;
     dnl On Cygwin 1.5.x, setlocale always succeeds but setlocale(LC_CTYPE,NULL)
     dnl is then still "C".
     cygwin*)
@@ -25,32 +28,6 @@ AC_DEFUN([gl_FUNC_SETLOCALE]
         1.5.*) NEED_SETLOCALE_IMPROVED=1 ;;
       esac
       ;;
-    dnl On Android 4.3, setlocale(category,"C") always fails.
-    *)
-      AC_CACHE_CHECK([whether setlocale supports the C locale],
-        [gl_cv_func_setlocale_works],
-        [AC_RUN_IFELSE(
-           [AC_LANG_SOURCE([[
-#include <locale.h>
-int main ()
-{
-  return setlocale (LC_ALL, "C") == NULL;
-}]])],
-           [gl_cv_func_setlocale_works=yes],
-           [gl_cv_func_setlocale_works=no],
-           [case "$host_os" in
-                               # Guess no on Android.
-              linux*-android*) gl_cv_func_setlocale_works="guessing no";;
-                               # Guess yes otherwise.
-              *)               gl_cv_func_setlocale_works="guessing yes";;
-            esac
-           ])
-        ])
-      case "$gl_cv_func_setlocale_works" in
-        *yes) ;;
-        *) NEED_SETLOCALE_IMPROVED=1 ;;
-      esac
-      ;;
   esac
   AC_DEFINE_UNQUOTED([NEED_SETLOCALE_IMPROVED], [$NEED_SETLOCALE_IMPROVED],
     [Define to 1 to enable general improvements of setlocale.])
diff --git a/modules/getlocalename_l-unsafe b/modules/getlocalename_l-unsafe
index b3873d7b02..c2392fc39d 100644
--- a/modules/getlocalename_l-unsafe
+++ b/modules/getlocalename_l-unsafe
@@ -17,7 +17,7 @@ flexmember
 lock
 bool
 thread-optim
-setlocale-messages
+setlocale-fixes
 setlocale-null
 free-posix
 
diff --git a/modules/setlocale b/modules/setlocale
index 45c35ff808..4cf9597ea8 100644
--- a/modules/setlocale
+++ b/modules/setlocale
@@ -7,7 +7,7 @@ m4/setlocale.m4
 
 Depends-on:
 locale-h
-setlocale-messages [test $NEED_SETLOCALE_IMPROVED = 1]
+setlocale-fixes    [test $NEED_SETLOCALE_IMPROVED = 1]
 localename         [test $NEED_SETLOCALE_IMPROVED = 1]
 localename-environ [test $NEED_SETLOCALE_IMPROVED = 1]
 setlocale-null     [test $NEED_SETLOCALE_MTSAFE = 1]
diff --git a/modules/setlocale-fixes b/modules/setlocale-fixes
new file mode 100644
index 0000000000..a397793da9
--- /dev/null
+++ b/modules/setlocale-fixes
@@ -0,0 +1,27 @@
+Description:
+Make the global locale minimally POSIX compliant.
+
+Files:
+lib/setlocale-fixes.h
+lib/setlocale-fixes.c
+
+Depends-on:
+
+configure.ac:
+AC_REQUIRE([AC_CANONICAL_HOST])
+gl_CONDITIONAL([GL_COND_OBJ_SETLOCALE_FIXES],
+               [case "$host_os" in mingw* | windows* | *-android*) true;; *) false;; esac])
+
+Makefile.am:
+if GL_COND_OBJ_SETLOCALE_FIXES
+lib_SOURCES += setlocale-fixes.c
+endif
+
+Include:
+"setlocale-fixes.h"
+
+License:
+LGPLv2+
+
+Maintainer:
+all
diff --git a/modules/setlocale-messages b/modules/setlocale-messages
deleted file mode 100644
index bd7c078cc8..0000000000
--- a/modules/setlocale-messages
+++ /dev/null
@@ -1,27 +0,0 @@
-Description:
-Extension of the global locale with LC_MESSAGES.
-
-Files:
-lib/setlocale-messages.h
-lib/setlocale-messages.c
-
-Depends-on:
-
-configure.ac:
-AC_REQUIRE([AC_CANONICAL_HOST])
-gl_CONDITIONAL([GL_COND_OBJ_SETLOCALE_MESSAGES],
-               [case "$host_os" in mingw* | windows*) true;; *) false;; esac])
-
-Makefile.am:
-if GL_COND_OBJ_SETLOCALE_MESSAGES
-lib_SOURCES += setlocale-messages.c
-endif
-
-Include:
-"setlocale-messages.h"
-
-License:
-LGPLv2+
-
-Maintainer:
-all
-- 
2.43.0

From 979dcc75b404ed579e588e048a13145f04440e15 Mon Sep 17 00:00:00 2001
From: Bruno Haible <br...@clisp.org>
Date: Sat, 22 Mar 2025 13:06:36 +0100
Subject: [PATCH 2/2] getlocalename_l-unsafe: Add Android workaround, like on
 OpenBSD.

* m4/intl-thread-locale.m4 (gt_INTL_THREAD_LOCALE_NAME): Set
gt_cv_locale_fake to yes also on Android.
---
 ChangeLog                |  6 ++++++
 m4/intl-thread-locale.m4 | 44 ++++++++++++++++++++++++----------------
 2 files changed, 33 insertions(+), 17 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 4b4c2e8a45..12aa0404b6 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2025-03-22  Bruno Haible  <br...@clisp.org>
+
+	getlocalename_l-unsafe: Add Android workaround, like on OpenBSD.
+	* m4/intl-thread-locale.m4 (gt_INTL_THREAD_LOCALE_NAME): Set
+	gt_cv_locale_fake to yes also on Android.
+
 2025-03-22  Bruno Haible  <br...@clisp.org>
 
 	setlocale-messages: Rename to setlocale-fixes and add Android support.
diff --git a/m4/intl-thread-locale.m4 b/m4/intl-thread-locale.m4
index 084eacf14a..91a1c20896 100644
--- a/m4/intl-thread-locale.m4
+++ b/m4/intl-thread-locale.m4
@@ -1,5 +1,5 @@
 # intl-thread-locale.m4
-# serial 14
+# serial 15
 dnl Copyright (C) 2015-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,
@@ -40,15 +40,21 @@ AC_DEFUN([gt_INTL_THREAD_LOCALE_NAME]
   dnl they did not think about the programs.
   dnl In this situation, even the HAVE_NAMELESS_LOCALES support cannot make
   dnl uselocale() work.
+  dnl Similarly on Android. See
+  dnl <https://android.googlesource.com/platform/bionic/+/refs/heads/main/libc/bionic/locale.cpp>.
   dnl So, define HAVE_FAKE_LOCALES and disable all per-thread locale support.
-  dnl Expected result: HAVE_FAKE_LOCALES is defined on OpenBSD ??? 6.2.
+  dnl Expected result:
+  dnl - HAVE_FAKE_LOCALES is defined on OpenBSD ??? 6.2, Android API level >= 21.
   case "$gt_cv_func_uselocale_works" in
     *yes)
       AC_CHECK_HEADERS_ONCE([xlocale.h])
-      AC_CACHE_CHECK([for fake locale system (OpenBSD)],
+      AC_CACHE_CHECK([for fake locale system (OpenBSD, Android)],
         [gt_cv_locale_fake],
-        [AC_RUN_IFELSE(
-           [AC_LANG_SOURCE([[
+        [case "$host_os" in
+           *-android*) gt_cv_locale_fake=yes ;;
+           *)
+             AC_RUN_IFELSE(
+               [AC_LANG_SOURCE([[
 #include <locale.h>
 #if HAVE_XLOCALE_H
 # include <xlocale.h>
@@ -62,14 +68,16 @@ AC_DEFUN([gt_INTL_THREAD_LOCALE_NAME]
   loc2 = newlocale (LC_ALL_MASK, "fr_FR.UTF-8", (locale_t)0);
   return !(loc1 == loc2);
 }]])],
-           [gt_cv_locale_fake=yes],
-           [gt_cv_locale_fake=no],
-           [dnl Guess the locale system is fake only on OpenBSD.
-            case "$host_os" in
-              openbsd*) gt_cv_locale_fake="guessing yes" ;;
-              *)        gt_cv_locale_fake="guessing no" ;;
-            esac
-           ])
+               [gt_cv_locale_fake=yes],
+               [gt_cv_locale_fake=no],
+               [dnl Guess the locale system is fake only on OpenBSD.
+                case "$host_os" in
+                  openbsd*) gt_cv_locale_fake="guessing yes" ;;
+                  *)        gt_cv_locale_fake="guessing no" ;;
+                esac
+               ])
+             ;;
+         esac
         ])
       ;;
     *) gt_cv_locale_fake=no ;;
@@ -124,8 +132,10 @@ AC_DEFUN([gt_INTL_THREAD_LOCALE_NAME]
   dnl requires the gnulib overrides of 'newlocale', 'duplocale', 'freelocale',
   dnl which is a problem for GNU libunistring.  Therefore try hard to avoid
   dnl enabling this code!
-  dnl Expected result: HAVE_NAMELESS_LOCALES is defined on OpenBSD ??? 6.2, AIX,
-  dnl and              HAVE_AIX72_LOCALES is defined on AIX ??? 7.2.
+  dnl Expected result:
+  dnl   - HAVE_NAMELESS_LOCALES is defined on OpenBSD ??? 6.2, AIX,
+  dnl                                         Android API level >= 21,
+  dnl   - HAVE_AIX72_LOCALES is defined on AIX ??? 7.2.
   gt_nameless_locales=$gt_fake_locales
   case "$host_os" in
     dnl It's needed on AIX 7.2.
@@ -162,7 +172,7 @@ AC_DEFUN([gt_INTL_THREAD_LOCALE_NAME]
   dnl   gt_good_uselocale = gt_working_uselocale && !gt_fake_locales.
   dnl Expected result: HAVE_GOOD_USELOCALE is defined on all platforms except
   dnl FreeBSD < 9.1, NetBSD, OpenBSD, Minix, AIX < 7, AIX 7.2, HP-UX, IRIX,
-  dnl Solaris < 11.4, Cygwin < 2.6, mingw, MSVC 14, Android API level < 21.
+  dnl Solaris < 11.4, Cygwin < 2.6, mingw, MSVC 14, Android.
   if test $gt_working_uselocale = yes && test $gt_fake_locales = no; then
     gt_good_uselocale=yes
     AC_DEFINE([HAVE_GOOD_USELOCALE], [1],
@@ -175,7 +185,7 @@ AC_DEFUN([gt_INTL_THREAD_LOCALE_NAME]
   dnl overrides newlocale(), duplocale(), freelocale() to keep track of locale
   dnl names.
   dnl Expected result: LOCALENAME_ENHANCE_LOCALE_FUNCS is defined on
-  dnl OpenBSD ??? 6.2, AIX 7.1, AIX ??? 7.3.
+  dnl OpenBSD ??? 6.2, AIX 7.1, AIX ??? 7.3, Android API level >= 21.
   if test $gt_working_uselocale = yes && test $gt_nameless_locales = yes; then
     gt_localename_enhances_locale_funcs=yes
     LOCALENAME_ENHANCE_LOCALE_FUNCS=1
-- 
2.43.0

Reply via email to