summaryrefslogtreecommitdiff
path: root/lib/setlocale_null.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/setlocale_null.c')
-rw-r--r--lib/setlocale_null.c176
1 files changed, 32 insertions, 144 deletions
diff --git a/lib/setlocale_null.c b/lib/setlocale_null.c
index 778429b9..5ecf413d 100644
--- a/lib/setlocale_null.c
+++ b/lib/setlocale_null.c
@@ -1,5 +1,5 @@
/* Query the name of the current global locale.
- Copyright (C) 2019-2022 Free Software Foundation, Inc.
+ Copyright (C) 2019-2024 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
@@ -25,12 +25,14 @@
#include <locale.h>
#include <stdlib.h>
#include <string.h>
-#if defined _WIN32 && !defined __CYGWIN__
-# include <wchar.h>
-#endif
#if !(SETLOCALE_NULL_ALL_MTSAFE && SETLOCALE_NULL_ONE_MTSAFE)
-# if defined _WIN32 && !defined __CYGWIN__
+
+# if AVOID_ANY_THREADS
+
+/* The option '--disable-threads' explicitly requests no locking. */
+
+# elif defined _WIN32 && !defined __CYGWIN__
# define WIN32_LEAN_AND_MEAN /* avoid including junk */
# include <windows.h>
@@ -51,154 +53,40 @@
# include <threads.h>
# endif
-#endif
-/* Use the system's setlocale() function, not the gnulib override, here. */
-#undef setlocale
-
-static const char *
-setlocale_null_androidfix (int category)
-{
- const char *result = setlocale (category, NULL);
-
-#ifdef __ANDROID__
- if (result == NULL)
- switch (category)
- {
- case LC_CTYPE:
- case LC_NUMERIC:
- case LC_TIME:
- case LC_COLLATE:
- case LC_MONETARY:
- case LC_MESSAGES:
- case LC_ALL:
- case LC_PAPER:
- case LC_NAME:
- case LC_ADDRESS:
- case LC_TELEPHONE:
- case LC_MEASUREMENT:
- result = "C";
- break;
- default:
- break;
- }
#endif
- return result;
-}
-
-static int
-setlocale_null_unlocked (int category, char *buf, size_t bufsize)
-{
-#if defined _WIN32 && !defined __CYGWIN__ && defined _MSC_VER
- /* On native Windows, nowadays, the setlocale() implementation is based
- on _wsetlocale() and uses malloc() for the result. We are better off
- using _wsetlocale() directly. */
- const wchar_t *result = _wsetlocale (category, NULL);
-
- if (result == NULL)
- {
- /* CATEGORY is invalid. */
- if (bufsize > 0)
- /* Return an empty string in BUF.
- This is a convenience for callers that don't want to write explicit
- code for handling EINVAL. */
- buf[0] = '\0';
- return EINVAL;
- }
- else
- {
- size_t length = wcslen (result);
- if (length < bufsize)
- {
- size_t i;
-
- /* Convert wchar_t[] -> char[], assuming plain ASCII. */
- for (i = 0; i <= length; i++)
- buf[i] = result[i];
+#if !(SETLOCALE_NULL_ALL_MTSAFE && SETLOCALE_NULL_ONE_MTSAFE) /* musl libc, macOS, FreeBSD, NetBSD, OpenBSD, AIX, Haiku, Cygwin < 3.4.6 */
- return 0;
- }
- else
- {
- if (bufsize > 0)
- {
- /* Return a truncated result in BUF.
- This is a convenience for callers that don't want to write
- explicit code for handling ERANGE. */
- size_t i;
-
- /* Convert wchar_t[] -> char[], assuming plain ASCII. */
- for (i = 0; i < bufsize; i++)
- buf[i] = result[i];
- buf[bufsize - 1] = '\0';
- }
- return ERANGE;
- }
- }
-#else
- const char *result = setlocale_null_androidfix (category);
-
- if (result == NULL)
- {
- /* CATEGORY is invalid. */
- if (bufsize > 0)
- /* Return an empty string in BUF.
- This is a convenience for callers that don't want to write explicit
- code for handling EINVAL. */
- buf[0] = '\0';
- return EINVAL;
- }
- else
- {
- size_t length = strlen (result);
- if (length < bufsize)
- {
- memcpy (buf, result, length + 1);
- return 0;
- }
- else
- {
- if (bufsize > 0)
- {
- /* Return a truncated result in BUF.
- This is a convenience for callers that don't want to write
- explicit code for handling ERANGE. */
- memcpy (buf, result, bufsize - 1);
- buf[bufsize - 1] = '\0';
- }
- return ERANGE;
- }
- }
-#endif
-}
-
-#if !(SETLOCALE_NULL_ALL_MTSAFE && SETLOCALE_NULL_ONE_MTSAFE) /* musl libc, macOS, FreeBSD, NetBSD, OpenBSD, AIX, Haiku, Cygwin */
-
-/* Use a lock, so that no two threads can invoke setlocale_null_unlocked
+/* Use a lock, so that no two threads can invoke setlocale_null_r_unlocked
at the same time. */
/* Prohibit renaming this symbol. */
# undef gl_get_setlocale_null_lock
-# if defined _WIN32 && !defined __CYGWIN__
+# if AVOID_ANY_THREADS
+
+/* The option '--disable-threads' explicitly requests no locking. */
+# define setlocale_null_r_with_lock setlocale_null_r_unlocked
+
+# elif defined _WIN32 && !defined __CYGWIN__
extern __declspec(dllimport) CRITICAL_SECTION *gl_get_setlocale_null_lock (void);
static int
-setlocale_null_with_lock (int category, char *buf, size_t bufsize)
+setlocale_null_r_with_lock (int category, char *buf, size_t bufsize)
{
CRITICAL_SECTION *lock = gl_get_setlocale_null_lock ();
int ret;
EnterCriticalSection (lock);
- ret = setlocale_null_unlocked (category, buf, bufsize);
+ ret = setlocale_null_r_unlocked (category, buf, bufsize);
LeaveCriticalSection (lock);
return ret;
}
-# elif HAVE_PTHREAD_API /* musl libc, macOS, FreeBSD, NetBSD, OpenBSD, AIX, Haiku, Cygwin */
+# elif HAVE_PTHREAD_API /* musl libc, macOS, FreeBSD, NetBSD, OpenBSD, AIX, Haiku, Cygwin < 3.4.6 */
extern
# if defined _WIN32 || defined __CYGWIN__
@@ -223,7 +111,7 @@ extern
# endif
static int
-setlocale_null_with_lock (int category, char *buf, size_t bufsize)
+setlocale_null_r_with_lock (int category, char *buf, size_t bufsize)
{
if (pthread_in_use())
{
@@ -232,14 +120,14 @@ setlocale_null_with_lock (int category, char *buf, size_t bufsize)
if (pthread_mutex_lock (lock))
abort ();
- ret = setlocale_null_unlocked (category, buf, bufsize);
+ ret = setlocale_null_r_unlocked (category, buf, bufsize);
if (pthread_mutex_unlock (lock))
abort ();
return ret;
}
else
- return setlocale_null_unlocked (category, buf, bufsize);
+ return setlocale_null_r_unlocked (category, buf, bufsize);
}
# elif HAVE_THREADS_H
@@ -247,14 +135,14 @@ setlocale_null_with_lock (int category, char *buf, size_t bufsize)
extern mtx_t *gl_get_setlocale_null_lock (void);
static int
-setlocale_null_with_lock (int category, char *buf, size_t bufsize)
+setlocale_null_r_with_lock (int category, char *buf, size_t bufsize)
{
mtx_t *lock = gl_get_setlocale_null_lock ();
int ret;
if (mtx_lock (lock) != thrd_success)
abort ();
- ret = setlocale_null_unlocked (category, buf, bufsize);
+ ret = setlocale_null_r_unlocked (category, buf, bufsize);
if (mtx_unlock (lock) != thrd_success)
abort ();
@@ -271,27 +159,27 @@ setlocale_null_r (int category, char *buf, size_t bufsize)
#if SETLOCALE_NULL_ALL_MTSAFE
# if SETLOCALE_NULL_ONE_MTSAFE
- return setlocale_null_unlocked (category, buf, bufsize);
+ return setlocale_null_r_unlocked (category, buf, bufsize);
# else
if (category == LC_ALL)
- return setlocale_null_unlocked (category, buf, bufsize);
+ return setlocale_null_r_unlocked (category, buf, bufsize);
else
- return setlocale_null_with_lock (category, buf, bufsize);
+ return setlocale_null_r_with_lock (category, buf, bufsize);
# endif
#else
# if SETLOCALE_NULL_ONE_MTSAFE
if (category == LC_ALL)
- return setlocale_null_with_lock (category, buf, bufsize);
+ return setlocale_null_r_with_lock (category, buf, bufsize);
else
- return setlocale_null_unlocked (category, buf, bufsize);
+ return setlocale_null_r_unlocked (category, buf, bufsize);
# else
- return setlocale_null_with_lock (category, buf, bufsize);
+ return setlocale_null_r_with_lock (category, buf, bufsize);
# endif
#endif
@@ -301,7 +189,7 @@ const char *
setlocale_null (int category)
{
#if SETLOCALE_NULL_ALL_MTSAFE && SETLOCALE_NULL_ONE_MTSAFE
- return setlocale_null_androidfix (category);
+ return setlocale_null_unlocked (category);
#else
/* This call must be multithread-safe. To achieve this without using
@@ -317,7 +205,7 @@ setlocale_null (int category)
if (category == LC_ALL)
{
# if SETLOCALE_NULL_ALL_MTSAFE
- return setlocale_null_androidfix (LC_ALL);
+ return setlocale_null_unlocked (LC_ALL);
# else
char buf[SETLOCALE_NULL_ALL_MAX];
static char resultbuf[SETLOCALE_NULL_ALL_MAX];
@@ -331,7 +219,7 @@ setlocale_null (int category)
else
{
# if SETLOCALE_NULL_ONE_MTSAFE
- return setlocale_null_androidfix (category);
+ return setlocale_null_unlocked (category);
# else
enum
{