From: Bruno Haible Date: Wed, 5 Apr 2023 13:15:00 +0000 (+0200) Subject: localename: Add support for Haiku's per-thread locales. X-Git-Tag: v1.0~1505 X-Git-Url: https://gitweb.git.savannah.gnu.org/gitweb/?a=commitdiff_plain;h=d795780cfbf8b3e5881f214bc44252e1126c66f5;p=gnulib.git localename: Add support for Haiku's per-thread locales. * lib/localename.c: Include . (gl_locale_name_thread_unsafe): Add special code for Haiku. --- diff --git a/ChangeLog b/ChangeLog index 1d8429955c..c629b253f5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2023-04-05 Bruno Haible + + localename: Add support for Haiku's per-thread locales. + * lib/localename.c: Include . + (gl_locale_name_thread_unsafe): Add special code for Haiku. + 2023-04-05 Bruno Haible uchar: Work around Haiku bug. 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 +# 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