summaryrefslogtreecommitdiff
path: root/lib/setlocale_null.c
diff options
context:
space:
mode:
authorBruno Haible <bruno@clisp.org>2019-12-18 16:30:09 +0100
committerBruno Haible <bruno@clisp.org>2019-12-18 16:33:48 +0100
commit3a310962887322e0b94708984886de643f94f8a5 (patch)
treed17f7545cbae02461db7cc47a219396a6faf7a33 /lib/setlocale_null.c
parentf7efd84ea3e6ff2be5932b5213ac60c5c022f5b9 (diff)
downloadgnulib-3a310962887322e0b94708984886de643f94f8a5.tar.gz
setlocale-null: Make API more useful.
* lib/locale.in.h (setlocale_null_r): Renamed from setlocale_null. All callers changed. (setlocale_null): New declaration. * lib/setlocale_null.c (setlocale_null_androidfix): New function, extracted from setlocale_null_unlocked. (setlocale_null_unlocked): Invoke it. (setlocale_null_r): Renamed from setlocale_null. (setlocale_null): New function, extracted from setlocale_mtsafe in setlocale.c. * lib/setlocale.c: Don't include <errno.h>. (setlocale_mtsafe): Invoke setlocale_null. * lib/setlocale-lock.c: Update comments. * doc/posix-functions/setlocale.texi: Mention both functions.
Diffstat (limited to 'lib/setlocale_null.c')
-rw-r--r--lib/setlocale_null.c171
1 files changed, 146 insertions, 25 deletions
diff --git a/lib/setlocale_null.c b/lib/setlocale_null.c
index 8072a4560e..c20125709a 100644
--- a/lib/setlocale_null.c
+++ b/lib/setlocale_null.c
@@ -55,6 +55,37 @@
/* 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)
{
@@ -105,30 +136,7 @@ setlocale_null_unlocked (int category, char *buf, size_t bufsize)
}
}
#else
- 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
+ const char *result = setlocale_null_androidfix (category);
if (result == NULL)
{
@@ -257,7 +265,7 @@ setlocale_null_with_lock (int category, char *buf, size_t bufsize)
#endif
int
-setlocale_null (int category, char *buf, size_t bufsize)
+setlocale_null_r (int category, char *buf, size_t bufsize)
{
#if SETLOCALE_NULL_ALL_MTSAFE
# if SETLOCALE_NULL_ONE_MTSAFE
@@ -287,3 +295,116 @@ setlocale_null (int category, char *buf, size_t bufsize)
# endif
#endif
}
+
+const char *
+setlocale_null (int category)
+{
+#if SETLOCALE_NULL_ALL_MTSAFE && SETLOCALE_NULL_ONE_MTSAFE
+ return setlocale_null_androidfix (category);
+#else
+
+ /* This call must be multithread-safe. To achieve this without using
+ thread-local storage:
+ 1. We use a specific static buffer for each possible CATEGORY
+ argument. So that different threads can call setlocale_mtsafe
+ with different CATEGORY arguments, without interfering.
+ 2. We use a simple strcpy or memcpy to fill this static buffer.
+ Filling it through, for example, strcpy + strcat would not be
+ guaranteed to leave the buffer's contents intact if another thread
+ is currently accessing it. If necessary, the contents is first
+ assembled in a stack-allocated buffer. */
+ if (category == LC_ALL)
+ {
+# if SETLOCALE_NULL_ALL_MTSAFE
+ return setlocale_null_androidfix (LC_ALL);
+# else
+ char buf[SETLOCALE_NULL_ALL_MAX];
+ static char resultbuf[SETLOCALE_NULL_ALL_MAX];
+
+ if (setlocale_null_r (LC_ALL, buf, sizeof (buf)))
+ return "C";
+ strcpy (resultbuf, buf);
+ return resultbuf;
+# endif
+ }
+ else
+ {
+# if SETLOCALE_NULL_ONE_MTSAFE
+ return setlocale_null_androidfix (category);
+# else
+ enum
+ {
+ LC_CTYPE_INDEX,
+ LC_NUMERIC_INDEX,
+ LC_TIME_INDEX,
+ LC_COLLATE_INDEX,
+ LC_MONETARY_INDEX,
+ LC_MESSAGES_INDEX,
+# ifdef LC_PAPER
+ LC_PAPER_INDEX,
+# endif
+# ifdef LC_NAME
+ LC_NAME_INDEX,
+# endif
+# ifdef LC_ADDRESS
+ LC_ADDRESS_INDEX,
+# endif
+# ifdef LC_TELEPHONE
+ LC_TELEPHONE_INDEX,
+# endif
+# ifdef LC_MEASUREMENT
+ LC_MEASUREMENT_INDEX,
+# endif
+# ifdef LC_IDENTIFICATION
+ LC_IDENTIFICATION_INDEX,
+# endif
+ LC_INDICES_COUNT
+ }
+ i;
+ char buf[SETLOCALE_NULL_MAX];
+ static char resultbuf[LC_INDICES_COUNT][SETLOCALE_NULL_MAX];
+ int err;
+
+ err = setlocale_null_r (category, buf, sizeof (buf));
+ if (err == EINVAL)
+ return NULL;
+ if (err)
+ return "C";
+
+ switch (category)
+ {
+ case LC_CTYPE: i = LC_CTYPE_INDEX; break;
+ case LC_NUMERIC: i = LC_NUMERIC_INDEX; break;
+ case LC_TIME: i = LC_TIME_INDEX; break;
+ case LC_COLLATE: i = LC_COLLATE_INDEX; break;
+ case LC_MONETARY: i = LC_MONETARY_INDEX; break;
+ case LC_MESSAGES: i = LC_MESSAGES_INDEX; break;
+# ifdef LC_PAPER
+ case LC_PAPER: i = LC_PAPER_INDEX; break;
+# endif
+# ifdef LC_NAME
+ case LC_NAME: i = LC_NAME_INDEX; break;
+# endif
+# ifdef LC_ADDRESS
+ case LC_ADDRESS: i = LC_ADDRESS_INDEX; break;
+# endif
+# ifdef LC_TELEPHONE
+ case LC_TELEPHONE: i = LC_TELEPHONE_INDEX; break;
+# endif
+# ifdef LC_MEASUREMENT
+ case LC_MEASUREMENT: i = LC_MEASUREMENT_INDEX; break;
+# endif
+# ifdef LC_IDENTIFICATION
+ case LC_IDENTIFICATION: i = LC_IDENTIFICATION_INDEX; break;
+# endif
+ default:
+ /* If you get here, a #ifdef LC_xxx is missing. */
+ abort ();
+ }
+
+ strcpy (resultbuf[i], buf);
+ return resultbuf[i];
+# endif
+ }
+#endif
+}