summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBruno Haible <bruno@clisp.org>2023-04-05 15:15:00 +0200
committerBruno Haible <bruno@clisp.org>2023-04-05 15:15:00 +0200
commitd795780cfbf8b3e5881f214bc44252e1126c66f5 (patch)
treeda5fcf58c126c528ae439334ce2b1f4734fef9f1
parentbfe8d458485a452a56e819f9adc5f1499dc86d98 (diff)
downloadgnulib-d795780cfbf8b3e5881f214bc44252e1126c66f5.tar.gz
localename: Add support for Haiku's per-thread locales.
* lib/localename.c: Include <dlfcn.h>. (gl_locale_name_thread_unsafe): Add special code for Haiku.
-rw-r--r--ChangeLog6
-rw-r--r--lib/localename.c65
2 files changed, 71 insertions, 0 deletions
diff --git a/ChangeLog b/ChangeLog
index 1d8429955c..c629b253f5 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,11 @@
2023-04-05 Bruno Haible <bruno@clisp.org>
+ localename: Add support for Haiku's per-thread locales.
+ * lib/localename.c: Include <dlfcn.h>.
+ (gl_locale_name_thread_unsafe): Add special code for Haiku.
+
+2023-04-05 Bruno Haible <bruno@clisp.org>
+
uchar: Work around Haiku bug.
* m4/uchar_h.m4 (gl_UCHAR_H, gl_TYPE_CHAR8_T, gl_TYPE_CHAR16_T,
gl_TYPE_CHAR32_T): Before including <uchar.h>, on Haiku, first include
diff --git a/lib/localename.c b/lib/localename.c
index 8fe90e0bf2..3c1dc67c14 100644
--- a/lib/localename.c
+++ b/lib/localename.c
@@ -59,6 +59,9 @@ extern char * getlocalename_l(int, locale_t);
# if HAVE_NAMELESS_LOCALES
# include "localename-table.h"
# endif
+# if defined __HAIKU__
+# include <dlfcn.h>
+# endif
#endif
#if HAVE_CFPREFERENCESCOPYAPPVALUE
@@ -3203,6 +3206,68 @@ gl_locale_name_thread_unsafe (int category, _GL_UNUSED const char *categoryname)
};
return ((struct __locale_t *) thread_locale)->categories[category];
# endif
+# elif defined __HAIKU__
+ /* Since 2022, Haiku has per-thread locales. locale_t is 'void *',
+ but in fact a 'LocaleBackendData *'. */
+ struct LocaleBackendData {
+ int magic;
+ void /*BPrivate::Libroot::LocaleBackend*/ *backend;
+ void /*BPrivate::Libroot::LocaleDataBridge*/ *databridge;
+ };
+ void *thread_locale_backend =
+ ((struct LocaleBackendData *) thread_locale)->backend;
+ if (thread_locale_backend != NULL)
+ {
+ /* The only existing concrete subclass of
+ BPrivate::Libroot::LocaleBackend is
+ BPrivate::Libroot::ICULocaleBackend.
+ Invoke the (non-virtual) method
+ BPrivate::Libroot::ICULocaleBackend::_QueryLocale on it.
+ This method is located in a separate shared library,
+ libroot-addon-icu.so. */
+ static void * volatile querylocale_method /* = NULL */;
+ static int volatile querylocale_found /* = 0 */;
+ /* Attempt to open this shared library, the first time we get
+ here. */
+ if (querylocale_found == 0)
+ {
+ void *handle =
+ dlopen ("/boot/system/lib/libroot-addon-icu.so", 0);
+ if (handle != NULL)
+ {
+ void *sym =
+ dlsym (handle, "_ZN8BPrivate7Libroot16ICULocaleBackend12_QueryLocaleEi");
+ if (sym != NULL)
+ {
+ querylocale_method = sym;
+ querylocale_found = 1;
+ }
+ else
+ /* Could not find the symbol. */
+ querylocale_found = -1;
+ }
+ else
+ /* Could not open the separate shared library. */
+ querylocale_found = -1;
+ }
+ if (querylocale_found > 0)
+ {
+ /* The _QueryLocale method is a non-static C++ method with
+ parameters (int category) and return type 'const char *'.
+ See
+ haiku/headers/private/libroot/locale/ICULocaleBackend.h
+ haiku/src/system/libroot/add-ons/icu/ICULocaleBackend.cpp
+ This is the same as a C function with parameters
+ (BPrivate::Libroot::LocaleBackend* this, int category)
+ and return type 'const char *'. Invoke it. */
+ const char * (*querylocale_func) (void *, int) =
+ (const char * (*) (void *, int)) querylocale_method;
+ return querylocale_func (thread_locale_backend, category);
+ }
+ }
+ else
+ /* It's the "C" or "POSIX" locale. */
+ return "C";
# elif defined __ANDROID__
return MB_CUR_MAX == 4 ? "C.UTF-8" : "C";
# endif