In 2022, Haiku got support for per-thread locales (POSIX functions uselocale, newlocale, duplocale, freelocale).
Gnulib needs support for this in the 'localename' module (so that GNU gettext will work when a per-thread locale is installed). This patch does it. It is pretty ugly, though. 2023-04-05 Bruno Haible <br...@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. 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