[haiku-commits] Change in haiku[master]: libs/posix: Implemented new locale functions

  • From: Gerrit <review@xxxxxxxxxxxxxxxxxxx>
  • To: waddlesplash <waddlesplash@xxxxxxxxx>, haiku-commits@xxxxxxxxxxxxx
  • Date: Wed, 1 Jun 2022 02:28:03 +0000

From Trung Nguyen <trungnt282910@xxxxxxxxx>:

Trung Nguyen has uploaded this change for review. ( 
https://review.haiku-os.org/c/haiku/+/5351 ;)


Change subject: libs/posix: Implemented new locale functions
......................................................................

libs/posix: Implemented new locale functions

Implemented the missing POSIX functions in <locale.h>:
newlocale, duplocale, uselocale, and freelocale, and also
provided missing type definitions for <locale.h>.

Modified LocaleBackend so that it could support thread-local
locales.

Some glibc-like locale-related variables supporting
ctype and printf family of functions have also been updated
to reflect the thread-local variables present in the latest
glibc sources.

As there have been some modifications to global symbols
from libroot, libroot_stubs.c has also been regenerated.

Change-Id: Ibf296c58c47d42d1d1dfb2ce64042442f2679431
---
M headers/posix/ctype.h
M headers/posix/locale.h
M headers/private/libroot/locale/LocaleBackend.h
M src/system/libroot/add-ons/icu/ICULocaleBackend.cpp
M src/system/libroot/add-ons/icu/ICUNumericData.cpp
M src/system/libroot/add-ons/icu/ICUTimeConversion.cpp
M src/system/libroot/posix/glibc/ctype/ctype.h
M src/system/libroot/posix/glibc/locale/Jamfile
A src/system/libroot/posix/glibc/locale/global-locale.c
M src/system/libroot/posix/glibc/locale/lc-ctype.c
M src/system/libroot/posix/glibc/locale/localeinfo.h
M src/system/libroot/posix/locale/Jamfile
M src/system/libroot/posix/locale/LocaleBackend.cpp
M src/system/libroot/posix/locale/LocaleDataBridge.cpp
A src/system/libroot/posix/locale/LocaleInternal.cpp
A src/system/libroot/posix/locale/LocaleInternal.h
M src/system/libroot/posix/locale/ctype.cpp
A src/system/libroot/posix/locale/ctype_loc.cpp
A src/system/libroot/posix/locale/ctype_loc_thread.cpp
A src/system/libroot/posix/locale/duplocale.cpp
A src/system/libroot/posix/locale/freelocale.cpp
M src/system/libroot/posix/locale/localeconv.cpp
A src/system/libroot/posix/locale/newlocale.cpp
M src/system/libroot/posix/locale/nl_langinfo.cpp
M src/system/libroot/posix/locale/setlocale.cpp
A src/system/libroot/posix/locale/uselocale.cpp
M src/system/libroot/posix/locale/wctype.cpp
M src/system/libroot/posix/string/strcoll.cpp
M src/system/libroot/posix/string/strxfrm.cpp
M src/system/libroot/posix/time/localtime.cpp
M src/system/libroot/posix/time/timelocal.cpp
M src/system/libroot/posix/wchar/mbrtowc.cpp
M src/system/libroot/posix/wchar/mbsrtowcs.cpp
M src/system/libroot/posix/wchar/wcrtomb.cpp
M src/system/libroot/posix/wchar/wcscoll.cpp
M src/system/libroot/posix/wchar/wcsrtombs.cpp
M src/system/libroot/posix/wchar/wcsxfrm.cpp
M src/system/libroot/stubbed/libroot_stubs.c
M src/system/runtime_loader/Jamfile
39 files changed, 1,063 insertions(+), 586 deletions(-)



  git pull ssh://git.haiku-os.org:22/haiku refs/changes/51/5351/1

diff --git a/headers/posix/ctype.h b/headers/posix/ctype.h
index 57b2820..95d904f 100644
--- a/headers/posix/ctype.h
+++ b/headers/posix/ctype.h
@@ -48,14 +48,28 @@
 extern const int *__ctype_tolower;
 extern const int *__ctype_toupper;

+// The OS won't boot if __ctype_* is accessed indirectly.
+#if !defined(_BOOT_MODE) && !defined(_KERNEL_MODE)
+extern const unsigned short int **__ctype_b_loc();
+extern const int **__ctype_tolower_loc();
+extern const int **__ctype_toupper_loc();
+
+#define __isctype(c, type) \
+       ((*__ctype_b_loc())[(int)(c)] & (unsigned short int)type)
+
+#define tolower(c) ((int)(*__ctype_tolower_loc())[(int)(c)])
+#define toupper(c) ((int)(*__ctype_toupper_loc())[(int)(c)])
+#else
 #define __isctype(c, type) \
        (__ctype_b[(int)(c)] & (unsigned short int)type)

+#define tolower(c) ((int)__ctype_tolower[(int)(c)])
+#define toupper(c) ((int)__ctype_toupper[(int)(c)])
+#endif // !defined(_BOOT_MODE) && !defined(_KERNEL_MODE)
+
 #define isascii(c) (((c) & ~0x7f) == 0)        /* ASCII characters have bit 8 
cleared */
 #define toascii(c) ((c) & 0x7f)                        /* Clear higher bits */

-#define tolower(c) ((int)__ctype_tolower[(int)(c)])
-#define toupper(c) ((int)__ctype_toupper[(int)(c)])
 #define _tolower(c)    tolower(c)
 #define _toupper(c)    toupper(c)

diff --git a/headers/posix/locale.h b/headers/posix/locale.h
index 2cc8717..bc38f45 100644
--- a/headers/posix/locale.h
+++ b/headers/posix/locale.h
@@ -48,6 +48,25 @@
  */
 #define        LC_LAST         LC_MESSAGES

+#define LC_COLLATE_MASK                (1 << (LC_COLLATE - 1))
+#define LC_CTYPE_MASK          (1 << (LC_CTYPE - 1))
+#define LC_MONETARY_MASK       (1 << (LC_MONETARY - 1))
+#define LC_NUMERIC_MASK        (1 << (LC_NUMERIC - 1))
+#define LC_TIME_MASK           (1 << (LC_TIME - 1))
+#define LC_MESSAGES_MASK       (1 << (LC_MESSAGES - 1))
+
+#define LC_ALL_MASK                    (LC_COLLATE_MASK | LC_CTYPE_MASK | \
+                                                       LC_MONETARY_MASK | 
LC_NUMERIC_MASK | \
+                                                       LC_TIME_MASK | 
LC_MESSAGES_MASK)
+
+typedef struct __locale_t {
+       int magic;
+       void* backend;
+       void* databridge;
+} *locale_t;
+
+#define LC_GLOBAL_LOCALE ((locale_t)-1)
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -55,6 +74,11 @@
 extern struct lconv *localeconv(void);
 extern char *setlocale(int category, const char *locale);

+extern locale_t duplocale(locale_t);
+extern void freelocale(locale_t);
+extern locale_t newlocale(int, const char *, locale_t);
+extern locale_t uselocale(locale_t);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/headers/private/libroot/locale/LocaleBackend.h 
b/headers/private/libroot/locale/LocaleBackend.h
index 38798b3..e4077af 100644
--- a/headers/private/libroot/locale/LocaleBackend.h
+++ b/headers/private/libroot/locale/LocaleBackend.h
@@ -8,11 +8,11 @@

 #include <SupportDefs.h>

+#include <locale.h>
 #include <time.h>
 #include <wctype.h>


-struct lconv;
 struct lc_time_t;
 struct locale_data;            // glibc

@@ -22,29 +22,33 @@


 struct LocaleCtypeDataBridge {
-       const unsigned short**  addrOfClassInfoTable;
-       const int**                             addrOfToLowerTable;
-       const int**                             addrOfToUpperTable;
+       const unsigned short**          addrOfClassInfoTable;
+       const int**                                     addrOfToLowerTable;
+       const int**                                     addrOfToUpperTable;

-       const unsigned short*   posixClassInfo;
-       const int*                              posixToLowerMap;
-       const int*                              posixToUpperMap;
+       const unsigned short* const     posixClassInfo;
+       const int* const                        posixToLowerMap;
+       const int* const                        posixToUpperMap;

-       LocaleCtypeDataBridge();
+       bool                                            isGlobal;
+
+       LocaleCtypeDataBridge(bool isGlobal);
+       ~LocaleCtypeDataBridge();

        void setMbCurMax(unsigned short mbCurMax);
+       void ApplyToCurrentThread();
 };


 struct LocaleMessagesDataBridge {
-       const char** posixLanginfo;
+       const char** const      posixLanginfo;

        LocaleMessagesDataBridge();
 };


 struct LocaleMonetaryDataBridge {
-       const struct lconv* posixLocaleConv;
+       const struct lconv* const posixLocaleConv;

        LocaleMonetaryDataBridge();
 };
@@ -73,16 +77,19 @@
        locale_data* originalGlibcLocale;

 public:
-       const struct lconv* posixLocaleConv;
-       GlibcNumericLocale  glibcNumericLocale;
+       const struct lconv* const       posixLocaleConv;
+       GlibcNumericLocale*             glibcNumericLocale;
+       bool                                            isGlobal;

-       LocaleNumericDataBridge();
+       LocaleNumericDataBridge(bool isGlobal);
        ~LocaleNumericDataBridge();
+
+       void ApplyToCurrentThread();
 };


 struct LocaleTimeDataBridge {
-       const struct lc_time_t* posixLCTimeInfo;
+       const struct lc_time_t* const posixLCTimeInfo;

        LocaleTimeDataBridge();
 };
@@ -92,8 +99,10 @@
        int*                                    addrOfDaylight;
        long*                                   addrOfTimezone;
        char**                                  addrOfTZName;
+       bool                                    isGlobal;

-       TimeConversionDataBridge();
+       TimeConversionDataBridge(bool isGlobal);
+       ~TimeConversionDataBridge();
 };


@@ -104,9 +113,12 @@
        LocaleNumericDataBridge         numericDataBridge;
        LocaleTimeDataBridge            timeDataBridge;
        TimeConversionDataBridge        timeConversionDataBridge;
-       const char**                            posixLanginfo;
+       const char** const                      posixLanginfo;
+       bool                                            isGlobal;

-       LocaleDataBridge();
+       LocaleDataBridge(bool isGlobal);
+
+       void ApplyToCurrentThread();
 };


@@ -162,14 +174,25 @@
        virtual void                            Initialize(LocaleDataBridge* 
dataBridge) = 0;

        static  status_t                        LoadBackend();
+       static  LocaleBackend*          CreateBackend();
+       static  void                            DestroyBackend(LocaleBackend* 
instance);
 };


-extern LocaleBackend* gLocaleBackend;
-
+extern thread_local locale_t gLocaleInfo;
+extern LocaleBackend* gGlobalLocaleBackend;
+extern LocaleDataBridge gGlobalLocaleDataBridge;

 }      // namespace Libroot
 }      // namespace BPrivate


+#define GET_LOCALE_BACKEND()                                                   
        \
+       ((BPrivate::Libroot::gLocaleInfo == NULL) ?                     \
+       BPrivate::Libroot::gGlobalLocaleBackend :                               
\
+       ((BPrivate::Libroot::gLocaleInfo->backend == NULL) ?    \
+       BPrivate::Libroot::gGlobalLocaleBackend :                               
\
+       
(BPrivate::Libroot::LocaleBackend*)BPrivate::Libroot::gLocaleInfo->backend))
+
+
 #endif // _LOCALE_BACKEND_H
diff --git a/src/system/libroot/add-ons/icu/ICULocaleBackend.cpp 
b/src/system/libroot/add-ons/icu/ICULocaleBackend.cpp
index 5dccc60..4d9a1e8 100644
--- a/src/system/libroot/add-ons/icu/ICULocaleBackend.cpp
+++ b/src/system/libroot/add-ons/icu/ICULocaleBackend.cpp
@@ -29,6 +29,12 @@
        return new(std::nothrow) ICULocaleBackend();
 }

+extern "C" void
+DestroyInstance(LocaleBackend* instance)
+{
+       delete instance;
+}
+

 ICULocaleBackend::ICULocaleBackend()
        :
diff --git a/src/system/libroot/add-ons/icu/ICUNumericData.cpp 
b/src/system/libroot/add-ons/icu/ICUNumericData.cpp
index cdde2de..733867a 100644
--- a/src/system/libroot/add-ons/icu/ICUNumericData.cpp
+++ b/src/system/libroot/add-ons/icu/ICUNumericData.cpp
@@ -34,9 +34,9 @@
 void
 ICUNumericData::Initialize(LocaleNumericDataBridge* dataBridge)
 {
-       dataBridge->glibcNumericLocale.values[0].string = fDecimalPoint;
-       dataBridge->glibcNumericLocale.values[1].string = fThousandsSep;
-       dataBridge->glibcNumericLocale.values[2].string = fGrouping;
+       dataBridge->glibcNumericLocale->values[0].string = fDecimalPoint;
+       dataBridge->glibcNumericLocale->values[1].string = fThousandsSep;
+       dataBridge->glibcNumericLocale->values[2].string = fGrouping;
        fDataBridge = dataBridge;
 }

@@ -62,13 +62,13 @@
                if (result == B_OK) {
                        result = _SetLocaleconvEntry(formatSymbols, 
fDecimalPoint,
                                DecimalFormatSymbols::kDecimalSeparatorSymbol);
-                       fDataBridge->glibcNumericLocale.values[3].word
+                       fDataBridge->glibcNumericLocale->values[3].word
                                = (unsigned int)fDecimalPoint[0];
                }
                if (result == B_OK) {
                        result = _SetLocaleconvEntry(formatSymbols, 
fThousandsSep,
                                DecimalFormatSymbols::kGroupingSeparatorSymbol);
-                       fDataBridge->glibcNumericLocale.values[4].word
+                       fDataBridge->glibcNumericLocale->values[4].word
                                = (unsigned int)fThousandsSep[0];
                }
                if (result == B_OK) {
@@ -104,9 +104,9 @@
                strcpy(fDecimalPoint, 
fDataBridge->posixLocaleConv->decimal_point);
                strcpy(fThousandsSep, 
fDataBridge->posixLocaleConv->thousands_sep);
                strcpy(fGrouping, fDataBridge->posixLocaleConv->grouping);
-               fDataBridge->glibcNumericLocale.values[3].word
+               fDataBridge->glibcNumericLocale->values[3].word
                        = (unsigned int)fDecimalPoint[0];
-               fDataBridge->glibcNumericLocale.values[4].word
+               fDataBridge->glibcNumericLocale->values[4].word
                        = (unsigned int)fThousandsSep[0];
        }

diff --git a/src/system/libroot/add-ons/icu/ICUTimeConversion.cpp 
b/src/system/libroot/add-ons/icu/ICUTimeConversion.cpp
index 5951b6c..6d45b71 100644
--- a/src/system/libroot/add-ons/icu/ICUTimeConversion.cpp
+++ b/src/system/libroot/add-ons/icu/ICUTimeConversion.cpp
@@ -47,6 +47,7 @@
 ICUTimeConversion::TZSet(const char* timeZoneID, const char* tz)
 {
        bool offsetHasBeenSet = false;
+       bool timeZoneIdMatches = false;

        // The given TZ environment variable's content overrides the default
        // system timezone.
@@ -55,8 +56,10 @@
                // value is implementation specific, we expect a full timezone 
ID.
                if (*tz == ':') {
                        // nothing to do if the given name matches the current 
timezone
-                       if (strcasecmp(fTimeZoneID, tz + 1) == 0)
-                               return B_OK;
+                       if (strcasecmp(fTimeZoneID, tz + 1) == 0) {
+                               timeZoneIdMatches = true;
+                               goto done;
+                       }

                        strlcpy(fTimeZoneID, tz + 1, sizeof(fTimeZoneID));
                } else {
@@ -64,8 +67,10 @@
                        strlcpy(fTimeZoneID, tz, sizeof(fTimeZoneID));

                        // nothing to do if the given name matches the current 
timezone
-                       if (strcasecmp(fTimeZoneID, 
fDataBridge->addrOfTZName[0]) == 0)
-                               return B_OK;
+                       if (strcasecmp(fTimeZoneID, 
fDataBridge->addrOfTZName[0]) == 0) {
+                               timeZoneIdMatches = true;
+                               goto done;
+                       }

                        // parse TZ variable (only <std> and <offset> supported)
                        const char* tzNameEnd = tz;
@@ -88,12 +93,22 @@
                }
        } else {
                // nothing to do if the given name matches the current timezone
-               if (strcasecmp(fTimeZoneID, timeZoneID) == 0)
-                       return B_OK;
+               if (strcasecmp(fTimeZoneID, timeZoneID) == 0) {
+                       timeZoneIdMatches = true;
+                       goto done;
+               }

                strlcpy(fTimeZoneID, timeZoneID, sizeof(fTimeZoneID));
        }

+done:
+       // fTimeZone can still be NULL if we don't initialize it
+       // in the first TZSet, causing problems for future
+       // Localtime invocations.
+       if (fTimeZone != NULL && timeZoneIdMatches) {
+               return B_OK;
+       }
+
        delete fTimeZone;
        fTimeZone = TimeZone::createTimeZone(fTimeZoneID);
        if (fTimeZone == NULL)
diff --git a/src/system/libroot/posix/glibc/ctype/ctype.h 
b/src/system/libroot/posix/glibc/ctype/ctype.h
index adffe76..af64a50 100644
--- a/src/system/libroot/posix/glibc/ctype/ctype.h
+++ b/src/system/libroot/posix/glibc/ctype/ctype.h
@@ -64,6 +64,11 @@
 /* These are defined in ctype-info.c.
    The declarations here must match those in localeinfo.h.

+   In the thread-specific locale model (see `uselocale' in <locale.h>)
+   we cannot use global variables for these as was done in the past.
+   Instead, the following accessor functions return the address of
+   each variable, which is local to the current thread if multithreaded.
+
    These point into arrays of 384, so they can be indexed by any `unsigned
    char' value [0,255]; by EOF (-1); or by any `signed char' value
    [-128,-1).  ISO C requires that the ctype functions work for `unsigned
@@ -72,12 +77,12 @@
    rather than `unsigned char's because tolower (EOF) must be EOF, which
    doesn't fit into an `unsigned char'.  But today more important is that
    the arrays are also used for multi-byte character sets.  */
-extern __const unsigned short int *__ctype_b;  /* Characteristics.  */
-extern __const __int32_t *__ctype_tolower; /* Case conversions.  */
-extern __const __int32_t *__ctype_toupper; /* Case conversions.  */
+extern __const unsigned short int **__ctype_b_loc (void); /* Characteristics. 
*/
+extern __const __int32_t **__ctype_tolower_loc (void);    /* Case conversions. 
*/
+extern __const __int32_t **__ctype_toupper_loc (void);    /* Case conversions. 
*/

 #define        __isctype(c, type) \
-  (__ctype_b[(int) (c)] & (unsigned short int) type)
+  ((*__ctype_b_loc())[(int) (c)] & (unsigned short int) type)

 #define        __isascii(c)    (((c) & ~0x7f) == 0)    /* If C is a 7 bit 
value.  */
 #define        __toascii(c)    ((c) & 0x7f)            /* Mask off high bits.  
*/
@@ -167,27 +172,27 @@
 __extern_inline int
 tolower (int __c) __THROW
 {
-  return __c >= -128 && __c < 256 ? __ctype_tolower[__c] : __c;
+  return __c >= -128 && __c < 256 ? (*__ctype_tolower_loc())[__c] : __c;
 }

 __extern_inline int
 toupper (int __c) __THROW
 {
-  return __c >= -128 && __c < 256 ? __ctype_toupper[__c] : __c;
+  return __c >= -128 && __c < 256 ? (*__ctype_toupper_loc())[__c] : __c;
 }
 # endif

 # if __GNUC__ >= 2 && defined __OPTIMIZE__ && !defined __cplusplus
-#  define tolower(c) __tobody (c, tolower, __ctype_tolower, (c))
-#  define toupper(c) __tobody (c, toupper, __ctype_toupper, (c))
+#  define tolower(c) __tobody (c, tolower, (*__ctype_tolower_loc()), (c))
+#  define toupper(c) __tobody (c, toupper, (*__ctype_toupper_loc()), (c))
 # endif        /* Optimizing gcc */

 # if defined __USE_SVID || defined __USE_MISC || defined __USE_XOPEN
 #  define isascii(c)   __isascii (c)
 #  define toascii(c)   __toascii (c)

-#  define _tolower(c)  ((int) __ctype_tolower[(int) (c)])
-#  define _toupper(c)  ((int) __ctype_toupper[(int) (c)])
+#  define _tolower(c)  ((int) (*__ctype_tolower_loc())[(int) (c)])
+#  define _toupper(c)  ((int) (*__ctype_toupper_loc())[(int) (c)])
 # endif

 #endif /* Not __NO_CTYPE.  */
diff --git a/src/system/libroot/posix/glibc/locale/Jamfile 
b/src/system/libroot/posix/glibc/locale/Jamfile
index b3ba468..de7d9c4 100644
--- a/src/system/libroot/posix/glibc/locale/Jamfile
+++ b/src/system/libroot/posix/glibc/locale/Jamfile
@@ -24,6 +24,7 @@
                        C-time.c
                        C_name.c
                        coll-lookup.c
+                       global-locale.c
                        lc-collate.c
                        lc-ctype.c
                        lc-messages.c
diff --git a/src/system/libroot/posix/glibc/locale/global-locale.c 
b/src/system/libroot/posix/glibc/locale/global-locale.c
new file mode 100644
index 0000000..fa93468
--- /dev/null
+++ b/src/system/libroot/posix/glibc/locale/global-locale.c
@@ -0,0 +1,48 @@
+/* Locale object representing the global locale controlled by setlocale.
+   Copyright (C) 2002-2019 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <locale.h>
+#include "localeinfo.h"
+
+#define DEFINE_CATEGORY(category, category_name, items, a) \
+extern struct locale_data _nl_C_##category;
+#include "categories.def"
+#undef        DEFINE_CATEGORY
+
+/* Defined in locale/C-ctype.c.  */
+extern const char _nl_C_LC_CTYPE_class[];
+extern const char _nl_C_LC_CTYPE_toupper[];
+extern const char _nl_C_LC_CTYPE_tolower[];
+
+/* Here we define the locale object maintained by setlocale.
+   The references in the initializer are weak, so the parts of
+   the structure that are never referred to will be zero.  */
+
+struct __locale_struct _nl_global_locale =
+  {
+    .__locales =
+    {
+#define DEFINE_CATEGORY(category, category_name, items, a) \
+      [category] = &_nl_C_##category,
+#include "categories.def"
+#undef        DEFINE_CATEGORY
+    },
+    .__ctype_b = (const unsigned short int *) _nl_C_LC_CTYPE_class + 128,
+    .__ctype_tolower = (const int *) _nl_C_LC_CTYPE_tolower + 128,
+    .__ctype_toupper = (const int *) _nl_C_LC_CTYPE_toupper + 128
+  };
diff --git a/src/system/libroot/posix/glibc/locale/lc-ctype.c 
b/src/system/libroot/posix/glibc/locale/lc-ctype.c
index 742dae4..99c0d8e 100644
--- a/src/system/libroot/posix/glibc/locale/lc-ctype.c
+++ b/src/system/libroot/posix/glibc/locale/lc-ctype.c
@@ -47,9 +47,9 @@

   offset = _NL_CURRENT_WORD (LC_CTYPE, _NL_CTYPE_CLASS_OFFSET);
   for (cnt = 0; cnt < 12; cnt++)
-    __ctype32_wctype[cnt] = _nl_current_LC_CTYPE->values[offset + cnt].string;
+    __ctype32_wctype[cnt] = (*_nl_current_LC_CTYPE)->values[offset + 
cnt].string;

   offset = _NL_CURRENT_WORD (LC_CTYPE, _NL_CTYPE_MAP_OFFSET);
   for (cnt = 0; cnt < 2; cnt++)
-    __ctype32_wctrans[cnt] = _nl_current_LC_CTYPE->values[offset + cnt].string;
+    __ctype32_wctrans[cnt] = (*_nl_current_LC_CTYPE)->values[offset + 
cnt].string;
 }
diff --git a/src/system/libroot/posix/glibc/locale/localeinfo.h 
b/src/system/libroot/posix/glibc/locale/localeinfo.h
index 814a273..0a89f90 100644
--- a/src/system/libroot/posix/glibc/locale/localeinfo.h
+++ b/src/system/libroot/posix/glibc/locale/localeinfo.h
@@ -27,6 +27,11 @@
 #include <stdint.h>
 #include <sys/types.h>

+// __locale_struct
+#include "xlocale.h"
+// LC_* values
+#include "locale.h"
+
 /* This has to be changed whenever a new locale is defined.  */
 #define __LC_LAST      7

@@ -143,7 +148,7 @@

 /* For each category declare the variable for the current locale data.  */
 #define DEFINE_CATEGORY(category, category_name, items, a) \
-extern struct locale_data *_nl_current_##category;
+extern __thread struct locale_data *const *_nl_current_##category;
 #include "categories.def"
 #undef DEFINE_CATEGORY

@@ -158,22 +163,27 @@
 /* The standard codeset.  */
 extern const char _nl_C_codeset[];

+/* This is the internal locale_t object that holds the global locale
+   controlled by calls to setlocale.  A thread's TSD locale pointer
+   points to this when `uselocale (LC_GLOBAL_LOCALE)' is in effect.  */
+extern struct __locale_struct _nl_global_locale;
+
 /* Extract the current CATEGORY locale's string for ITEM.  */
 #define _NL_CURRENT(category, item) \
-  (_nl_current_##category->values[_NL_ITEM_INDEX (item)].string)
+  ((*_nl_current_##category)->values[_NL_ITEM_INDEX (item)].string)

 /* Extract the current CATEGORY locale's string for ITEM.  */
 #define _NL_CURRENT_WSTR(category, item) \
-  ((wchar_t *) (_nl_current_##category->values[_NL_ITEM_INDEX (item)].wstr))
+  ((wchar_t *) ((*_nl_current_##category)->values[_NL_ITEM_INDEX (item)].wstr))

 /* Extract the current CATEGORY locale's word for ITEM.  */
 #define _NL_CURRENT_WORD(category, item) \
-  (_nl_current_##category->values[_NL_ITEM_INDEX (item)].word)
+  ((*_nl_current_##category)->values[_NL_ITEM_INDEX (item)].word)

 /* This is used in lc-CATEGORY.c to define _nl_current_CATEGORY.  */
 #define _NL_CURRENT_DEFINE(category) \
-  extern struct locale_data _nl_C_##category; \
-  struct locale_data *_nl_current_##category = &_nl_C_##category
+  __thread struct locale_data *const *_nl_current_##category \
+    = &_nl_global_locale.__locales[category];

 /* Load the locale data for CATEGORY from the file specified by *NAME.
    If *NAME is "", use environment variables as specified by POSIX,
diff --git a/src/system/libroot/posix/locale/Jamfile 
b/src/system/libroot/posix/locale/Jamfile
index d2f9aef..aff1b11 100644
--- a/src/system/libroot/posix/locale/Jamfile
+++ b/src/system/libroot/posix/locale/Jamfile
@@ -12,14 +12,24 @@
                local architecture = $(TARGET_PACKAGING_ARCH) ;

                MergeObject <$(architecture)>posix_locale.o :
+                       ctype_loc_thread.cpp
                        ctype.cpp
+                       duplocale.cpp
+                       freelocale.cpp
                        LocaleBackend.cpp
                        LocaleData.cpp
                        LocaleDataBridge.cpp
+                       LocaleInternal.cpp
                        localeconv.cpp
+                       newlocale.cpp
                        nl_langinfo.cpp
                        setlocale.cpp
+                       uselocale.cpp
                        wctype.cpp
                        ;
+
+               MergeObject <$(architecture)>ctype_loc.o :
+                       ctype_loc.cpp
+                       ;
        }
 }
diff --git a/src/system/libroot/posix/locale/LocaleBackend.cpp 
b/src/system/libroot/posix/locale/LocaleBackend.cpp
index dfd1be5..154711e 100644
--- a/src/system/libroot/posix/locale/LocaleBackend.cpp
+++ b/src/system/libroot/posix/locale/LocaleBackend.cpp
@@ -15,32 +15,50 @@
 namespace Libroot {


-LocaleBackend* gLocaleBackend = NULL;
+thread_local locale_t gLocaleInfo = NULL;
+LocaleBackend* gGlobalLocaleBackend = NULL;
+LocaleDataBridge gGlobalLocaleDataBridge = LocaleDataBridge(true);


-static LocaleDataBridge sLocaleDataBridge;
+static void* sImageHandle = NULL;
+typedef LocaleBackend* (*create_instance_t)();
+typedef void (*destroy_instance_t)(LocaleBackend*);
+static create_instance_t sCreateInstanceFunc = NULL;
+static destroy_instance_t sDestroyInstanceFunc = NULL;
+
+
 static pthread_once_t sBackendInitOnce = PTHREAD_ONCE_INIT;
+static pthread_once_t sFunctionsInitOnce = PTHREAD_ONCE_INIT;
+
+
+static void
+LoadFunctions()
+{
+       sImageHandle = dlopen("libroot-addon-icu.so", RTLD_LAZY);
+       if (sImageHandle == NULL)
+               return;
+
+       sCreateInstanceFunc = (create_instance_t)dlsym(sImageHandle, 
"CreateInstance");
+       sDestroyInstanceFunc = (destroy_instance_t)dlsym(sImageHandle, 
"DestroyInstance");
+
+       if ((sCreateInstanceFunc == NULL) || (sDestroyInstanceFunc == NULL)) {
+               dlclose(sImageHandle);
+               return;
+       }
+}


 static void
 LoadBackend()
 {
-       void* imageHandle = dlopen("libroot-addon-icu.so", RTLD_LAZY);
-       if (imageHandle == NULL)
-               return;
-
-       typedef LocaleBackend* (*symbolType)();
-       symbolType createInstanceFunc
-               = (symbolType)dlsym(imageHandle, "CreateInstance");
-       if (createInstanceFunc == NULL) {
-               dlclose(imageHandle);
-               return;
+       gGlobalLocaleBackend = LocaleBackend::CreateBackend();
+       if (gGlobalLocaleBackend != NULL) {
+               gGlobalLocaleBackend->Initialize(&gGlobalLocaleDataBridge);
        }
-
-       gLocaleBackend = createInstanceFunc();
 }


+
 LocaleBackend::LocaleBackend()
 {
 }
@@ -54,15 +72,35 @@
 status_t
 LocaleBackend::LoadBackend()
 {
-       if (gLocaleBackend == NULL) {
+       if (gGlobalLocaleBackend == NULL) {
                pthread_once(&sBackendInitOnce, 
&BPrivate::Libroot::LoadBackend);
-               if (gLocaleBackend != NULL)
-                       gLocaleBackend->Initialize(&sLocaleDataBridge);
        }

-       return gLocaleBackend != NULL ? B_OK : B_ERROR;
+       return gGlobalLocaleBackend != NULL ? B_OK : B_ERROR;
 }

+LocaleBackend*
+LocaleBackend::CreateBackend()
+{
+       if (sCreateInstanceFunc == NULL) {
+               pthread_once(&sFunctionsInitOnce, 
&BPrivate::Libroot::LoadFunctions);
+       }
+
+       if (sCreateInstanceFunc != NULL) {
+               LocaleBackend* backend = sCreateInstanceFunc();
+               return backend;
+       }
+
+       return NULL;
+}
+
+void
+LocaleBackend::DestroyBackend(LocaleBackend* instance)
+{
+       if (sDestroyInstanceFunc != NULL) {
+               sDestroyInstanceFunc(instance);
+       }
+}

 }      // namespace Libroot
 }      // namespace BPrivate
diff --git a/src/system/libroot/posix/locale/LocaleDataBridge.cpp 
b/src/system/libroot/posix/locale/LocaleDataBridge.cpp
index c8f2631..eaf84fa 100644
--- a/src/system/libroot/posix/locale/LocaleDataBridge.cpp
+++ b/src/system/libroot/posix/locale/LocaleDataBridge.cpp
@@ -17,30 +17,71 @@
 #include <PosixLocaleConv.h>


-extern locale_data* _nl_current_LC_NUMERIC;
+extern const unsigned short* __ctype_b;
+extern const int* __ctype_tolower;
+extern const int* __ctype_toupper;
+
+
+extern thread_local locale_data* const* _nl_current_LC_NUMERIC;
+struct __locale_struct
+{
+       locale_data *__locales[7];
+
+       const unsigned short int *__ctype_b;
+       const int *__ctype_tolower;
+       const int *__ctype_toupper;
+}; // struct from glibc xlocale.h
+extern struct __locale_struct _nl_global_locale;
+const int __LC_NUMERIC = 1; // constant from bits/locale.h
+// Convenience macro
+#define _NL_GLOBAL_LC_NUMERIC (_nl_global_locale.__locales[__LC_NUMERIC])
+


 namespace BPrivate {
 namespace Libroot {


-LocaleCtypeDataBridge::LocaleCtypeDataBridge()
+LocaleCtypeDataBridge::LocaleCtypeDataBridge(bool isGlobal)
        :
-       addrOfClassInfoTable(&__ctype_b),
-       addrOfToLowerTable(&__ctype_tolower),
-       addrOfToUpperTable(&__ctype_toupper),
        posixClassInfo(gPosixClassInfo),
        posixToLowerMap(gPosixToLowerMap),
-       posixToUpperMap(gPosixToUpperMap)
+       posixToUpperMap(gPosixToUpperMap),
+       isGlobal(isGlobal)
 {
+       if (isGlobal) {
+               addrOfClassInfoTable = &__ctype_b;
+               addrOfToLowerTable = &__ctype_tolower;
+               addrOfToUpperTable = &__ctype_toupper;
+       } else {
+               addrOfClassInfoTable = new const unsigned short*(__ctype_b);
+               addrOfToLowerTable = new const int*(__ctype_tolower);
+               addrOfToUpperTable = new const int*(__ctype_toupper);
+       }
 }

+LocaleCtypeDataBridge::~LocaleCtypeDataBridge()
+{
+       if (!isGlobal) {
+               delete addrOfClassInfoTable;
+               delete addrOfToLowerTable;
+               delete addrOfToUpperTable;
+       }
+}

 void LocaleCtypeDataBridge::setMbCurMax(unsigned short mbCurMax)
 {
        __ctype_mb_cur_max = mbCurMax;
 }

+void
+LocaleCtypeDataBridge::ApplyToCurrentThread()
+{
+       *__ctype_b_loc() = *addrOfClassInfoTable;
+       *__ctype_tolower_loc() = *addrOfToLowerTable;
+       *__ctype_toupper_loc() = *addrOfToUpperTable;
+}
+

 LocaleMessagesDataBridge::LocaleMessagesDataBridge()
        :
@@ -56,20 +97,36 @@
 }


-LocaleNumericDataBridge::LocaleNumericDataBridge()
+LocaleNumericDataBridge::LocaleNumericDataBridge(bool isGlobal)
        :
-       originalGlibcLocale(_nl_current_LC_NUMERIC),
-       posixLocaleConv(&gPosixLocaleConv)
+       posixLocaleConv(&gPosixLocaleConv),
+       glibcNumericLocale(new GlibcNumericLocale)
 {
-       memcpy(&glibcNumericLocale, _nl_current_LC_NUMERIC,
-               sizeof(glibcNumericLocale));
-       _nl_current_LC_NUMERIC = (locale_data*)&glibcNumericLocale;
-}

+       memcpy(glibcNumericLocale, _NL_GLOBAL_LC_NUMERIC,
+               sizeof(GlibcNumericLocale));
+
+       if (isGlobal) {
+               originalGlibcLocale = _NL_GLOBAL_LC_NUMERIC;
+               _NL_GLOBAL_LC_NUMERIC = (locale_data*)glibcNumericLocale;
+       }
+}

 LocaleNumericDataBridge::~LocaleNumericDataBridge()
 {
-       _nl_current_LC_NUMERIC = originalGlibcLocale;
+       if (isGlobal) {
+               _NL_GLOBAL_LC_NUMERIC = originalGlibcLocale;
+       } else if (_nl_current_LC_NUMERIC == 
(locale_data**)&glibcNumericLocale) {
+               _nl_current_LC_NUMERIC = &_NL_GLOBAL_LC_NUMERIC;
+       }
+
+       delete glibcNumericLocale;
+}
+
+void
+LocaleNumericDataBridge::ApplyToCurrentThread()
+{
+       _nl_current_LC_NUMERIC = (locale_data**)&glibcNumericLocale;
 }


@@ -80,21 +137,58 @@
 }


-TimeConversionDataBridge::TimeConversionDataBridge()
+TimeConversionDataBridge::TimeConversionDataBridge(bool isGlobal)
        :
-       addrOfDaylight(&daylight),
-       addrOfTimezone(&timezone),
-       addrOfTZName(tzname)
+       isGlobal(isGlobal)
 {
+       if (isGlobal) {
+               addrOfDaylight = &daylight;
+               addrOfTimezone = &timezone;
+               addrOfTZName = tzname;
+       } else {
+               addrOfDaylight = new int(daylight);
+               addrOfTimezone = new long(timezone);
+               addrOfTZName = new char*[2] { new char[64], new char[64] };
+               strlcpy(addrOfTZName[0], tzname[0], 64);
+               strlcpy(addrOfTZName[1], tzname[1], 64);
+       }
+}
+
+TimeConversionDataBridge::~TimeConversionDataBridge()
+{
+       if (!isGlobal) {
+               delete addrOfDaylight;
+               delete addrOfTimezone;
+               delete [] addrOfTZName[0];
+               delete [] addrOfTZName[1];
+               delete [] addrOfTZName;
+       }
 }


-LocaleDataBridge::LocaleDataBridge()
+LocaleDataBridge::LocaleDataBridge(bool isGlobal)
        :
-       posixLanginfo(gPosixLanginfo)
+       ctypeDataBridge(isGlobal),
+       numericDataBridge(isGlobal),
+       timeConversionDataBridge(isGlobal),
+       posixLanginfo(gPosixLanginfo),
+       isGlobal(isGlobal)
 {
 }

+void
+LocaleDataBridge::ApplyToCurrentThread()
+{
+       ctypeDataBridge.ApplyToCurrentThread();
+       numericDataBridge.ApplyToCurrentThread();
+       // While timeConverstionDataBridge stores read-write variables,
+       // these variables are global (by POSIX definition). Furthermore,
+       // none of the backends seem to access these variables
+       // directly. The values are set in the bridge mostly for
+       // synchronization purposes. Therefore, don't call
+       // ApplyToCurrentThread for this object.
+}
+

 }      // namespace Libroot
 }      // namespace BPrivate
diff --git a/src/system/libroot/posix/locale/LocaleInternal.cpp 
b/src/system/libroot/posix/locale/LocaleInternal.cpp
new file mode 100644
index 0000000..9c88699
--- /dev/null
+++ b/src/system/libroot/posix/locale/LocaleInternal.cpp
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2004-2007, Axel Dörfler, axeld@xxxxxxxxxxxxxxxx
+ * Copyright 2010, Oliver Tappe, zooey@xxxxxxxxxxxxxxx
+ * All rights reserved. Distributed under the terms of the MIT License.
+ */
+
+
+#include "LocaleInternal.h"
+
+#include <locale.h>
+#include <stdlib.h>
+#include <strings.h>
+
+
+namespace BPrivate {
+namespace Libroot {
+
+
+status_t
+GetLocalesFromEnvironment(int category, const char** locales)
+{
+       const char* locale = getenv("LC_ALL");
+       if (locale && *locale)
+               locales[category] = locale;
+       else {
+               // the order of the names must match the one specified in 
locale.h
+               const char* categoryNames[] = {
+                       "LC_ALL",
+                       "LC_COLLATE",
+                       "LC_CTYPE",
+                       "LC_MONETARY",
+                       "LC_NUMERIC",
+                       "LC_TIME",
+                       "LC_MESSAGES"
+               };
+               int from, to;
+               if (category == LC_ALL) {
+                       // we need to check each real category if all of them 
should be set
+                       from = 1;
+                       to = LC_LAST;
+               } else
+                       from = to = category;
+               bool haveDifferentLocales = false;
+               locale = NULL;
+               for (int lc = from; lc <= to; lc++) {
+                       const char* lastLocale = locale;
+                       locale = getenv(categoryNames[lc]);
+                       if (!locale || *locale == '\0')
+                               locale = getenv("LANG");
+                       if (!locale || *locale == '\0')
+                               locale = "POSIX";
+                       locales[lc] = locale;
+                       if (lastLocale && strcasecmp(locale, lastLocale) != 0)
+                               haveDifferentLocales = true;
+               }
+               if (!haveDifferentLocales) {
+                       // we can set all locales at once
+                       locales[LC_ALL] = locale;
+               }
+       }
+
+       return B_OK;
+}
+
+}      // namespace Libroot
+}      // namespace BPrivate
diff --git a/src/system/libroot/posix/locale/LocaleInternal.h 
b/src/system/libroot/posix/locale/LocaleInternal.h
new file mode 100644
index 0000000..3041dea
--- /dev/null
+++ b/src/system/libroot/posix/locale/LocaleInternal.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2004-2007, Axel Dörfler, axeld@xxxxxxxxxxxxxxxx
+ * Copyright 2010, Oliver Tappe, zooey@xxxxxxxxxxxxxxx
+ * All rights reserved. Distributed under the terms of the MIT License.
+ */
+
+
+#include <SupportDefs.h>
+
+
+#define LOCALE_T_MAGIC 0x4C4F4341
+
+
+namespace BPrivate {
+namespace Libroot {
+
+
+status_t GetLocalesFromEnvironment(int category, const char** locales);
+
+}      // namespace Libroot
+}      // namespace BPrivate
diff --git a/src/system/libroot/posix/locale/ctype.cpp 
b/src/system/libroot/posix/locale/ctype.cpp
index e558a86..20b53de 100644
--- a/src/system/libroot/posix/locale/ctype.cpp
+++ b/src/system/libroot/posix/locale/ctype.cpp
@@ -26,6 +26,13 @@
 #undef toupper


+#if defined(_KERNEL_MODE)
+#define GET_CTYPE(name) (name)
+#else
+#define GET_CTYPE(name) (*name##_loc())
+#endif
+
+
 extern "C"
 {

@@ -44,7 +51,7 @@
 isalnum(int c)
 {
        if (c >= -128 && c < 256)
-               return __ctype_b[c] & (_ISupper | _ISlower | _ISdigit);
+               return GET_CTYPE(__ctype_b)[c] & (_ISupper | _ISlower | 
_ISdigit);

        return 0;
 }
@@ -54,7 +61,7 @@
 isalpha(int c)
 {
        if (c >= -128 && c < 256)
-               return __ctype_b[c] & (_ISupper | _ISlower);
+               return GET_CTYPE(__ctype_b)[c] & (_ISupper | _ISlower);

        return 0;
 }
@@ -72,7 +79,7 @@
 isblank(int c)
 {
        if (c >= -128 && c < 256)
-               return __ctype_b[c] & _ISblank;
+               return GET_CTYPE(__ctype_b)[c] & _ISblank;

        return 0;
 }
@@ -82,7 +89,7 @@
 iscntrl(int c)
 {
        if (c >= -128 && c < 256)
-               return __ctype_b[c] & _IScntrl;
+               return GET_CTYPE(__ctype_b)[c] & _IScntrl;

        return 0;
 }
@@ -92,7 +99,7 @@
 isdigit(int c)
 {
        if (c >= -128 && c < 256)
-               return __ctype_b[c] & _ISdigit;
+               return GET_CTYPE(__ctype_b)[c] & _ISdigit;

        return 0;
 }
@@ -102,7 +109,7 @@
 isgraph(int c)
 {
        if (c >= -128 && c < 256)
-               return __ctype_b[c] & _ISgraph;
+               return GET_CTYPE(__ctype_b)[c] & _ISgraph;

        return 0;
 }
@@ -112,7 +119,7 @@
 islower(int c)
 {
        if (c >= -128 && c < 256)
-               return __ctype_b[c] & _ISlower;
+               return GET_CTYPE(__ctype_b)[c] & _ISlower;

        return 0;
 }
@@ -122,7 +129,7 @@
 isprint(int c)
 {
        if (c >= -128 && c < 256)
-               return __ctype_b[c] & _ISprint;
+               return GET_CTYPE(__ctype_b)[c] & _ISprint;

        return 0;
 }
@@ -132,7 +139,7 @@
 ispunct(int c)
 {
        if (c >= -128 && c < 256)
-               return __ctype_b[c] & _ISpunct;
+               return GET_CTYPE(__ctype_b)[c] & _ISpunct;

        return 0;
 }
@@ -142,7 +149,7 @@
 isspace(int c)
 {
        if (c >= -128 && c < 256)
-               return __ctype_b[c] & _ISspace;
+               return GET_CTYPE(__ctype_b)[c] & _ISspace;

        return 0;
 }
@@ -152,7 +159,7 @@
 isupper(int c)
 {
        if (c >= -128 && c < 256)
-               return __ctype_b[c] & _ISupper;
+               return GET_CTYPE(__ctype_b)[c] & _ISupper;

        return 0;
 }
@@ -162,7 +169,7 @@
 isxdigit(int c)
 {
        if (c >= -128 && c < 256)
-               return __ctype_b[c] & _ISxdigit;
+               return GET_CTYPE(__ctype_b)[c] & _ISxdigit;

        return 0;
 }
@@ -180,7 +187,7 @@
 tolower(int c)
 {
        if (c >= -128 && c < 256)
-               return __ctype_tolower[c];
+               return GET_CTYPE(__ctype_tolower)[c];

        return c;
 }
@@ -190,7 +197,7 @@
 toupper(int c)
 {
        if (c >= -128 && c < 256)
-               return __ctype_toupper[c];
+               return GET_CTYPE(__ctype_toupper)[c];

        return c;
 }
diff --git a/src/system/libroot/posix/locale/ctype_loc.cpp 
b/src/system/libroot/posix/locale/ctype_loc.cpp
new file mode 100644
index 0000000..dabea33
--- /dev/null
+++ b/src/system/libroot/posix/locale/ctype_loc.cpp
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2022, Trung Nguyen, trungnt282910@xxxxxxxxx
+ * All rights reserved. Distributed under the terms of the MIT License.
+ */
+
+
+#ifndef _KERNEL_MODE
+#include <ctype.h>
+
+
+// These functions are intended for scenarios where we cannot
+// link to the whole libroot and access pthread functions;
+// for example, when we're in the static "libruntime_loader.a"
+
+extern "C" const unsigned short**
+__ctype_b_loc()
+{
+       return &__ctype_b;
+}
+
+extern "C" const int**
+__ctype_tolower_loc()
+{
+       return &__ctype_tolower;
+}
+
+extern "C" const int**
+__ctype_toupper_loc()
+{
+       return &__ctype_toupper;
+}
+
+
+#endif //_KERNEL_MODE
diff --git a/src/system/libroot/posix/locale/ctype_loc_thread.cpp 
b/src/system/libroot/posix/locale/ctype_loc_thread.cpp
new file mode 100644
index 0000000..2804444
--- /dev/null
+++ b/src/system/libroot/posix/locale/ctype_loc_thread.cpp
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2022, Trung Nguyen, trungnt282910@xxxxxxxxx
+ * All rights reserved. Distributed under the terms of the MIT License.
+ */
+
+
+#ifndef _KERNEL_MODE
+#include <ctype.h>
+#include <pthread.h>
+
+
+namespace BPrivate {
+namespace Libroot {
+
+
+struct ctype_info {
+       const unsigned short*   __ctype_b;
+       const int*                              __ctype_tolower;
+       const int*                              __ctype_toupper;
+};
+
+
+static pthread_key_t sCtypeInfoPthreadKey;
+static pthread_once_t sCtypeInfoPthreadKeyOnce = PTHREAD_ONCE_INIT;
+
+
+static void
+ctype_info_destroy(void* ptr)
+{
+       ctype_info* info = (ctype_info*)ptr;
+       delete info;
+}
+
+static void
+ctype_info_make_key()
+{
+       pthread_key_create(&sCtypeInfoPthreadKey, ctype_info_destroy);
+}
+
+static ctype_info*
+__ctype_info_get()
+{
+       ctype_info* ptr;
+       pthread_once(&sCtypeInfoPthreadKeyOnce, ctype_info_make_key);
+       if ((ptr = (ctype_info*)pthread_getspecific(sCtypeInfoPthreadKey)) == 
NULL) {
+               ptr = new ctype_info;
+               ptr->__ctype_b = __ctype_b;
+               ptr->__ctype_tolower = __ctype_tolower;
+               ptr->__ctype_toupper = __ctype_toupper;
+               pthread_setspecific(sCtypeInfoPthreadKey, ptr);
+       }
+       return ptr;
+}
+
+
+extern "C" const unsigned short**
+__ctype_b_loc()
+{
+       return &__ctype_info_get()->__ctype_b;
+}
+
+extern "C" const int**
+__ctype_tolower_loc()
+{
+       return &__ctype_info_get()->__ctype_tolower;
+}
+
+extern "C" const int**
+__ctype_toupper_loc()
+{
+       return &__ctype_info_get()->__ctype_toupper;
+}
+
+
+}      // namespace Libroot
+}      // namespace BPrivate
+
+
+#endif //
diff --git a/src/system/libroot/posix/locale/duplocale.cpp 
b/src/system/libroot/posix/locale/duplocale.cpp
new file mode 100644
index 0000000..befb19a
--- /dev/null
+++ b/src/system/libroot/posix/locale/duplocale.cpp
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2022, Trung Nguyen, trungnt282910@xxxxxxxxx
+ * All rights reserved. Distributed under the terms of the MIT License.
+ */
+
+
+#include <new>
+#include <errno.h>
+#include <locale.h>
+#include <strings.h>
+
+#include <ErrnoMaintainer.h>
+
+#include "LocaleBackend.h"
+
+
+using BPrivate::Libroot::gGlobalLocaleBackend;
+using BPrivate::Libroot::LocaleBackend;
+using BPrivate::Libroot::LocaleDataBridge;
+
+
+extern "C" locale_t
+duplocale(locale_t locobj)
+{
+    locale_t newObj = new (std::nothrow) __locale_t;
+    if (newObj == NULL) {
+        errno = ENOMEM;
+        return (locale_t)0;
+    }
+
+    LocaleBackend* backend = (locobj == LC_GLOBAL_LOCALE) ?
+        gGlobalLocaleBackend : (LocaleBackend*)locobj->backend;
+
+    if (backend == NULL) {
+        newObj->backend = NULL;
+        return newObj;
+    }
+
+    // Check if everything is set to "C" or "POSIX",
+    // and avoid making a backend.
+    const char* localeDescription = backend->SetLocale(LC_ALL, NULL);
+
+    if ((strcasecmp(localeDescription, "POSIX") == 0) || 
(strcasecmp(localeDescription, "C") == 0)) {
+        newObj->backend = NULL;
+        return newObj;
+    }
+
+    BPrivate::ErrnoMaintainer errnoMaintainer;
+
+    LocaleBackend*& newBackend = (LocaleBackend*&)newObj->backend;
+    LocaleDataBridge*& newDataBridge = (LocaleDataBridge*&)newObj->databridge;
+    newBackend = LocaleBackend::CreateBackend();
+
+    if (newBackend == NULL) {
+        errno = ENOMEM;
+        delete newObj;
+        return (locale_t)0;
+    }
+
+    newDataBridge = new (std::nothrow) LocaleDataBridge(false);
+
+    if (newDataBridge == NULL) {
+        errno = ENOMEM;
+        delete newBackend;
+        delete newObj;
+        return (locale_t)0;
+    }
+
+    newBackend->Initialize(newDataBridge);
+
+    // Skipping LC_ALL. Asking for LC_ALL would force the backend
+    // to query each other value once, anyway.
+    for (int lc = 1; lc <= LC_LAST; ++lc) {
+        newBackend->SetLocale(lc, backend->SetLocale(lc, NULL));
+    }
+
+    return newObj;
+}
diff --git a/src/system/libroot/posix/locale/freelocale.cpp 
b/src/system/libroot/posix/locale/freelocale.cpp
new file mode 100644
index 0000000..ccc29ea
--- /dev/null
+++ b/src/system/libroot/posix/locale/freelocale.cpp
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2022, Trung Nguyen, trungnt282910@xxxxxxxxx
+ * All rights reserved. Distributed under the terms of the MIT License.
+ */
+
+
+#include <locale.h>
+
+#include "LocaleBackend.h"
+
+
+using BPrivate::Libroot::LocaleBackend;
+using BPrivate::Libroot::LocaleDataBridge;
+
+
+extern "C" void
+freelocale(locale_t locobj)
+{
+    if (locobj->backend) {
+        LocaleBackend::DestroyBackend((LocaleBackend*)locobj->backend);
+        LocaleDataBridge* databridge = (LocaleDataBridge*)locobj->databridge;
+        delete databridge;
+    }
+    delete locobj;
+}
diff --git a/src/system/libroot/posix/locale/localeconv.cpp 
b/src/system/libroot/posix/locale/localeconv.cpp
index 8b353cc..7c397ff 100644
--- a/src/system/libroot/posix/locale/localeconv.cpp
+++ b/src/system/libroot/posix/locale/localeconv.cpp
@@ -12,7 +12,6 @@

 #ifndef _KERNEL_MODE
 #include "LocaleBackend.h"
-using BPrivate::Libroot::gLocaleBackend;
 #endif


@@ -20,8 +19,8 @@
 localeconv(void)
 {
 #ifndef _KERNEL_MODE
-       if (gLocaleBackend)
-               return const_cast<lconv*>(gLocaleBackend->LocaleConv());
+       if (GET_LOCALE_BACKEND())
+               return const_cast<lconv*>(GET_LOCALE_BACKEND()->LocaleConv());
 #endif

        return &BPrivate::Libroot::gPosixLocaleConv;
diff --git a/src/system/libroot/posix/locale/newlocale.cpp 
b/src/system/libroot/posix/locale/newlocale.cpp
new file mode 100644
index 0000000..fad4a9d
--- /dev/null
+++ b/src/system/libroot/posix/locale/newlocale.cpp
@@ -0,0 +1,120 @@
+/*
+ * Copyright 2022, Trung Nguyen, trungnt282910@xxxxxxxxx
+ * All rights reserved. Distributed under the terms of the MIT License.
+ */
+
+#include <new>
+#include <errno.h>
+#include <locale.h>
+#include <strings.h>
+
+#include <ErrnoMaintainer.h>
+
+#include "LocaleBackend.h"
+#include "LocaleInternal.h"
+
+
+using BPrivate::Libroot::GetLocalesFromEnvironment;
+using BPrivate::Libroot::LocaleBackend;
+using BPrivate::Libroot::LocaleDataBridge;
+
+
+extern "C" locale_t
+newlocale(int category_mask, const char* locale, locale_t base)
+{
+    if (((category_mask | LC_ALL_MASK) != LC_ALL_MASK) || (locale == NULL)) {
+        errno = EINVAL;
+        return (locale_t)0;
+    }
+
+    bool newObject = false;
+
+    if (base == NULL) {
+        base = new (std::nothrow) __locale_t;
+        if (base == NULL) {
+            errno = ENOMEM;
+            return (locale_t)0;
+        }
+        base->magic = LOCALE_T_MAGIC;
+        base->backend = NULL;
+
+        newObject = true;
+    }
+
+    LocaleBackend*& backend = (LocaleBackend*&)base->backend;
+    LocaleDataBridge*& databridge = (LocaleDataBridge*&)base->databridge;
+
+    const char* locales[LC_LAST + 1];
+       for (int lc = 0; lc <= LC_LAST; lc++)
+               locales[lc] = NULL;
+
+    if (*locale == '\0') {
+        if (category_mask == LC_ALL_MASK) {
+            GetLocalesFromEnvironment(LC_ALL, locales);
+        } else {
+            for (int lc = 1; lc <= LC_LAST; ++lc) {
+                if (category_mask & (1 << (lc - 1))) {
+                    GetLocalesFromEnvironment(lc, locales);
+                }
+            }
+        }
+    } else {
+        if (category_mask == LC_ALL_MASK) {
+            locales[LC_ALL] = locale;
+        }
+        for (int lc = 1; lc <= LC_LAST; ++lc) {
+            if (category_mask & (1 << (lc - 1))) {
+                locales[lc] = locale;
+            }
+        }
+    }
+
+    if (!backend) {
+        // for any locale other than POSIX/C, we try to activate the ICU
+        // backend
+        bool needBackend = false;
+        for (int lc = 0; lc <= LC_LAST; lc++) {
+            if (locales[lc] != NULL && strcasecmp(locales[lc], "POSIX") != 0
+                    && strcasecmp(locales[lc], "C") != 0) {
+                needBackend = true;
+                break;
+            }
+        }
+        if (needBackend) {
+            backend = LocaleBackend::CreateBackend();
+            if (backend == NULL) {
+                errno = ENOMEM;
+                if (newObject) {
+                    delete base;
+                }
+                return (locale_t)0;
+            }
+            databridge = new (std::nothrow) LocaleDataBridge(false);
+            if (databridge == NULL) {
+                errno = ENOMEM;
+                delete backend;
+                if (newObject) {
+                    delete base;
+                }
+                return (locale_t)0;
+            }
+            backend->Initialize(databridge);
+        }
+       }
+
+    BPrivate::ErrnoMaintainer errnoMaintainer;
+
+    if (backend != NULL) {
+        for (int lc = 0; lc <= LC_LAST; lc++) {
+                       if (locales[lc] != NULL) {
+                               locale = backend->SetLocale(lc, locales[lc]);
+                               if (lc == LC_ALL) {
+                                       // skip the rest, LC_ALL overrides
+                    break;
+                               }
+                       }
+        }
+    }
+
+    return base;
+}
diff --git a/src/system/libroot/posix/locale/nl_langinfo.cpp 
b/src/system/libroot/posix/locale/nl_langinfo.cpp
index b48f6f5..48670f8 100644
--- a/src/system/libroot/posix/locale/nl_langinfo.cpp
+++ b/src/system/libroot/posix/locale/nl_langinfo.cpp
@@ -11,7 +11,6 @@
 #include <PosixLanginfo.h>


-using BPrivate::Libroot::gLocaleBackend;
 using BPrivate::Libroot::gPosixLanginfo;


@@ -21,8 +20,8 @@
        if (item < 0 || item >= _NL_LANGINFO_LAST)
                return const_cast<char*>("");

-       if (gLocaleBackend != NULL)
-               return const_cast<char*>(gLocaleBackend->GetLanginfo(item));
+       if (GET_LOCALE_BACKEND() != NULL)
+               return 
const_cast<char*>(GET_LOCALE_BACKEND()->GetLanginfo(item));

        return const_cast<char*>(gPosixLanginfo[item]);
 }
diff --git a/src/system/libroot/posix/locale/setlocale.cpp 
b/src/system/libroot/posix/locale/setlocale.cpp
index 7977780..7519e1d 100644
--- a/src/system/libroot/posix/locale/setlocale.cpp
+++ b/src/system/libroot/posix/locale/setlocale.cpp
@@ -7,65 +7,19 @@

 #include <ctype.h>
 #include <locale.h>
-#include <stdlib.h>
 #include <strings.h>

 #include <ErrnoMaintainer.h>

 #include "LocaleBackend.h"
+#include "LocaleInternal.h"


-using BPrivate::Libroot::gLocaleBackend;
+using BPrivate::Libroot::gGlobalLocaleBackend;
+using BPrivate::Libroot::GetLocalesFromEnvironment;
 using BPrivate::Libroot::LocaleBackend;


-static status_t
-GetLocalesFromEnvironment(int category, const char** locales)
-{
-       const char* locale = getenv("LC_ALL");
-       if (locale && *locale)
-               locales[category] = locale;
-       else {
-               // the order of the names must match the one specified in 
locale.h
-               const char* categoryNames[] = {
-                       "LC_ALL",
-                       "LC_COLLATE",
-                       "LC_CTYPE",
-                       "LC_MONETARY",
-                       "LC_NUMERIC",
-                       "LC_TIME",
-                       "LC_MESSAGES"
-               };
-               int from, to;
-               if (category == LC_ALL) {
-                       // we need to check each real category if all of them 
should be set
-                       from = 1;
-                       to = LC_LAST;
-               } else
-                       from = to = category;
-               bool haveDifferentLocales = false;
-               locale = NULL;
-               for (int lc = from; lc <= to; lc++) {
-                       const char* lastLocale = locale;
-                       locale = getenv(categoryNames[lc]);
-                       if (!locale || *locale == '\0')
-                               locale = getenv("LANG");
-                       if (!locale || *locale == '\0')
-                               locale = "POSIX";
-                       locales[lc] = locale;
-                       if (lastLocale && strcasecmp(locale, lastLocale) != 0)
-                               haveDifferentLocales = true;
-               }
-               if (!haveDifferentLocales) {
-                       // we can set all locales at once
-                       locales[LC_ALL] = locale;
-               }
-       }
-
-       return B_OK;
-}
-
-
 extern "C" char*
 setlocale(int category, const char* locale)
 {
@@ -76,8 +30,8 @@

        if (locale == NULL) {
                // query the locale of the given category
-               if (gLocaleBackend != NULL)
-                       return 
const_cast<char*>(gLocaleBackend->SetLocale(category, NULL));
+               if (gGlobalLocaleBackend != NULL)
+                       return 
const_cast<char*>(gGlobalLocaleBackend->SetLocale(category, NULL));
                else
                        return const_cast<char*>("POSIX");
        }
@@ -93,7 +47,7 @@
        else
                locales[category] = locale;

-       if (!gLocaleBackend) {
+       if (!gGlobalLocaleBackend) {
                // for any locale other than POSIX/C, we try to activate the ICU
                // backend
                bool needBackend = false;
@@ -108,17 +62,17 @@
                        return NULL;
        }

-       if (gLocaleBackend != NULL) {
+       if (gGlobalLocaleBackend != NULL) {
                for (int lc = 0; lc <= LC_LAST; lc++) {
                        if (locales[lc] != NULL) {
-                               locale = gLocaleBackend->SetLocale(lc, 
locales[lc]);
+                               locale = gGlobalLocaleBackend->SetLocale(lc, 
locales[lc]);
                                if (lc == LC_ALL) {
                                        // skip the rest, LC_ALL overrides
                                        return const_cast<char*>(locale);
                                }
                        }
                }
-               return const_cast<char*>(gLocaleBackend->SetLocale(category, 
NULL));
+               return 
const_cast<char*>(gGlobalLocaleBackend->SetLocale(category, NULL));
        }

        return const_cast<char*>("POSIX");
diff --git a/src/system/libroot/posix/locale/uselocale.cpp 
b/src/system/libroot/posix/locale/uselocale.cpp
new file mode 100644
index 0000000..c3b7c89
--- /dev/null
+++ b/src/system/libroot/posix/locale/uselocale.cpp
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2022, Trung Nguyen, trungnt282910@xxxxxxxxx
+ * All rights reserved. Distributed under the terms of the MIT License.
+ */
+
+
+#include <errno.h>
+#include <locale.h>
+
+#include "LocaleBackend.h"
+#include "LocaleInternal.h"
+
+
+using BPrivate::Libroot::gGlobalLocaleDataBridge;
+using BPrivate::Libroot::gLocaleInfo;
+using BPrivate::Libroot::LocaleDataBridge;
+
+
+extern "C" locale_t
+uselocale(locale_t newLoc)
+{
+    locale_t oldLoc = gLocaleInfo;
+    if (gLocaleInfo == NULL) {
+        oldLoc = LC_GLOBAL_LOCALE;
+    }
+
+    if (newLoc != (locale_t)0) {
+        if (newLoc == LC_GLOBAL_LOCALE) {
+            gLocaleInfo = NULL;
+        } else {
+            if (newLoc->magic != LOCALE_T_MAGIC) {
+                errno = EINVAL;
+                return (locale_t)0;
+            }
+            gLocaleInfo = newLoc;
+        }
+
+        if (gLocaleInfo != NULL) {
+            
((LocaleDataBridge*)gLocaleInfo->databridge)->ApplyToCurrentThread();
+        } else {
+            gGlobalLocaleDataBridge.ApplyToCurrentThread();
+        }
+    }
+
+    return oldLoc;
+}
diff --git a/src/system/libroot/posix/locale/wctype.cpp 
b/src/system/libroot/posix/locale/wctype.cpp
index 4c50c5b..4b71446 100644
--- a/src/system/libroot/posix/locale/wctype.cpp
+++ b/src/system/libroot/posix/locale/wctype.cpp
@@ -13,7 +13,8 @@
 #include "LocaleBackend.h"


-using BPrivate::Libroot::gLocaleBackend;
+using BPrivate::Libroot::LocaleBackend;
+

 /*
  * In many of the following functions, we make use of the fact that with
@@ -26,13 +27,15 @@
 int
 iswctype(wint_t wc, wctype_t charClass)
 {
-       if (gLocaleBackend == NULL) {
+       LocaleBackend* backend = GET_LOCALE_BACKEND();
+
+       if (backend == NULL) {
                if (wc < 0 || wc > 127)
                        return 0;
                return __isctype(wc, charClass);
        }

-       return gLocaleBackend->IsWCType(wc, charClass);
+       return backend->IsWCType(wc, charClass);
 }


@@ -123,14 +126,16 @@
 wint_t
 towlower(wint_t wc)
 {
-       if (gLocaleBackend == NULL) {
+       LocaleBackend* backend = GET_LOCALE_BACKEND();
+
+       if (backend == NULL) {
                if (wc < 0 || wc > 127)
                        return wc;
                return tolower(wc);
        }

        wint_t result = wc;
-       gLocaleBackend->ToWCTrans(wc, _ISlower, result);
+       backend->ToWCTrans(wc, _ISlower, result);

        return result;
 }
@@ -139,14 +144,16 @@
 wint_t
 towupper(wint_t wc)
 {
-       if (gLocaleBackend == NULL) {
+       LocaleBackend* backend = GET_LOCALE_BACKEND();
+
+       if (backend == NULL) {
                if (wc < 0 || wc > 127)
                        return wc;
                return toupper(wc);
        }

        wint_t result = wc;
-       gLocaleBackend->ToWCTrans(wc, _ISupper, result);
+       backend->ToWCTrans(wc, _ISupper, result);

        return result;
 }
@@ -155,7 +162,9 @@
 wint_t
 towctrans(wint_t wc, wctrans_t transition)
 {
-       if (gLocaleBackend == NULL) {
+       LocaleBackend* backend = GET_LOCALE_BACKEND();
+
+       if (backend == NULL) {
                if (transition == _ISlower)
                        return tolower(wc);
                if (transition == _ISupper)
@@ -166,7 +175,7 @@
        }

        wint_t result = wc;
-       status_t status = gLocaleBackend->ToWCTrans(wc, transition, result);
+       status_t status = backend->ToWCTrans(wc, transition, result);
        if (status != B_OK)
                __set_errno(EINVAL);

diff --git a/src/system/libroot/posix/string/strcoll.cpp 
b/src/system/libroot/posix/string/strcoll.cpp
index 1a477e5..fa61d76 100644
--- a/src/system/libroot/posix/string/strcoll.cpp
+++ b/src/system/libroot/posix/string/strcoll.cpp
@@ -11,15 +11,17 @@
 #include "LocaleBackend.h"


-using BPrivate::Libroot::gLocaleBackend;
+using BPrivate::Libroot::LocaleBackend;
 

 extern "C" int
 strcoll(const char *a, const char *b)
 {
-       if (gLocaleBackend != NULL) {
+       LocaleBackend* backend = GET_LOCALE_BACKEND();
+
+       if (backend != NULL) {
                int result = 0;
-               status_t status = gLocaleBackend->Strcoll(a, b, result);
+               status_t status = backend->Strcoll(a, b, result);

                if (status != B_OK)
                        __set_errno(EINVAL);
diff --git a/src/system/libroot/posix/string/strxfrm.cpp 
b/src/system/libroot/posix/string/strxfrm.cpp
index 058f3cf..fbeb1ba 100644
--- a/src/system/libroot/posix/string/strxfrm.cpp
+++ b/src/system/libroot/posix/string/strxfrm.cpp
@@ -11,15 +11,17 @@
 #include "LocaleBackend.h"


-using BPrivate::Libroot::gLocaleBackend;
+using BPrivate::Libroot::LocaleBackend;

 
 extern "C" size_t
 strxfrm(char *out, const char *in, size_t size)
 {
-       if (gLocaleBackend != NULL) {
+       LocaleBackend* backend = GET_LOCALE_BACKEND();
+
+       if (backend != NULL) {
                size_t outSize = 0;
-               status_t status =  gLocaleBackend->Strxfrm(out, in, size, 
outSize);
+               status_t status =  backend->Strxfrm(out, in, size, outSize);

                if (status != B_OK)
                        __set_errno(EINVAL);
diff --git a/src/system/libroot/posix/time/localtime.cpp 
b/src/system/libroot/posix/time/localtime.cpp
index 739712f..7923f89 100644
--- a/src/system/libroot/posix/time/localtime.cpp
+++ b/src/system/libroot/posix/time/localtime.cpp
@@ -17,7 +17,6 @@
 #include "LocaleBackend.h"


-using BPrivate::Libroot::gLocaleBackend;
 using BPrivate::Libroot::LocaleBackend;


@@ -43,13 +42,13 @@
 extern "C" void
 tzset(void)
 {
-       if (gLocaleBackend == NULL && LocaleBackend::LoadBackend() != B_OK)
+       if (GET_LOCALE_BACKEND() == NULL && LocaleBackend::LoadBackend() != 
B_OK)
                return;

        char timeZoneID[B_FILE_NAME_LENGTH] = { "GMT" };
        _kern_get_timezone(NULL, timeZoneID, sizeof(timeZoneID));

-       gLocaleBackend->TZSet(timeZoneID, getenv("TZ"));
+       GET_LOCALE_BACKEND()->TZSet(timeZoneID, getenv("TZ"));
 }


@@ -71,8 +70,11 @@
        }

        tzset();
-       if (gLocaleBackend != NULL) {
-               status_t status = gLocaleBackend->Localtime(inTime, tmOut);
+
+       LocaleBackend* backend = GET_LOCALE_BACKEND();
+
+       if (backend != NULL) {
+               status_t status = backend->Localtime(inTime, tmOut);

                if (status != B_OK)
                        __set_errno(EOVERFLOW);
@@ -104,8 +106,11 @@
        }

        tzset();
-       if (gLocaleBackend != NULL) {
-               status_t status = gLocaleBackend->Gmtime(inTime, tmOut);
+
+       LocaleBackend* backend = GET_LOCALE_BACKEND();
+
+       if (backend != NULL) {
+               status_t status = backend->Gmtime(inTime, tmOut);

                if (status != B_OK)
                        __set_errno(EOVERFLOW);
@@ -128,9 +133,12 @@
        }

        tzset();
-       if (gLocaleBackend != NULL) {
+
+       LocaleBackend* backend = GET_LOCALE_BACKEND();
+
+       if (backend != NULL) {
                time_t timeOut;
-               status_t status = gLocaleBackend->Mktime(inTm, timeOut);
+               status_t status = backend->Mktime(inTm, timeOut);

                if (status != B_OK) {
                        __set_errno(EOVERFLOW);
@@ -154,9 +162,12 @@
                return -1;
        }
        tzset();
-       if (gLocaleBackend != NULL) {
+
+       LocaleBackend* backend = GET_LOCALE_BACKEND();
+
+       if (backend != NULL) {
                time_t timeOut;
-               status_t status = gLocaleBackend->Timegm(inTm, timeOut);
+               status_t status = backend->Timegm(inTm, timeOut);

                if (status != B_OK) {
                        __set_errno(EOVERFLOW);
diff --git a/src/system/libroot/posix/time/timelocal.cpp 
b/src/system/libroot/posix/time/timelocal.cpp
index bfa62bb..1b83bfe 100644
--- a/src/system/libroot/posix/time/timelocal.cpp
+++ b/src/system/libroot/posix/time/timelocal.cpp
@@ -12,14 +12,11 @@
 #include "PosixLCTimeInfo.h"


-using BPrivate::Libroot::gLocaleBackend;
-
-
 extern "C" const lc_time_t*
 __get_current_time_locale(void)
 {
-       if (gLocaleBackend)
-               return gLocaleBackend->LCTimeInfo();
+       if (GET_LOCALE_BACKEND())
+               return GET_LOCALE_BACKEND()->LCTimeInfo();

        return &BPrivate::Libroot::gPosixLCTimeInfo;
 }
diff --git a/src/system/libroot/posix/wchar/mbrtowc.cpp 
b/src/system/libroot/posix/wchar/mbrtowc.cpp
index 38ee8a0..c2154e1 100644
--- a/src/system/libroot/posix/wchar/mbrtowc.cpp
+++ b/src/system/libroot/posix/wchar/mbrtowc.cpp
@@ -20,7 +20,7 @@
 #endif


-using BPrivate::Libroot::gLocaleBackend;
+using BPrivate::Libroot::LocaleBackend;


 extern "C" size_t
@@ -34,7 +34,9 @@
        if (s == NULL)
                return __mbrtowc(NULL, "", 1, ps);

-       if (gLocaleBackend == NULL) {
+       LocaleBackend* backend = GET_LOCALE_BACKEND();
+
+       if (backend == NULL) {
                if (*s == '\0') {
                        memset(ps, 0, sizeof(mbstate_t));

@@ -64,7 +66,7 @@

        size_t lengthUsed;
        status_t status
-               = gLocaleBackend->MultibyteToWchar(pwc, s, n, ps, lengthUsed);
+               = backend->MultibyteToWchar(pwc, s, n, ps, lengthUsed);

        if (status == B_BAD_INDEX)
                return (size_t)-2;
diff --git a/src/system/libroot/posix/wchar/mbsrtowcs.cpp 
b/src/system/libroot/posix/wchar/mbsrtowcs.cpp
index 7776be2..15b1d84 100644
--- a/src/system/libroot/posix/wchar/mbsrtowcs.cpp
+++ b/src/system/libroot/posix/wchar/mbsrtowcs.cpp
@@ -20,22 +20,24 @@
 #endif


-using BPrivate::Libroot::gLocaleBackend;
+using BPrivate::Libroot::LocaleBackend;


 extern "C" size_t
 __mbsnrtowcs(wchar_t* dst, const char** src, size_t nmc, size_t len,
        mbstate_t* ps)
 {
+       LocaleBackend* backend = GET_LOCALE_BACKEND();
+
        TRACE(("mbsnrtowcs(%p, %p, %lu, %lu) - lb:%p\n", dst, *src, nmc, len,
-               gLocaleBackend));
+               backend));

        if (ps == NULL) {
                static mbstate_t internalMbState;
                ps = &internalMbState;
        }

-       if (gLocaleBackend == NULL) {
+       if (backend == NULL) {
                /*
                 * The POSIX locale is active. Since the POSIX locale only 
contains
                 * chars 0-127 and those ASCII chars are compatible with the 
UTF32
@@ -82,7 +84,7 @@
        }

        size_t result = 0;
-       status_t status = gLocaleBackend->MultibyteStringToWchar(dst, len, src, 
nmc,
+       status_t status = backend->MultibyteStringToWchar(dst, len, src, nmc,
                ps, result);

        if (status == B_BAD_DATA) {
@@ -112,7 +114,8 @@
                ps = &internalMbState;
        }

-       size_t srcLen = gLocaleBackend == NULL ? strlen(*src) + 1 : (size_t)-1;
+       LocaleBackend* backend = GET_LOCALE_BACKEND();
+       size_t srcLen = backend == NULL ? strlen(*src) + 1 : (size_t)-1;

        return __mbsnrtowcs(dst, src, srcLen, len, ps);
 }
diff --git a/src/system/libroot/posix/wchar/wcrtomb.cpp 
b/src/system/libroot/posix/wchar/wcrtomb.cpp
index 8285351..f84dfc9 100644
--- a/src/system/libroot/posix/wchar/wcrtomb.cpp
+++ b/src/system/libroot/posix/wchar/wcrtomb.cpp
@@ -20,12 +20,14 @@
 #endif


-using BPrivate::Libroot::gLocaleBackend;
+using BPrivate::Libroot::LocaleBackend;


 extern "C" size_t
 __wcrtomb(char* s, wchar_t wc, mbstate_t* ps)
 {
+       LocaleBackend* backend = GET_LOCALE_BACKEND();
+
        if (ps == NULL) {
                static mbstate_t internalMbState;
                ps = &internalMbState;
@@ -34,7 +36,7 @@
        if (s == NULL)
                wc = 0;

-       if (gLocaleBackend == NULL) {
+       if (backend == NULL) {
                /*
                 * The POSIX locale is active. Since the POSIX locale only 
contains
                 * chars 0-127 and those ASCII chars are compatible with the 
UTF32
@@ -54,7 +56,7 @@
        }

        size_t lengthUsed;
-       status_t status = gLocaleBackend->WcharToMultibyte(s, wc, ps, 
lengthUsed);
+       status_t status = backend->WcharToMultibyte(s, wc, ps, lengthUsed);

        if (status == B_BAD_INDEX)
                return (size_t)-2;
diff --git a/src/system/libroot/posix/wchar/wcscoll.cpp 
b/src/system/libroot/posix/wchar/wcscoll.cpp
index d06ffcb..e2d4e41f 100644
--- a/src/system/libroot/posix/wchar/wcscoll.cpp
+++ b/src/system/libroot/posix/wchar/wcscoll.cpp
@@ -8,15 +8,17 @@
 #include <wchar_private.h>


-using BPrivate::Libroot::gLocaleBackend;
+using BPrivate::Libroot::LocaleBackend;


 extern "C" int
 __wcscoll(const wchar_t* wcs1, const wchar_t* wcs2)
 {
-       if (gLocaleBackend != NULL) {
+       LocaleBackend* backend = GET_LOCALE_BACKEND();
+
+       if (backend != NULL) {
                int result = 0;
-               status_t status = gLocaleBackend->Wcscoll(wcs1, wcs2, result);
+               status_t status = backend->Wcscoll(wcs1, wcs2, result);

                if (status != B_OK)
                        __set_errno(EINVAL);
diff --git a/src/system/libroot/posix/wchar/wcsrtombs.cpp 
b/src/system/libroot/posix/wchar/wcsrtombs.cpp
index 9d6b3cc..d33ab80 100644
--- a/src/system/libroot/posix/wchar/wcsrtombs.cpp
+++ b/src/system/libroot/posix/wchar/wcsrtombs.cpp
@@ -21,22 +21,24 @@
 #endif


-using BPrivate::Libroot::gLocaleBackend;
+using BPrivate::Libroot::LocaleBackend;


 extern "C" size_t
 __wcsnrtombs(char* dst, const wchar_t** src, size_t nwc, size_t len,
        mbstate_t* ps)
 {
+       LocaleBackend* backend = GET_LOCALE_BACKEND();
+
        TRACE(("wcsnrtombs(%p, %p, %lu, %lu) - lb:%p\n", dst, *src, nwc, len,
-               gLocaleBackend));
+               backend));

        if (ps == NULL) {
                static mbstate_t internalMbState;
                ps = &internalMbState;
        }

-       if (gLocaleBackend == NULL) {
+       if (backend == NULL) {
                /*
                 * The POSIX locale is active. Since the POSIX locale only 
contains
                 * chars 0-127 and those ASCII chars are compatible with the 
UTF32
@@ -83,7 +85,7 @@
        }

        size_t result = 0;
-       status_t status = gLocaleBackend->WcharStringToMultibyte(dst, len, src, 
nwc,
+       status_t status = backend->WcharStringToMultibyte(dst, len, src, nwc,
                ps, result);

        if (status == B_BAD_DATA) {
diff --git a/src/system/libroot/posix/wchar/wcsxfrm.cpp 
b/src/system/libroot/posix/wchar/wcsxfrm.cpp
index 4260703..fc8ebd9 100644
--- a/src/system/libroot/posix/wchar/wcsxfrm.cpp
+++ b/src/system/libroot/posix/wchar/wcsxfrm.cpp
@@ -10,15 +10,17 @@
 #include <wchar_private.h>


-using BPrivate::Libroot::gLocaleBackend;
+using BPrivate::Libroot::LocaleBackend;


 extern "C" size_t
 __wcsxfrm(wchar_t* dest, const wchar_t* src, size_t destSize)
 {
-       if (gLocaleBackend != NULL) {
+       LocaleBackend* backend = GET_LOCALE_BACKEND();
+
+       if (backend != NULL) {
                size_t outSize = 0;
-               status_t status = gLocaleBackend->Wcsxfrm(dest, src, destSize, 
outSize);
+               status_t status = backend->Wcsxfrm(dest, src, destSize, 
outSize);

                if (status != B_OK)
                        __set_errno(EINVAL);
diff --git a/src/system/libroot/stubbed/libroot_stubs.c 
b/src/system/libroot/stubbed/libroot_stubs.c
index 5cd88a1..55458be 100644
--- a/src/system/libroot/stubbed/libroot_stubs.c
+++ b/src/system/libroot/stubbed/libroot_stubs.c
@@ -11,16 +11,17 @@
 int _ZN8BPrivate10kGroupFileE;
 int _ZN8BPrivate11kPasswdFileE;
 int _ZN8BPrivate14kShadowPwdFileE;
-int _ZN8BPrivate7Libroot14gLocaleBackendE;
+int _ZN8BPrivate7Libroot11gLocaleInfoE;
 int _ZN8BPrivate7Libroot14gPosixLanginfoE;
 int _ZN8BPrivate7Libroot16gPosixLCTimeInfoE;
 int _ZN8BPrivate7Libroot16gPosixLocaleConvE;
+int _ZN8BPrivate7Libroot20gGlobalLocaleBackendE;
+int _ZN8BPrivate7Libroot23gGlobalLocaleDataBridgeE;
 int _ZN8BPrivate9hoardHeap10_sizeTableE;
 int _ZN8BPrivate9hoardHeap10_thresholdE;
 int _ZN8BPrivate9hoardHeap14_numProcessorsE;
 int _ZN8BPrivate9hoardHeap15fMaxThreadHeapsE;
 int _ZN8BPrivate9hoardHeap18_numProcessorsMaskE;
-int __bss_start;
 int __ctype32_wctrans;
 int __ctype32_wctype;
 int __ctype_b;
@@ -28,6 +29,7 @@
 int __ctype_tolower;
 int __ctype_toupper;
 int __gABIVersion;
+int __gAPIVersion;
 int __gCPUCount;
 int __gCommPageAddress;
 int __gRuntimeLoader;
@@ -42,10 +44,10 @@
 int __printf_arginfo_table;
 int __printf_function_table;
 int __progname;
+int __signgam;
+int __stack_chk_guard;
 int __wcsmbs_gconv_fcts;
 int _data_offset_main_;
-int _edata;
-int _end;
 int _gSharedObjectHaikuABI;
 int _gSharedObjectHaikuVersion;
 int _nl_C_LC_COLLATE;
@@ -60,6 +62,7 @@
 int _nl_current_LC_MESSAGES;
 int _nl_current_LC_MONETARY;
 int _nl_current_LC_NUMERIC;
+int _nl_global_locale;
 int _obstack;
 int _rtDebugFlag;
 int _single_threaded;
@@ -79,12 +82,10 @@
 int optind;
 int optopt;
 int re_syntax_options;
-int signgam;
 int stderr;
 int stdin;
 int stdout;
 int sys_siglist;
-int tab54;
 int timezone;
 int tzname;

@@ -288,6 +289,7 @@
 void _Z17__init_after_forkv() {}
 void _Z18HMAC_SHA256_UpdateP15HMAC_SHA256_CTXPKvm() {}
 void _Z18crypto_scrypt_smixPhmmPvS0_() {}
+void _Z20__pthread_mutex_lockP14_pthread_mutexjl() {}
 void _Z22internal_path_for_pathPcmPKcS1_19path_base_directoryS1_jS_m() {}
 void _Z26get_driver_settings_stringPvPcPlb() {}
 void 
_Z36posix_spawn_file_actions_addchdir_npPP25_posix_spawn_file_actionsPKc() {}
@@ -312,7 +314,7 @@
 void _ZN10__cxxabiv120__si_class_type_infoD0Ev() {}
 void _ZN10__cxxabiv120__si_class_type_infoD1Ev() {}
 void _ZN10__cxxabiv120__si_class_type_infoD2Ev() {}
-void _ZN11LocalRWLock15StructureUnlockEv() {}
+void _ZN11LocalRWLock5_WaitEbjl() {}
 void _ZN11LocalRWLock8_UnblockEv() {}
 void _ZN14parsed_element11SetCharTypeEha() {}
 void _ZN14parsed_element5AdoptERK16known_identifier() {}
@@ -323,11 +325,17 @@
 void 
_ZN16DoublyLinkedListI15AtExitInfoBlock31DoublyLinkedListStandardGetLinkIS0_EED2Ev()
 {}
 void 
_ZN16SinglyLinkedListI10AtExitInfo31SinglyLinkedListStandardGetLinkIS0_EED1Ev() 
{}
 void 
_ZN16SinglyLinkedListI10AtExitInfo31SinglyLinkedListStandardGetLinkIS0_EED2Ev() 
{}
+void _ZN17EnvironmentFilter5_InitEiPKcmPKS1_m() {}
+void _ZN8BPrivate10AutoLockerI11LocalRWLockNS1_7LockingEE6UnlockEv() {}
+void _ZN8BPrivate10AutoLockerI5mutex12MutexLockingE6UnlockEv() {}
+void _ZN8BPrivate10AutoLockerIiNS_16UserGroupLockingEE6UnlockEv() {}
 void _ZN8BPrivate10hoardYieldEv() {}
 void _ZN8BPrivate10superblock14makeSuperblockEiPNS_11processHeapE() {}
+void _ZN8BPrivate10superblock8getBlockEv() {}
 void _ZN8BPrivate10superblockC1EiiPNS_9hoardHeapE() {}
 void _ZN8BPrivate10superblockC2EiiPNS_9hoardHeapE() {}
 void _ZN8BPrivate10threadHeap6mallocEm() {}
+void _ZN8BPrivate10threadHeap8memalignEmm() {}
 void _ZN8BPrivate10threadHeapC1Ev() {}
 void _ZN8BPrivate10threadHeapC2Ev() {}
 void _ZN8BPrivate11hoardUnlockER5mutex() {}
@@ -370,14 +378,17 @@
 void _ZN8BPrivate6SHA256D1Ev() {}
 void _ZN8BPrivate6SHA256D2Ev() {}
 void _ZN8BPrivate7Libroot13LocaleBackend11LoadBackendEv() {}
+void _ZN8BPrivate7Libroot13LocaleBackend13CreateBackendEv() {}
+void _ZN8BPrivate7Libroot13LocaleBackend14DestroyBackendEPS1_() {}
 void _ZN8BPrivate7Libroot13LocaleBackendC1Ev() {}
 void _ZN8BPrivate7Libroot13LocaleBackendC2Ev() {}
 void _ZN8BPrivate7Libroot13LocaleBackendD0Ev() {}
 void _ZN8BPrivate7Libroot13LocaleBackendD1Ev() {}
 void _ZN8BPrivate7Libroot13LocaleBackendD2Ev() {}
 void _ZN8BPrivate7Libroot15gPosixClassInfoE() {}
-void _ZN8BPrivate7Libroot16LocaleDataBridgeC1Ev() {}
-void _ZN8BPrivate7Libroot16LocaleDataBridgeC2Ev() {}
+void _ZN8BPrivate7Libroot16LocaleDataBridge20ApplyToCurrentThreadEv() {}
+void _ZN8BPrivate7Libroot16LocaleDataBridgeC1Eb() {}
+void _ZN8BPrivate7Libroot16LocaleDataBridgeC2Eb() {}
 void _ZN8BPrivate7Libroot16LocaleDataBridgeD1Ev() {}
 void _ZN8BPrivate7Libroot16LocaleDataBridgeD2Ev() {}
 void _ZN8BPrivate7Libroot16gPosixToLowerMapE() {}
@@ -385,18 +396,25 @@
 void _ZN8BPrivate7Libroot20LocaleTimeDataBridgeC1Ev() {}
 void _ZN8BPrivate7Libroot20LocaleTimeDataBridgeC2Ev() {}
 void _ZN8BPrivate7Libroot21LocaleCtypeDataBridge11setMbCurMaxEt() {}
-void _ZN8BPrivate7Libroot21LocaleCtypeDataBridgeC1Ev() {}
-void _ZN8BPrivate7Libroot21LocaleCtypeDataBridgeC2Ev() {}
-void _ZN8BPrivate7Libroot23LocaleNumericDataBridgeC1Ev() {}
-void _ZN8BPrivate7Libroot23LocaleNumericDataBridgeC2Ev() {}
+void _ZN8BPrivate7Libroot21LocaleCtypeDataBridge20ApplyToCurrentThreadEv() {}
+void _ZN8BPrivate7Libroot21LocaleCtypeDataBridgeC1Eb() {}
+void _ZN8BPrivate7Libroot21LocaleCtypeDataBridgeC2Eb() {}
+void _ZN8BPrivate7Libroot21LocaleCtypeDataBridgeD1Ev() {}
+void _ZN8BPrivate7Libroot21LocaleCtypeDataBridgeD2Ev() {}
+void _ZN8BPrivate7Libroot23LocaleNumericDataBridge20ApplyToCurrentThreadEv() {}
+void _ZN8BPrivate7Libroot23LocaleNumericDataBridgeC1Eb() {}
+void _ZN8BPrivate7Libroot23LocaleNumericDataBridgeC2Eb() {}
 void _ZN8BPrivate7Libroot23LocaleNumericDataBridgeD1Ev() {}
 void _ZN8BPrivate7Libroot23LocaleNumericDataBridgeD2Ev() {}
 void _ZN8BPrivate7Libroot24LocaleMessagesDataBridgeC1Ev() {}
 void _ZN8BPrivate7Libroot24LocaleMessagesDataBridgeC2Ev() {}
 void _ZN8BPrivate7Libroot24LocaleMonetaryDataBridgeC1Ev() {}
 void _ZN8BPrivate7Libroot24LocaleMonetaryDataBridgeC2Ev() {}
-void _ZN8BPrivate7Libroot24TimeConversionDataBridgeC1Ev() {}
-void _ZN8BPrivate7Libroot24TimeConversionDataBridgeC2Ev() {}
+void _ZN8BPrivate7Libroot24TimeConversionDataBridgeC1Eb() {}
+void _ZN8BPrivate7Libroot24TimeConversionDataBridgeC2Eb() {}
+void _ZN8BPrivate7Libroot24TimeConversionDataBridgeD1Ev() {}
+void _ZN8BPrivate7Libroot24TimeConversionDataBridgeD2Ev() {}
+void _ZN8BPrivate7Libroot25GetLocalesFromEnvironmentEiPPKc() {}
 void _ZN8BPrivate8KMessage11ReceiveFromEilP17port_message_info() {}
 void _ZN8BPrivate8KMessage11_InitBufferEj() {}
 void _ZN8BPrivate8KMessage12_CapacityForEi() {}
@@ -431,7 +449,10 @@
 void 
_ZN8BPrivate9hoardHeap16insertSuperblockEiPNS_10superblockEPNS_11processHeapE() 
{}
 void _ZN8BPrivate9hoardHeap16removeSuperblockEPNS_10superblockEi() {}
 void _ZN8BPrivate9hoardHeap19removeMaxSuperblockEi() {}
+void 
_ZN8BPrivate9hoardHeap23findAvailableSuperblockEiRPNS_5blockEPNS_11processHeapE()
 {}
 void _ZN8BPrivate9hoardHeap5reuseEi() {}
+void _ZN8BPrivate9hoardHeap7recycleEPNS_10superblockE() {}
+void _ZN8BPrivate9hoardHeap8decStatsEiii() {}
 void 
_ZN8BPrivate9hoardHeap9freeBlockERPNS_5blockERPNS_10superblockEiPNS_11processHeapE()
 {}
 void _ZN8BPrivate9hoardHeapC1Ev() {}
 void _ZN8BPrivate9hoardHeapC2Ev() {}
@@ -439,6 +460,8 @@
 void _ZN8BPrivate9hoardSbrkEl() {}
 void _ZN8DateMask10IsCompleteEv() {}
 void _ZN8DateMask7HasTimeEv() {}
+void _ZN9__gnu_cxx20recursive_init_errorC1Ev() {}
+void _ZN9__gnu_cxx20recursive_init_errorC2Ev() {}
 void _ZN9__gnu_cxx20recursive_init_errorD0Ev() {}
 void _ZN9__gnu_cxx20recursive_init_errorD1Ev() {}
 void _ZN9__gnu_cxx20recursive_init_errorD2Ev() {}
@@ -456,6 +479,7 @@
 void _ZN9__gnu_cxx29__concurrence_broadcast_errorD1Ev() {}
 void _ZN9__gnu_cxx29__concurrence_broadcast_errorD2Ev() {}
 void _ZN9__gnu_cxx30__throw_concurrence_lock_errorEv() {}
+void _ZN9__gnu_cxx32__throw_concurrence_unlock_errorEv() {}
 void _ZN9__gnu_cxx35__throw_concurrence_broadcast_errorEv() {}
 void _ZN9__gnu_cxx9__freeresEv() {}
 void _ZNK10__cxxabiv117__class_type_info10__do_catchEPKSt9type_infoPPvj() {}
@@ -494,7 +518,6 @@
 void _ZNK8BPrivate8KMessage9FindFieldEPKcPNS_13KMessageFieldE() {}
 void _ZNK8BPrivate8KMessage9FindFieldEPKcjPNS_13KMessageFieldE() {}
 void _ZNK8BPrivate8KMessage9ReplyPortEv() {}
-void _ZNK8BPrivate8KMessage9_FindTypeIiEEiPKcjiPT_() {}
 void _ZNK9__gnu_cxx24__concurrence_lock_error4whatEv() {}
 void _ZNK9__gnu_cxx24__concurrence_wait_error4whatEv() {}
 void _ZNK9__gnu_cxx26__concurrence_unlock_error4whatEv() {}
@@ -531,7 +554,6 @@
 void _ZNSt9type_infoD1Ev() {}
 void _ZNSt9type_infoD2Ev() {}
 void _ZSt10unexpectedv() {}
-void 
_ZSt13__adjust_heapIPN17EnvironmentFilter5EntryElS1_N9__gnu_cxx5__ops15_Iter_less_iterEEvT_T0_S7_T1_T2_()
 {}
 void _ZSt13get_terminatev() {}
 void _ZSt13set_terminatePFvvE() {}
 void _ZSt14get_unexpectedv() {}
@@ -597,40 +619,18 @@
 void _ZdlPv() {}
 void _ZdlPvRKSt9nothrow_t() {}
 void _ZdlPvm() {}
+void _Znam() {}
 void _ZnamRKSt9nothrow_t() {}
+void _Znwm() {}
 void _ZnwmRKSt9nothrow_t() {}
-void __acos() {}
-void __acosf() {}
-void __acosh() {}
-void __acoshf() {}
-void __acoshl() {}
-void __acosl() {}
-void __acr() {}
-void __add() {}
 void __allocate_pthread() {}
 void __arch_get_stack_trace() {}
 void __arch_get_system_time_offset() {}
 void __arch_init_time() {}
-void __asin() {}
-void __asinf() {}
-void __asinh() {}
-void __asinhf() {}
-void __asinhl() {}
-void __asinl() {}
 void __asprintf() {}
 void __assert_fail() {}
 void __assert_perror_fail() {}
-void __atan2() {}
-void __atan2f() {}
-void __atan2l() {}
-void __atanf() {}
-void __atanh() {}
-void __atanhf() {}
-void __atanhl() {}
-void __atanl() {}
-void __branred() {}
 void __btowc() {}
-void __c32() {}
 void __cabs() {}
 void __cabsf() {}
 void __cabsl() {}
@@ -655,18 +655,12 @@
 void __catanhf() {}
 void __catanhl() {}
 void __catanl() {}
-void __cbrt() {}
-void __cbrtf() {}
-void __cbrtl() {}
 void __ccos() {}
 void __ccosf() {}
 void __ccosh() {}
 void __ccoshf() {}
 void __ccoshl() {}
 void __ccosl() {}
-void __ceil() {}
-void __ceilf() {}
-void __ceill() {}
 void __cexp() {}
 void __cexpf() {}
 void __cexpl() {}
@@ -686,25 +680,12 @@
 void __conj() {}
 void __conjf() {}
 void __conjl() {}
-void __copysign() {}
-void __copysignf() {}
-void __copysignl() {}
-void __cos() {}
-void __cos32() {}
-void __cosf() {}
-void __cosh() {}
-void __coshf() {}
-void __coshl() {}
-void __cosl() {}
 void __cpow() {}
 void __cpowf() {}
 void __cpowl() {}
 void __cproj() {}
 void __cprojf() {}
 void __cprojl() {}
-void __cpy() {}
-void __cpymn() {}
-void __cr() {}
 void __creal() {}
 void __crealf() {}
 void __creall() {}
@@ -724,7 +705,10 @@
 void __ctanhf() {}
 void __ctanhl() {}
 void __ctanl() {}
+void __ctype_b_loc() {}
 void __ctype_get_mb_cur_max() {}
+void __ctype_tolower_loc() {}
+void __ctype_toupper_loc() {}
 void __cxa_allocate_dependent_exception() {}
 void __cxa_allocate_exception() {}
 void __cxa_atexit() {}
@@ -734,7 +718,6 @@
 void __cxa_call_terminate() {}
 void __cxa_call_unexpected() {}
 void __cxa_current_exception_type() {}
-void __cxa_deleted_virtual() {}
 void __cxa_demangle() {}
 void __cxa_end_catch() {}
 void __cxa_finalize() {}
@@ -747,50 +730,12 @@
 void __cxa_guard_acquire() {}
 void __cxa_guard_release() {}
 void __cxa_init_primary_exception() {}
-void __cxa_pure_virtual() {}
 void __cxa_rethrow() {}
 void __cxa_throw() {}
 void __cxa_throw_bad_array_new_length() {}
-void __dbl_mp() {}
-void __doasin() {}
-void __docos() {}
 void __drand48_iterate() {}
-void __drem() {}
-void __dremf() {}
-void __dreml() {}
-void __dubcos() {}
-void __dubsin() {}
-void __dvd() {}
 void __erand48_r() {}
-void __erf() {}
-void __erfc() {}
-void __erfcf() {}
-void __erfcl() {}
-void __erff() {}
-void __erfl() {}
-void __exp() {}
-void __exp1() {}
-void __exp10() {}
-void __exp10f() {}
-void __exp10l() {}
-void __exp2() {}
-void __exp2f() {}
-void __exp2l() {}
-void __exp_atable() {}
-void __exp_deltatable() {}
-void __expf() {}
-void __expl() {}
-void __expl_finite() {}
-void __expm1() {}
-void __expm1f() {}
-void __expm1l() {}
-void __fabs() {}
-void __fabsf() {}
-void __fabsl() {}
 void __fcloseall() {}
-void __fdim() {}
-void __fdimf() {}
-void __fdiml() {}
 void __fe_dfl_env() {}
 void __fedisableexcept() {}
 void __feenableexcept() {}
@@ -806,21 +751,6 @@
 void __finitef() {}
 void __finitel() {}
 void __flatten_process_args() {}
-void __floor() {}
-void __floorf() {}
-void __floorl() {}
-void __fma() {}
-void __fmaf() {}
-void __fmal() {}
-void __fmax() {}
-void __fmaxf() {}
-void __fmaxl() {}
-void __fmin() {}
-void __fminf() {}
-void __fminl() {}
-void __fmod() {}
-void __fmodf() {}
-void __fmodl() {}
 void __fopen_internal() {}
 void __fopen_maybe_mmap() {}
 void __fpclassify() {}
@@ -828,9 +758,6 @@
 void __fpclassifyl() {}
 void __fpurge() {}
 void __freading() {}
-void __frexp() {}
-void __frexpf() {}
-void __frexpl() {}
 void __fsetlocking() {}
 void __fts_children() {}
 void __fts_close() {}
@@ -841,9 +768,6 @@
 void __fts_set() {}
 void __fts_set_clientptr() {}
 void __fwprintf() {}
-void __gamma() {}
-void __gammaf() {}
-void __gammal() {}
 void __gcclibcxx_demangle_callback() {}
 void __gconv_get_builtin_trans() {}
 void __gconv_transform_ascii_internal() {}
@@ -873,113 +797,22 @@
 void __guess_grouping() {}
 void __guess_secondary_architecture_from_path() {}
 void __gxx_personality_v0() {}
-void __halfulp() {}
-void __hdestroy() {}
 void __heap_after_fork_child() {}
 void __heap_after_fork_parent() {}
 void __heap_before_fork() {}
 void __heap_terminate_after() {}
 void __heap_thread_exit() {}
 void __heap_thread_init() {}
-void __hypot() {}
-void __hypotf() {}
-void __hypotl() {}
-void __ieee754_acos() {}
-void __ieee754_acosf() {}
-void __ieee754_acosh() {}
-void __ieee754_acoshf() {}
-void __ieee754_acoshl() {}
-void __ieee754_acosl() {}
-void __ieee754_asin() {}
-void __ieee754_asinf() {}
-void __ieee754_asinl() {}
-void __ieee754_atan2() {}
-void __ieee754_atan2f() {}
-void __ieee754_atan2l() {}
-void __ieee754_atanh() {}
-void __ieee754_atanhf() {}
-void __ieee754_atanhl() {}
-void __ieee754_cosh() {}
-void __ieee754_coshf() {}
-void __ieee754_coshl() {}
-void __ieee754_exp() {}
-void __ieee754_exp10() {}
-void __ieee754_exp10f() {}
-void __ieee754_exp10l() {}
-void __ieee754_exp2() {}
-void __ieee754_exp2f() {}
-void __ieee754_exp2l() {}
-void __ieee754_expf() {}
-void __ieee754_expl() {}
-void __ieee754_fmod() {}
-void __ieee754_fmodf() {}
-void __ieee754_fmodl() {}
-void __ieee754_gamma_r() {}
-void __ieee754_gammaf_r() {}
-void __ieee754_gammal_r() {}
-void __ieee754_hypot() {}
-void __ieee754_hypotf() {}
-void __ieee754_hypotl() {}
-void __ieee754_ilogbl() {}
-void __ieee754_j0() {}
-void __ieee754_j0f() {}
-void __ieee754_j0l() {}
-void __ieee754_j1() {}
-void __ieee754_j1f() {}
-void __ieee754_j1l() {}
-void __ieee754_jn() {}
-void __ieee754_jnf() {}
-void __ieee754_jnl() {}
-void __ieee754_lgamma_r() {}
-void __ieee754_lgammaf_r() {}
-void __ieee754_lgammal_r() {}
-void __ieee754_log() {}
-void __ieee754_log10() {}
-void __ieee754_log10f() {}
-void __ieee754_log10l() {}
-void __ieee754_log2() {}
-void __ieee754_log2f() {}
-void __ieee754_log2l() {}
-void __ieee754_logf() {}
-void __ieee754_logl() {}
-void __ieee754_pow() {}
-void __ieee754_powf() {}
-void __ieee754_powl() {}
-void __ieee754_rem_pio2() {}
-void __ieee754_rem_pio2f() {}
-void __ieee754_remainder() {}
-void __ieee754_remainderf() {}
-void __ieee754_remainderl() {}
-void __ieee754_scalb() {}
-void __ieee754_scalbf() {}
-void __ieee754_scalbl() {}
-void __ieee754_sinh() {}
-void __ieee754_sinhf() {}
-void __ieee754_sinhl() {}
-void __ieee754_sqrt() {}
-void __ieee754_sqrtf() {}
-void __ieee754_sqrtl() {}
-void __ieee754_y0() {}
-void __ieee754_y0f() {}
-void __ieee754_y0l() {}
-void __ieee754_y1() {}
-void __ieee754_y1f() {}
-void __ieee754_y1l() {}
-void __ieee754_yn() {}
-void __ieee754_ynf() {}
-void __ieee754_ynl() {}
-void __ilogb() {}
-void __ilogbf() {}
-void __ilogbl() {}
 void __init_env() {}
 void __init_env_post_heap() {}
 void __init_heap() {}
 void __init_once() {}
 void __init_pthread() {}
 void __init_pwd_backend() {}
+void __init_stack_protector() {}
 void __init_time() {}
 void __initstate_r() {}
-void __inv() {}
+void __ioctl() {}
 void __isinf() {}
 void __isinff() {}
 void __isinfl() {}
@@ -990,56 +823,15 @@
 void __kernel_casinh() {}
 void __kernel_casinhf() {}
 void __kernel_casinhl() {}
-void __kernel_cosf() {}
-void __kernel_rem_pio2() {}
-void __kernel_rem_pio2f() {}
-void __kernel_sinf() {}
-void __kernel_tan() {}
-void __kernel_tanf() {}
 void __lcong48_r() {}
-void __ldexp() {}
-void __ldexpf() {}
-void __ldexpl() {}
-void __lgamma() {}
-void __lgamma_r() {}
-void __lgammaf() {}
-void __lgammaf_r() {}
-void __lgammal() {}
 void __lgammal_r() {}
 void __libc_dlclose() {}
 void __libc_dlopen() {}
 void __libc_dlsym() {}
 void __libc_use_alloca() {}
-void __llrint() {}
-void __llrintf() {}
-void __llrintl() {}
-void __llround() {}
-void __llroundf() {}
-void __llroundl() {}
-void __log() {}
-void __log10() {}
-void __log10f() {}
-void __log10l() {}
-void __log1p() {}
-void __log1pf() {}
-void __log1pl() {}
-void __log2() {}
-void __log2f() {}
-void __log2l() {}
-void __logb() {}
-void __logbf() {}
-void __logbl() {}
-void __logf() {}
-void __logf_finite() {}
-void __logl() {}
+void __load_image_at_path() {}
 void __longjmp_return() {}
-void __lrint() {}
-void __lrintf() {}
-void __lrintl() {}
-void __lround() {}
-void __lroundf() {}
-void __lroundl() {}
-void __matherr() {}
+void __look_up_in_path() {}
 void __mblen() {}
 void __mbrlen() {}
 void __mbrtowc() {}
@@ -1050,16 +842,6 @@
 void __mbtowc() {}
 void __memrchr() {}
 void __mktime_fallback() {}
-void __modf() {}
-void __modff() {}
-void __modfl() {}
-void __mp_dbl() {}
-void __mpatan() {}
-void __mpatan2() {}
-void __mpcos() {}
-void __mpcos1() {}
-void __mpexp() {}
-void __mplog() {}
 void __mpn_add() {}
 void __mpn_add_1() {}
 void __mpn_add_n() {}
@@ -1084,23 +866,11 @@
 void __mpn_sub_1() {}
 void __mpn_sub_n() {}
 void __mpn_submul_1() {}
-void __mpranred() {}
-void __mpsin() {}
-void __mpsin1() {}
-void __mpsqrt() {}
-void __mptan() {}
-void __mul() {}
 void __mutex_destroy() {}
 void __mutex_init() {}
 void __mutex_init_etc() {}
 void __mutex_lock() {}
 void __mutex_unlock() {}
-void __nan() {}
-void __nanf() {}
-void __nanl() {}
-void __nearbyint() {}
-void __nearbyintf() {}
-void __nearbyintl() {}
 void __new_fclose() {}
 void __new_fdopen() {}
 void __new_fgetpos() {}
@@ -1109,26 +879,16 @@
 void __new_pclose() {}
 void __new_popen() {}
 void __new_tmpfile() {}
-void __nextafter() {}
-void __nextafterf() {}
-void __nextafterl() {}
-void __nexttoward() {}
-void __nexttowardf() {}
-void __nexttowardl() {}
 void __nrand48_r() {}
 void __overflow() {}
 void __parse_invoke_line() {}
 void __path_search() {}
-void __pow() {}
-void __pow10() {}
-void __pow10f() {}
-void __pow10l() {}
-void __powf() {}
-void __powl() {}
+void __ppoll() {}
 void __printf_fp() {}
 void __printf_fphex() {}
 void __pselect() {}
 void __pselect_beos() {}
+void __pthread_attr_get_np() {}
 void __pthread_cleanup_pop_handler() {}
 void __pthread_cleanup_push_handler() {}
 void __pthread_destroy_thread() {}
@@ -1150,18 +910,6 @@
 void __register_atfork() {}
 void __register_printf_function() {}
 void __reinit_pwd_backend_after_fork() {}
-void __remainder() {}
-void __remainderf() {}
-void __remainderl() {}
-void __remquo() {}
-void __remquof() {}
-void __remquol() {}
-void __rint() {}
-void __rintf() {}
-void __rintl() {}
-void __round() {}
-void __roundf() {}
-void __roundl() {}
 void __rw_lock_destroy() {}
 void __rw_lock_init() {}
 void __rw_lock_init_etc() {}
@@ -1169,15 +917,6 @@
 void __rw_lock_read_unlock() {}
 void __rw_lock_write_lock() {}
 void __rw_lock_write_unlock() {}
-void __scalb() {}
-void __scalbf() {}
-void __scalbl() {}
-void __scalbln() {}
-void __scalblnf() {}
-void __scalblnl() {}
-void __scalbn() {}
-void __scalbnf() {}
-void __scalbnl() {}
 void __seed48_r() {}
 void __set_scheduler_mode() {}
 void __set_stack_protection() {}
@@ -1201,7 +940,6 @@
 void __siginterrupt_beos() {}
 void __sigismember() {}
 void __sigismember_beos() {}
-void __signArctan() {}
 void __signal() {}
 void __signal_beos() {}
 void __signal_get_sigrtmax() {}
@@ -1209,9 +947,6 @@
 void __signbit() {}
 void __signbitf() {}
 void __signbitl() {}
-void __significand() {}
-void __significandf() {}
-void __significandl() {}
 void __sigpause() {}
 void __sigpause_beos() {}
 void __sigpending() {}
@@ -1227,24 +962,11 @@
 void __sigsuspend_beos() {}
 void __sigwait() {}
 void __sigwait_beos() {}
-void __sin() {}
-void __sin32() {}
-void __sincos() {}
-void __sincosf() {}
-void __sincosl() {}
-void __sinf() {}
-void __sinh() {}
-void __sinhf() {}
-void __sinhl() {}
-void __sinl() {}
-void __slowexp() {}
-void __slowpow() {}
 void __snprintf() {}
-void __sqrt() {}
-void __sqrtf() {}
-void __sqrtl() {}
 void __srand48_r() {}
 void __srandom_r() {}
+void __stack_chk_fail() {}
+void __stack_chk_fail_local() {}
 void __start_watching_system() {}
 void __stop_watching_system() {}
 void __strtod_internal() {}
@@ -1254,7 +976,6 @@
 void __strtoll_internal() {}
 void __strtoul_internal() {}
 void __strtoull_internal() {}
-void __sub() {}
 void __swap_double() {}
 void __swap_float() {}
 void __swap_int16() {}
@@ -1262,28 +983,12 @@
 void __swap_int64() {}
 void __sysconf() {}
 void __sysconf_beos() {}
-void __tanf() {}
-void __tanh() {}
-void __tanhf() {}
-void __tanhl() {}
-void __tanl() {}
-void __tdelete() {}
-void __tdestroy() {}
 void __tens() {}
 void __test_executable() {}
-void __tfind() {}
-void __tgamma() {}
-void __tgammaf() {}
-void __tgammal() {}
+void __timegm_fallback() {}
 void __times() {}
 void __times_beos() {}
 void __tls_get_addr() {}
-void ___tls_get_addr() {}
-void __trunc() {}
-void __truncf() {}
-void __truncl() {}
-void __tsearch() {}
-void __twalk() {}
 void __uflow() {}
 void __underflow() {}
 void __vfscanf() {}
@@ -1356,6 +1061,7 @@
 void _fstat_beos() {}
 void _fstat_current() {}
 void _get_area_info() {}
+void _get_cpu_info_etc() {}
 void _get_image_info() {}
 void _get_next_area_info() {}
 void _get_next_image_info() {}
@@ -1370,6 +1076,8 @@
 void _get_team_usage_info() {}
 void _get_thread_info() {}
 void _getopt_internal() {}
+void _getrusage_base() {}
+void _getrusage_current() {}
 void _init() {}
 void _init_c_library_() {}
 void _itoa() {}
@@ -1498,8 +1206,10 @@
 void _kern_lock_node() {}
 void _kern_map_file() {}
 void _kern_memory_advice() {}
+void _kern_mlock() {}
 void _kern_mount() {}
 void _kern_move_partition() {}
+void _kern_munlock() {}
 void _kern_mutex_lock() {}
 void _kern_mutex_sem_acquire() {}
 void _kern_mutex_sem_release() {}
@@ -1519,6 +1229,7 @@
 void _kern_poll() {}
 void _kern_port_buffer_size_etc() {}
 void _kern_port_count() {}
+void _kern_preallocate() {}
 void _kern_process_info() {}
 void _kern_read() {}
 void _kern_read_attr() {}
@@ -1642,6 +1353,7 @@
 void _kern_wait_for_objects() {}
 void _kern_wait_for_team() {}
 void _kern_wait_for_thread() {}
+void _kern_wait_for_thread_etc() {}
 void _kern_write() {}
 void _kern_write_attr() {}
 void _kern_write_fs_info() {}
@@ -1715,6 +1427,7 @@
 void acquire_sem() {}
 void acquire_sem_etc() {}
 void alarm() {}
+void aligned_alloc() {}
 void alphasort() {}
 void area_for() {}
 void asctime() {}
@@ -1895,6 +1608,7 @@
 void debug_vprintf() {}
 void debugger() {}
 void delete_area() {}
+void delete_driver_settings() {}
 void delete_port() {}
 void delete_sem() {}
 void dev_for_path() {}
@@ -1908,19 +1622,21 @@
 void dlerror() {}
 void dlopen() {}
 void dlsym() {}
+void dprintf() {}
 void drand48() {}
 void drand48_r() {}
 void drem() {}
 void dremf() {}
-void dreml() {}
 void dup() {}
 void dup2() {}
+void duplocale() {}
 void ecvt() {}
 void ecvt_r() {}
 void encrypt() {}
 void endgrent() {}
 void endpwent() {}
 void endspent() {}
+void endutxent() {}
 void erand48() {}
 void erand48_r() {}
 void erf() {}
@@ -1955,7 +1671,6 @@
 void fabsf() {}
 void fabsl() {}
 void faccessat() {}
-void fastiroot() {}
 void fchdir() {}
 void fchmod() {}
 void fchmodat() {}
@@ -1974,16 +1689,13 @@
 void fedisableexcept() {}
 void feenableexcept() {}
 void fegetenv() {}
-void fegetround() {}
 void feholdexcept() {}
 void feof() {}
 void feof_unlocked() {}
 void feraiseexcept() {}
 void ferror() {}
 void ferror_unlocked() {}
-void fesetenv() {}
 void fesetexceptflag() {}
-void fesetround() {}
 void feupdateenv() {}
 void fflush() {}
 void fflush_unlocked() {}
@@ -2048,6 +1760,7 @@
 void fread() {}
 void fread_unlocked() {}
 void free() {}
+void freelocale() {}
 void freopen() {}
 void frexp() {}
 void frexpf() {}
@@ -2108,9 +1821,6 @@
 void fwrite() {}
 void fwrite_unlocked() {}
 void fwscanf() {}
-void gamma() {}
-void gammaf() {}
-void gammal() {}
 void gcvt() {}
 void get_architecture() {}
 void get_architectures() {}
@@ -2175,7 +1885,6 @@
 void getpwuid() {}
 void getpwuid_r() {}
 void getrlimit() {}
-void getrusage() {}
 void gets() {}
 void getsid() {}
 void getspent() {}
@@ -2185,6 +1894,9 @@
 void getsubopt() {}
 void gettimeofday() {}
 void getuid() {}
+void getutxent() {}
+void getutxid() {}
+void getutxline() {}
 void getw() {}
 void getwc() {}
 void getwc_unlocked() {}
@@ -2258,13 +1970,10 @@
 void isxdigit() {}
 void j0() {}
 void j0f() {}
-void j0l() {}
 void j1() {}
 void j1f() {}
-void j1l() {}
 void jn() {}
 void jnf() {}
-void jnl() {}
 void jrand48() {}
 void jrand48_r() {}
 void kill() {}
@@ -2338,7 +2047,6 @@
 void madvise() {}
 void malloc() {}
 void malloc_usable_size() {}
-void matherr() {}
 void mblen() {}
 void mbrlen() {}
 void mbrtowc() {}
@@ -2367,6 +2075,7 @@
 void mkstemps() {}
 void mktemp() {}
 void mktime() {}
+void mlock() {}
 void mmap() {}
 void modf() {}
 void modff() {}
@@ -2380,6 +2089,7 @@
 void msgsnd() {}
 void mstats() {}
 void msync() {}
+void munlock() {}
 void munmap() {}
 void nan() {}
 void nanf() {}
@@ -2388,6 +2098,7 @@
 void nearbyint() {}
 void nearbyintf() {}
 void nearbyintl() {}
+void newlocale() {}
 void next_dev() {}
 void nextafter() {}
 void nextafterf() {}
@@ -2451,6 +2162,7 @@
 void pow10l() {}
 void powf() {}
 void powl() {}
+void ppoll() {}
 void pread() {}
 void printf() {}
 void printf_size() {}
@@ -2482,6 +2194,7 @@
 void pthread_barrierattr_setpshared() {}
 void pthread_cancel() {}
 void pthread_cond_broadcast() {}
+void pthread_cond_clockwait() {}
 void pthread_cond_destroy() {}
 void pthread_cond_init() {}
 void pthread_cond_signal() {}
@@ -2505,6 +2218,7 @@
 void pthread_key_create() {}
 void pthread_key_delete() {}
 void pthread_kill() {}
+void pthread_mutex_clocklock() {}
 void pthread_mutex_destroy() {}
 void pthread_mutex_getprioceiling() {}
 void pthread_mutex_init() {}
@@ -2524,6 +2238,8 @@
 void pthread_mutexattr_setpshared() {}
 void pthread_mutexattr_settype() {}
 void pthread_once() {}
+void pthread_rwlock_clockrdlock() {}
+void pthread_rwlock_clockwrlock() {}
 void pthread_rwlock_destroy() {}
 void pthread_rwlock_init() {}
 void pthread_rwlock_rdlock() {}
@@ -2556,6 +2272,7 @@
 void putchar_unlocked() {}
 void putenv() {}
 void puts() {}
+void pututxline() {}
 void putw() {}
 void putwc() {}
 void putwc_unlocked() {}
@@ -2628,7 +2345,6 @@
 void sbrk() {}
 void scalb() {}
 void scalbf() {}
-void scalbl() {}
 void scalbln() {}
 void scalblnf() {}
 void scalblnl() {}
@@ -2644,6 +2360,7 @@
 void seed48_r() {}
 void seekdir() {}
 void select() {}
+void sem_clockwait() {}
 void sem_close() {}
 void sem_destroy() {}
 void sem_getvalue() {}
@@ -2670,7 +2387,6 @@
 void set_sem_owner() {}
 void set_signal_stack() {}
 void set_thread_priority() {}
-void set_timezone() {}
 void setbuf() {}
 void setbuffer() {}
 void setegid() {}
@@ -2700,6 +2416,7 @@
 void setstate() {}
 void setstate_r() {}
 void setuid() {}
+void setutxent() {}
 void setvbuf() {}
 void sgetspent() {}
 void sgetspent_r() {}
@@ -2707,9 +2424,9 @@
 void shm_unlink() {}
 void sigaltstack() {}
 void siglongjmp() {}
+void signgam() {}
 void significand() {}
 void significandf() {}
-void significandl() {}
 void sigqueue() {}
 void sigsetjmp() {}
 void sigtimedwait() {}
@@ -2739,8 +2456,6 @@
 void srand48_r() {}
 void srandom() {}
 void srandom_r() {}
-void __stack_chk_fail() {}
-void __stack_chk_fail_local() {}
 void sscanf() {}
 void statvfs() {}
 void stime() {}
@@ -2813,9 +2528,11 @@
 void tcflush() {}
 void tcgetattr() {}
 void tcgetpgrp() {}
+void tcgetsid() {}
 void tcsendbreak() {}
 void tcsetattr() {}
 void tcsetpgrp() {}
+void tcsetsid() {}
 void tdelete() {}
 void tdestroy() {}
 void telldir() {}
@@ -2825,6 +2542,14 @@
 void tgamma() {}
 void tgammaf() {}
 void tgammal() {}
+void thrd_create() {}
+void thrd_current() {}
+void thrd_detach() {}
+void thrd_equal() {}
+void thrd_exit() {}
+void thrd_join() {}
+void thrd_sleep() {}
+void thrd_yield() {}
 void time() {}
 void timegm() {}
 void timer_create() {}
@@ -2832,6 +2557,7 @@
 void timer_getoverrun() {}
 void timer_gettime() {}
 void timer_settime() {}
+void timespec_get() {}
 void tls_address() {}
 void tls_allocate() {}
 void tls_get() {}
@@ -2867,6 +2593,7 @@
 void unload_driver_settings() {}
 void unlockpt() {}
 void unsetenv() {}
+void uselocale() {}
 void usleep() {}
 void utime() {}
 void utimensat() {}
@@ -2959,13 +2686,10 @@
 void wscanf() {}
 void y0() {}
 void y0f() {}
-void y0l() {}
 void y1() {}
 void y1f() {}
-void y1l() {}
 void yn() {}
 void ynf() {}
-void ynl() {}

 #include <symbol_versioning.h>

@@ -2975,6 +2699,8 @@
 DEFINE_LIBROOT_KERNEL_SYMBOL_VERSION("__find_directory_alpha4", 
"find_directory@", "BASE");
 DEFINE_LIBROOT_KERNEL_SYMBOL_VERSION("_fstat_current", "fstat@@", "1_ALPHA1");
 DEFINE_LIBROOT_KERNEL_SYMBOL_VERSION("_fstat_beos", "fstat@", "BASE");
+DEFINE_LIBROOT_KERNEL_SYMBOL_VERSION("_getrusage_current", "getrusage@@", 
"1_BETA3");
+DEFINE_LIBROOT_KERNEL_SYMBOL_VERSION("_getrusage_base", "getrusage@", "BASE");
 DEFINE_LIBROOT_KERNEL_SYMBOL_VERSION("_lstat_current", "lstat@@", "1_ALPHA1");
 DEFINE_LIBROOT_KERNEL_SYMBOL_VERSION("_lstat_beos", "lstat@", "BASE");
 DEFINE_LIBROOT_KERNEL_SYMBOL_VERSION("__pselect", "pselect@@", "1_ALPHA4");
diff --git a/src/system/runtime_loader/Jamfile 
b/src/system/runtime_loader/Jamfile
index 99b87e6..372e9e3 100644
--- a/src/system/runtime_loader/Jamfile
+++ b/src/system/runtime_loader/Jamfile
@@ -51,6 +51,7 @@
                        <src!system!libroot!posix!$(architecture)>fcntl.o

                        <src!system!libroot!posix!locale!$(architecture)>ctype.o
+                       
<src!system!libroot!posix!locale!$(architecture)>ctype_loc.o
                        
<src!system!libroot!posix!locale!$(architecture)>LocaleData.o

                        
<src!system!libroot!posix!string!$(architecture)>memchr.o

--
To view, visit https://review.haiku-os.org/c/haiku/+/5351
To unsubscribe, or for help writing mail filters, visit 
https://review.haiku-os.org/settings

Gerrit-Project: haiku
Gerrit-Branch: master
Gerrit-Change-Id: Ibf296c58c47d42d1d1dfb2ce64042442f2679431
Gerrit-Change-Number: 5351
Gerrit-PatchSet: 1
Gerrit-Owner: Trung Nguyen <trungnt282910@xxxxxxxxx>
Gerrit-MessageType: newchange

Other related posts:

  • » [haiku-commits] Change in haiku[master]: libs/posix: Implemented new locale functions - Gerrit