summaryrefslogtreecommitdiff
path: root/arm-riscos-gnueabi/recipes/patches/gccsdk/posix-extended-locale.p
diff options
context:
space:
mode:
Diffstat (limited to 'arm-riscos-gnueabi/recipes/patches/gccsdk/posix-extended-locale.p')
-rw-r--r--arm-riscos-gnueabi/recipes/patches/gccsdk/posix-extended-locale.p1920
1 files changed, 1920 insertions, 0 deletions
diff --git a/arm-riscos-gnueabi/recipes/patches/gccsdk/posix-extended-locale.p b/arm-riscos-gnueabi/recipes/patches/gccsdk/posix-extended-locale.p
new file mode 100644
index 0000000..e422786
--- /dev/null
+++ b/arm-riscos-gnueabi/recipes/patches/gccsdk/posix-extended-locale.p
@@ -0,0 +1,1920 @@
+Index: libunixlib/Makefile.am
+===================================================================
+--- libunixlib/Makefile.am (revision 7698)
++++ libunixlib/Makefile.am (working copy)
+@@ -583,11 +583,11 @@
+ else
+ locale_src = \
+ locale/localeconv.c \
++ locale/newlocale.c \
+ locale/nl_langinfo.c \
+ locale/setlocale.c \
+ locale/strcoll.c \
+- locale/strxfrm.c \
+- locale/territory.c
++ locale/strxfrm.c
+ endif
+ locale_src += \
+ locale/iconv.c
+@@ -1312,6 +1312,7 @@
+ bits/in.h \
+ bits/libc-lock.h \
+ bits/locale.h \
++ bits/locale_t.h \
+ bits/mathcalls.h \
+ bits/mathdef.h \
+ bits/mathinline.h \
+Index: libunixlib/ctype/ctypetable.c
+===================================================================
+--- libunixlib/ctype/ctypetable.c (revision 7698)
++++ libunixlib/ctype/ctypetable.c (working copy)
+@@ -10,36 +10,35 @@
+ #include <internal/os.h>
+ #include <internal/unix.h>
+
+-/* Note the offset 1 and depth 257 instead of 0 and 256: ISO C says we must
+- support EOF. */
+-static unsigned char ctype[257];
+-const unsigned char * const __ctype = &ctype[1];
++/* Global containing current locale settings. */
++struct _locale __locale_global;
++/* Offset 1 as the first entry is reserved for EOF. */
++const unsigned char * const __ctype = &__locale_global.ctype[1];
++const short * const __ctype_upper = &__locale_global.ctype_upper[1];
++const short * const __ctype_lower = &__locale_global.ctype_lower[1];
+
+-static short ctype_upper[257];
+-const short * const __ctype_upper = &ctype_upper[1];
+-
+-static short ctype_lower[257];
+-const short * const __ctype_lower = &ctype_lower[1];
+-
+ void
+-__build_ctype_tables (int territory)
++__build_ctype_tables (locale_t locobj, int territory)
+ {
+ PTHREAD_UNSAFE
+
+ if (territory == -2)
+ {
+- /* Initialise the array. This is only done by __unixinit(). */
++ /* Initialise the array. This is only done by __unixinit()/newlocale(). */
+ territory = -1;
+- for (int x = 0; x <= LC_ALL; x++)
+- __locale_territory[x] = -1;
++ for (int x = 0; x < LC_ALL; x++)
++ locobj->locale_territory[x] = -1;
++ __localeconv_lconv_init(&locobj->lc);
++ locobj->lc_needs_refresh = 1;
+ }
+
+ /* Initialise ctype_upper/ctype_lower tables. */
+ for (int x = 0; x < 257; x++)
+ {
+- /* In the C/POSIX locate, tolower(top bit set char)
++ /* In the C/POSIX locale, tolower(top bit set char)
+ should return the character unchanged. */
+- ctype_lower[x] = ctype_upper[x] = x - 1;
++ locobj->ctype_lower[x] = locobj->ctype_upper[x] = x - 1;
++ locobj->ctype[x] = 0;
+ }
+
+ int regs[10];
+@@ -61,7 +60,7 @@
+ for (int offset = 1; bits; bits = bits >> 1, offset += 1)
+ {
+ if (bits & 1)
+- ctype[pos + offset] |= 1 << code;
++ locobj->ctype[pos + offset] |= 1 << code;
+ }
+ pos += 32;
+ }
+@@ -80,7 +79,7 @@
+ int y = (territory == -1) ? 128 : 256;
+ for (int x = 1; x <= y; x++)
+ {
+- ctype_lower[x] = (short)*p++;
+- ctype_upper[x] = (short)*q++;
++ locobj->ctype_lower[x] = (short)*p++;
++ locobj->ctype_upper[x] = (short)*q++;
+ }
+ }
+Index: libunixlib/ctype/isalnum.c
+===================================================================
+--- libunixlib/ctype/isalnum.c (revision 7698)
++++ libunixlib/ctype/isalnum.c (working copy)
+@@ -3,6 +3,7 @@
+ */
+
+ #include <ctype.h>
++#include <locale.h>
+
+ int
+ (isalnum) (int c)
+@@ -10,3 +11,8 @@
+ return isalnum (c);
+ }
+
++int
++isalnum_l (int c, locale_t locobj)
++{
++ return ((&locobj->ctype[1])[c] & (___ctype_alpha | ___ctype_digit));
++}
+Index: libunixlib/ctype/isalpha.c
+===================================================================
+--- libunixlib/ctype/isalpha.c (revision 7698)
++++ libunixlib/ctype/isalpha.c (working copy)
+@@ -3,6 +3,7 @@
+ */
+
+ #include <ctype.h>
++#include <locale.h>
+
+ int
+ (isalpha) (int c)
+@@ -10,3 +11,8 @@
+ return isalpha (c);
+ }
+
++int
++isalpha_l (int c, locale_t locobj)
++{
++ return ((&locobj->ctype[1])[c] & ___ctype_alpha);
++}
+Index: libunixlib/ctype/isascii.c
+===================================================================
+--- libunixlib/ctype/isascii.c (revision 7698)
++++ libunixlib/ctype/isascii.c (working copy)
+@@ -10,3 +10,9 @@
+ return isascii (c);
+ }
+
++int
++isascii_l (int c, locale_t locobj)
++{
++ (void) locobj;
++ return isascii (c);
++}
+Index: libunixlib/ctype/isblank.c
+===================================================================
+--- libunixlib/ctype/isblank.c (revision 7698)
++++ libunixlib/ctype/isblank.c (working copy)
+@@ -9,3 +9,10 @@
+ {
+ return isblank (c);
+ }
++
++int
++isblank_l (int c, locale_t locobj)
++{
++ (void) locobj;
++ return isblank (c);
++}
+Index: libunixlib/ctype/iscntrl.c
+===================================================================
+--- libunixlib/ctype/iscntrl.c (revision 7698)
++++ libunixlib/ctype/iscntrl.c (working copy)
+@@ -3,6 +3,7 @@
+ */
+
+ #include <ctype.h>
++#include <locale.h>
+
+ int
+ (iscntrl) (int c)
+@@ -10,3 +11,8 @@
+ return iscntrl (c);
+ }
+
++int
++iscntrl_l (int c, locale_t locobj)
++{
++ return ((&locobj->ctype[1])[c] & ___ctype_ctrl);
++}
+Index: libunixlib/ctype/isdigit.c
+===================================================================
+--- libunixlib/ctype/isdigit.c (revision 7698)
++++ libunixlib/ctype/isdigit.c (working copy)
+@@ -3,6 +3,7 @@
+ */
+
+ #include <ctype.h>
++#include <locale.h>
+
+ int
+ (isdigit) (int c)
+@@ -10,3 +11,8 @@
+ return isdigit (c);
+ }
+
++int
++isdigit_l (int c, locale_t locobj)
++{
++ return ((&locobj->ctype[1])[c] & ___ctype_digit);
++}
+Index: libunixlib/ctype/isgraph.c
+===================================================================
+--- libunixlib/ctype/isgraph.c (revision 7698)
++++ libunixlib/ctype/isgraph.c (working copy)
+@@ -3,6 +3,7 @@
+ */
+
+ #include <ctype.h>
++#include <locale.h>
+
+ int
+ (isgraph) (int c)
+@@ -10,3 +11,8 @@
+ return isgraph (c);
+ }
+
++int
++isgraph_l (int c, locale_t locobj)
++{
++ return ((&locobj->ctype[1])[c] & ~(___ctype_white | ___ctype_ctrl));
++}
+Index: libunixlib/ctype/islower.c
+===================================================================
+--- libunixlib/ctype/islower.c (revision 7698)
++++ libunixlib/ctype/islower.c (working copy)
+@@ -3,6 +3,7 @@
+ */
+
+ #include <ctype.h>
++#include <locale.h>
+
+ int
+ (islower) (int c)
+@@ -10,3 +11,8 @@
+ return islower (c);
+ }
+
++int
++islower_l (int c, locale_t locobj)
++{
++ return ((&locobj->ctype[1])[c] & ___ctype_lower);
++}
+Index: libunixlib/ctype/isprint.c
+===================================================================
+--- libunixlib/ctype/isprint.c (revision 7698)
++++ libunixlib/ctype/isprint.c (working copy)
+@@ -3,6 +3,7 @@
+ */
+
+ #include <ctype.h>
++#include <locale.h>
+
+ int
+ (isprint) (int c)
+@@ -10,3 +11,10 @@
+ return isprint (c);
+ }
+
++int
++isprint_l (int c, locale_t locobj)
++{
++ return ((&locobj->ctype[1])[c] &
++ (___ctype_upper | ___ctype_lower | ___ctype_digit | ___ctype_punc |
++ ___ctype_white)) && !((&locobj->ctype[1])[c] & ___ctype_ctrl);
++}
+Index: libunixlib/ctype/ispunct.c
+===================================================================
+--- libunixlib/ctype/ispunct.c (revision 7698)
++++ libunixlib/ctype/ispunct.c (working copy)
+@@ -3,6 +3,7 @@
+ */
+
+ #include <ctype.h>
++#include <locale.h>
+
+ int
+ (ispunct) (int c)
+@@ -10,3 +11,8 @@
+ return ispunct (c);
+ }
+
++int
++ispunct_l (int c, locale_t locobj)
++{
++ return ((&locobj->ctype[1])[c] & ___ctype_punc);
++}
+Index: libunixlib/ctype/isspace.c
+===================================================================
+--- libunixlib/ctype/isspace.c (revision 7698)
++++ libunixlib/ctype/isspace.c (working copy)
+@@ -3,6 +3,7 @@
+ */
+
+ #include <ctype.h>
++#include <locale.h>
+
+ int
+ (isspace) (int c)
+@@ -10,3 +11,8 @@
+ return isspace (c);
+ }
+
++int
++isspace_l (int c, locale_t locobj)
++{
++ return ((&locobj->ctype[1])[c] & ___ctype_white);
++}
+Index: libunixlib/ctype/isupper.c
+===================================================================
+--- libunixlib/ctype/isupper.c (revision 7698)
++++ libunixlib/ctype/isupper.c (working copy)
+@@ -3,6 +3,7 @@
+ */
+
+ #include <ctype.h>
++#include <locale.h>
+
+ int
+ (isupper) (int c)
+@@ -10,3 +11,8 @@
+ return isupper (c);
+ }
+
++int
++isupper_l (int c, locale_t locobj)
++{
++ return ((&locobj->ctype[1])[c] & ___ctype_upper);
++}
+Index: libunixlib/ctype/isxdigit.c
+===================================================================
+--- libunixlib/ctype/isxdigit.c (revision 7698)
++++ libunixlib/ctype/isxdigit.c (working copy)
+@@ -3,6 +3,7 @@
+ */
+
+ #include <ctype.h>
++#include <locale.h>
+
+ int
+ (isxdigit) (int c)
+@@ -10,3 +11,8 @@
+ return isxdigit (c);
+ }
+
++int
++isxdigit_l (int c, locale_t locobj)
++{
++ return ((&locobj->ctype[1])[c] & ___ctype_xdigit);
++}
+Index: libunixlib/ctype/toascii.c
+===================================================================
+--- libunixlib/ctype/toascii.c (revision 7698)
++++ libunixlib/ctype/toascii.c (working copy)
+@@ -10,3 +10,9 @@
+ return toascii (c);
+ }
+
++int
++toascii_l (int c, locale_t locobj)
++{
++ (void) locobj;
++ return toascii (c);
++}
+Index: libunixlib/ctype/tolower.c
+===================================================================
+--- libunixlib/ctype/tolower.c (revision 7698)
++++ libunixlib/ctype/tolower.c (working copy)
+@@ -3,6 +3,7 @@
+ */
+
+ #include <ctype.h>
++#include <locale.h>
+
+ int
+ (tolower) (int c)
+@@ -10,3 +11,8 @@
+ return tolower (c);
+ }
+
++int
++tolower_l (int c, locale_t locobj)
++{
++ return (&locobj->ctype_lower[1])[c];
++}
+Index: libunixlib/ctype/toupper.c
+===================================================================
+--- libunixlib/ctype/toupper.c (revision 7698)
++++ libunixlib/ctype/toupper.c (working copy)
+@@ -3,6 +3,7 @@
+ */
+
+ #include <ctype.h>
++#include <locale.h>
+
+ int
+ (toupper) (int c)
+@@ -10,3 +11,8 @@
+ return toupper (c);
+ }
+
++int
++toupper_l (int c, locale_t locobj)
++{
++ return (&locobj->ctype_upper[1])[c];
++}
+Index: libunixlib/incl-local/locale.h
+===================================================================
+--- libunixlib/incl-local/locale.h (revision 7698)
++++ libunixlib/incl-local/locale.h (working copy)
+@@ -13,15 +13,36 @@
+
+ #ifndef __TARGET_SCL__
+
+-/* Territory number for each locale. C locale is -1. */
+-extern int __locale_territory[LC_ALL + 1];
++struct _locale {
++ /* Map from locale category to territory number. C locale is -1. */
++ int locale_territory[LC_ALL];
+
+-/* Set to 1 is setlocale has been called since the last call to
+- localeconv. localeconv uses this flag to cache the lconv structure. */
+-extern int __setlocale_called;
++ /* Character type LUTs: EOF + one entry per character
++ *
++ * EOF is defined as -1, so character entries start at offset 1.
++ */
++ short ctype_upper[257];
++ short ctype_lower[257];
++ unsigned char ctype[257];
+
+-extern void __build_ctype_tables (int __territory) __THROW;
++ /* Set to 1 if the locale information has changed since the last time
++ * the lconv structure was updated. */
++ int lc_needs_refresh;
++ /* Numeric formatting information for locale */
++ struct lconv lc;
++};
+
++extern struct _locale __locale_global;
++
++extern void __build_ctype_tables (locale_t locobj, int __territory) __THROW;
++
++extern char *__setlocale_l (locale_t locobj, int __category,
++ const char *__locale) __THROW;
++
++void __localeconv_lconv_init (struct lconv *lc);
++void __localeconv_lconv_fini (struct lconv *lc);
++void __localeconv_l (locale_t locobj);
++
+ #endif
+
+ __END_DECLS
+Index: libunixlib/include/bits/locale_t.h
+===================================================================
+--- libunixlib/include/bits/locale_t.h (nonexistent)
++++ libunixlib/include/bits/locale_t.h (working copy)
+@@ -0,0 +1,10 @@
++/*
++ * Copyright (c) 2022 UnixLib Developers
++ */
++
++#ifndef _BITS_LOCALE_T_H_
++#define _BITS_LOCALE_T_H_
++
++typedef struct _locale *locale_t;
++
++#endif
+Index: libunixlib/include/ctype.h
+===================================================================
+--- libunixlib/include/ctype.h (revision 7698)
++++ libunixlib/include/ctype.h (working copy)
+@@ -51,6 +51,48 @@
+ extern int isblank (int __c) __THROW;
+
+ #ifndef __TARGET_SCL__
++# ifdef __USE_XOPEN2K8
++# include <bits/locale_t.h>
++
++/* c is alphabetic or numeric. */
++extern int isalnum_l (int __c, locale_t locobj) __THROW;
++
++/* c is alphabetic. */
++extern int isalpha_l (int __c, locale_t locobj) __THROW;
++
++/* c is a control character. */
++extern int iscntrl_l (int __c, locale_t locobj) __THROW;
++
++/* c is a decimal digit. */
++extern int isdigit_l (int __c, locale_t locobj) __THROW;
++
++/* c is any printable character other than a space. */
++extern int isgraph_l (int __c, locale_t locobj) __THROW;
++
++/* c is a lower-case letter. */
++extern int islower_l (int __c, locale_t locobj) __THROW;
++
++/* c is an upper-case letter. */
++extern int isupper_l (int __c, locale_t locobj) __THROW;
++
++/* c is a printable character. */
++extern int isprint_l (int __c, locale_t locobj) __THROW;
++
++/* c is a printable character other than a space or a
++ alphanumeric character. */
++extern int ispunct_l (int __c, locale_t locobj) __THROW;
++
++/* c is a white space character e.g. space, newline, tab, linefeed,
++ return, vertical tab. */
++extern int isspace_l (int __c, locale_t locobj) __THROW;
++
++/* c is a hex digit. */
++extern int isxdigit_l (int __c, locale_t locobj) __THROW;
++
++/* c is tab or space. */
++extern int isblank_l (int __c, locale_t locobj) __THROW;
++# endif
++
+ /* Characteristics. */
+ extern const unsigned char * const __ctype;
+ /* Lower case table. */
+@@ -108,6 +150,10 @@
+ extern int toupper (int __c) __THROW;
+ #ifndef __TARGET_SCL__
+ # define toupper(c) ((int) __ctype_upper[(int) (c)])
++
++# ifdef __USE_XOPEN2K8
++extern int toupper_l (int __c, locale_t locobj) __THROW;
++# endif
+ #endif
+
+ /* Convert c to lower case. */
+@@ -114,6 +160,10 @@
+ extern int tolower (int __c) __THROW;
+ #ifndef __TARGET_SCL__
+ # define tolower(c) ((int) __ctype_lower[(int) (c)])
++
++# ifdef __USE_XOPEN2K8
++extern int tolower_l (int __c, locale_t locobj) __THROW;
++# endif
+ #endif
+
+ #ifndef __TARGET_SCL__
+@@ -135,6 +185,11 @@
+ /* Is c an ASCII character. */
+ extern int isascii (int __c) __THROW;
+ # define isascii(c) ((unsigned)(c) <= 0x7f)
++
++# ifdef __USE_XOPEN2K8
++extern int toascii_l (int __c, locale_t locobj) __THROW;
++extern int isascii_l (int __c, locale_t locobj) __THROW;
++# endif
+ # endif
+ #endif
+
+Index: libunixlib/include/langinfo.h
+===================================================================
+--- libunixlib/include/langinfo.h (revision 7698)
++++ libunixlib/include/langinfo.h (working copy)
+@@ -580,18 +580,12 @@
+ extern char *nl_langinfo (nl_item __item) __THROW;
+
+
+-#if 0
+-#ifdef __USE_GNU
+-/* This interface is for the extended locale model. See <locale.h> for
+- more information. */
++#ifdef __USE_XOPEN2K8
++# include <bits/locale_t.h>
+
+-/* Get locale datatype definition. */
+-# include <xlocale.h>
+-
+ /* Just like nl_langinfo but get the information from the locale object L. */
+-extern char *nl_langinfo_l (nl_item __item, __locale_t l);
++extern char *nl_langinfo_l (nl_item __item, locale_t __l);
+ #endif
+-#endif
+
+ __END_DECLS
+
+Index: libunixlib/include/locale.h
+===================================================================
+--- libunixlib/include/locale.h (revision 7698)
++++ libunixlib/include/locale.h (working copy)
+@@ -33,16 +33,16 @@
+ /* Entire locale. */
+ # define LC_ALL 6
+
+-#define LC_COLLATE_MASK (1L << 1)
+-#define LC_CTYPE_MASK (1L << 2)
+-#define LC_MESSAGES_MASK (1L << 3)
+-#define LC_MONETARY_MASK (1L << 4)
+-#define LC_NUMERIC_MASK (1L << 5)
+-#define LC_TIME_MASK (1L << 6)
+-#define LC_ALL_MASK (LC_COLLATE_MASK | LC_CTYPE_MASK | LC_MESSAGES_MASK | LC_MONETARY_MASK | LC_NUMERIC_MASK | LC_TIME_MASK)
++# ifdef __USE_XOPEN2K8
++# define LC_COLLATE_MASK (1L << 0)
++# define LC_CTYPE_MASK (1L << 1)
++# define LC_MESSAGES_MASK (1L << 2)
++# define LC_MONETARY_MASK (1L << 3)
++# define LC_NUMERIC_MASK (1L << 4)
++# define LC_TIME_MASK (1L << 5)
++# define LC_ALL_MASK (LC_COLLATE_MASK | LC_CTYPE_MASK | LC_MESSAGES_MASK | LC_MONETARY_MASK | LC_NUMERIC_MASK | LC_TIME_MASK)
++# endif
+
+-typedef struct _locale *locale_t;
+-
+ #else
+ /* String collation (functions 'strcoll' and 'strxfrm'). */
+ # define LC_COLLATE 1
+@@ -121,6 +121,9 @@
+ extern struct lconv *localeconv (void) __THROW;
+
+ #ifndef __TARGET_SCL__
++# ifdef __USE_XOPEN2K8
++# include <bits/locale_t.h>
++
+ extern locale_t uselocale(locale_t newloc);
+
+ extern void freelocale(locale_t locobj);
+@@ -127,7 +130,11 @@
+
+ extern locale_t newlocale(int category_mask, const char *locale,
+ locale_t base);
+-# define LC_GLOBAL_LOCALE ((locale_t) -1L)
++
++extern locale_t duplocale(locale_t locobj);
++
++# define LC_GLOBAL_LOCALE ((locale_t) -1L)
++# endif
+ #endif
+
+ __END_NAMESPACE_STD
+Index: libunixlib/include/string.h
+===================================================================
+--- libunixlib/include/string.h (revision 7698)
++++ libunixlib/include/string.h (working copy)
+@@ -93,6 +93,16 @@
+ const char *__restrict __src, size_t __n)
+ __THROW __nonnull ((2));
+
++#ifdef __USE_XOPEN2K8
++#include <bits/locale_t.h>
++
++extern int strcoll_l (const char *__s1, const char *__s2, locale_t __l)
++ __THROW __attribute_pure__ __nonnull ((1, 2, 3));
++
++extern size_t strxfrm_l (char *__dest, const char *__src, size_t __n,
++ locale_t __l) __THROW __nonnull ((2, 4));
++#endif
++
+ /* Find the first occurrence of c in s. */
+ extern char *strchr (const char *__s, int __c)
+ __THROW __attribute_pure__ __nonnull ((1)) __wur;
+@@ -281,6 +291,17 @@
+ /* Compare no more than N chars of S1 and S2, ignoring case. */
+ extern int strncasecmp (const char *__s1, const char *__s2, size_t __n)
+ __THROW __attribute_pure__ __nonnull ((1, 2)) __wur;
++
++# ifdef __USE_XOPEN2K8
++# include <bits/locale_t.h>
++
++extern int strcasecmp_l (const char *__s1, const char *__s2, locale_t __loc)
++ __THROW __attribute_pure__ __nonnull ((1, 2, 3));
++
++extern int strncasecmp_l (const char *__s1, const char *__s2,
++ size_t __n, locale_t __loc)
++ __THROW __attribute_pure__ __nonnull ((1, 2, 4));
++# endif
+ #endif /* Use BSD. */
+
+ #if defined __USE_XOPEN2K || defined __USE_MISC
+@@ -289,6 +310,11 @@
+ __THROW __nonnull ((2));
+ #endif
+
++#ifdef __USE_XOPEN2K8
++/* Translate error number to string according to the locale L. */
++extern char *strerror_l (int __errnum, locale_t __l) __THROW;
++#endif
++
+ #ifndef __TARGET_SCL__
+ # ifndef basename
+ /* Return the file name within directory of FILENAME. We don't
+Index: libunixlib/include/strings.h
+===================================================================
+--- libunixlib/include/strings.h (revision 7698)
++++ libunixlib/include/strings.h (working copy)
+@@ -37,7 +37,17 @@
+ /* Compare n chars of S1 and S2, ignoring case. */
+ extern int strncasecmp (const char *__s1, const char *__s2, size_t __n);
+
++# ifdef __USE_XOPEN2K8
++# include <bits/locale_t.h>
+
++extern int strcasecmp_l (const char *__s1, const char *__s2, locale_t __loc)
++ __THROW __attribute_pure__ __nonnull ((1, 2, 3));
++
++extern int strncasecmp_l (const char *__s1, const char *__s2,
++ size_t __n, locale_t __loc)
++ __THROW __attribute_pure__ __nonnull ((1, 2, 4));
++# endif
++
+ /* Return the position of the first bit set in I, or 0 if none are set.
+ The least-significant bit is position 1, the most-significant 32. */
+ extern int ffs (int __i);
+Index: libunixlib/include/wchar.h
+===================================================================
+--- libunixlib/include/wchar.h (revision 7698)
++++ libunixlib/include/wchar.h (working copy)
+@@ -1,7 +1,7 @@
+ /*
+ * File taken from glibc 2.11.
+ * Following changes were made:
+- * - Disabled non-standard reentrant locale prototypes.
++ * - None
+ */
+
+ /* Copyright (C) 1995-2008, 2009 Free Software Foundation, Inc.
+@@ -172,7 +172,6 @@
+ __END_NAMESPACE_STD
+ #endif
+
+-#if 0
+ #ifdef __USE_XOPEN2K8
+ /* Compare S1 and S2, ignoring case. */
+ extern int wcscasecmp (__const wchar_t *__s1, __const wchar_t *__s2) __THROW;
+@@ -183,15 +182,14 @@
+
+ /* Similar to the two functions above but take the information from
+ the provided locale and not the global locale. */
+-# include <xlocale.h>
++# include <bits/locale_t.h>
+
+ extern int wcscasecmp_l (__const wchar_t *__s1, __const wchar_t *__s2,
+- __locale_t __loc) __THROW;
++ locale_t __loc) __THROW;
+
+ extern int wcsncasecmp_l (__const wchar_t *__s1, __const wchar_t *__s2,
+- size_t __n, __locale_t __loc) __THROW;
++ size_t __n, locale_t __loc) __THROW;
+ #endif
+-#endif
+
+ __BEGIN_NAMESPACE_STD
+ /* Compare S1 and S2, both interpreted as appropriate to the
+@@ -205,7 +203,6 @@
+ __END_NAMESPACE_STD
+
+ #ifdef __USE_XOPEN2K8
+-#if 0
+ /* Similar to the two functions above but take the information from
+ the provided locale and not the global locale. */
+
+@@ -212,14 +209,13 @@
+ /* Compare S1 and S2, both interpreted as appropriate to the
+ LC_COLLATE category of the given locale. */
+ extern int wcscoll_l (__const wchar_t *__s1, __const wchar_t *__s2,
+- __locale_t __loc) __THROW;
++ locale_t __loc) __THROW;
+
+ /* Transform S2 into array pointed to by S1 such that if wcscmp is
+ applied to two transformed strings the result is the as applying
+ `wcscoll' to the original strings. */
+ extern size_t wcsxfrm_l (wchar_t *__s1, __const wchar_t *__s2,
+- size_t __n, __locale_t __loc) __THROW;
+-#endif
++ size_t __n, locale_t __loc) __THROW;
+
+ #ifndef __TARGET_SCL__
+ /* Duplicate S, returning an identical malloc'd string. */
+Index: libunixlib/include/wctype.h
+===================================================================
+--- libunixlib/include/wctype.h (revision 7698)
++++ libunixlib/include/wctype.h (working copy)
+@@ -3,7 +3,6 @@
+ * Following changes were made:
+ * - Replaced "#include <bits/types.h>" into "#include <unixlib/types.h>"
+ * - Add wint_t typedef when it hasn't been defined in stddef.h.
+- * - Disabled non-standard reentrant locale prototypes.
+ */
+
+ /* Copyright (C) 1996-2002,2005,2007,2008,2009 Free Software Foundation, Inc.
+@@ -191,7 +190,6 @@
+ /* Determine whether the wide-character WC has the property described by
+ DESC. */
+ extern int iswctype (wint_t __wc, wctype_t __desc) __THROW;
+-#define iswctype_l(c, d, l) iswctype(c, d)
+
+ __END_NAMESPACE_C99
+
+@@ -241,73 +239,71 @@
+ extern wint_t towctrans (wint_t __wc, wctrans_t __desc) __THROW;
+ __END_NAMESPACE_C99
+
+-#if 0
+ # ifdef __USE_XOPEN2K8
+-/* Declare the interface to extended locale model. */
+-# include <xlocale.h>
++# include <bits/locale_t.h>
+
+ /* Test for any wide character for which `iswalpha' or `iswdigit' is
+ true. */
+-extern int iswalnum_l (wint_t __wc, __locale_t __locale) __THROW;
++extern int iswalnum_l (wint_t __wc, locale_t __locale) __THROW;
+
+ /* Test for any wide character for which `iswupper' or 'iswlower' is
+ true, or any wide character that is one of a locale-specific set of
+ wide-characters for which none of `iswcntrl', `iswdigit',
+ `iswpunct', or `iswspace' is true. */
+-extern int iswalpha_l (wint_t __wc, __locale_t __locale) __THROW;
++extern int iswalpha_l (wint_t __wc, locale_t __locale) __THROW;
+
+ /* Test for any control wide character. */
+-extern int iswcntrl_l (wint_t __wc, __locale_t __locale) __THROW;
++extern int iswcntrl_l (wint_t __wc, locale_t __locale) __THROW;
+
+ /* Test for any wide character that corresponds to a decimal-digit
+ character. */
+-extern int iswdigit_l (wint_t __wc, __locale_t __locale) __THROW;
++extern int iswdigit_l (wint_t __wc, locale_t __locale) __THROW;
+
+ /* Test for any wide character for which `iswprint' is true and
+ `iswspace' is false. */
+-extern int iswgraph_l (wint_t __wc, __locale_t __locale) __THROW;
++extern int iswgraph_l (wint_t __wc, locale_t __locale) __THROW;
+
+ /* Test for any wide character that corresponds to a lowercase letter
+ or is one of a locale-specific set of wide characters for which
+ none of `iswcntrl', `iswdigit', `iswpunct', or `iswspace' is true. */
+-extern int iswlower_l (wint_t __wc, __locale_t __locale) __THROW;
++extern int iswlower_l (wint_t __wc, locale_t __locale) __THROW;
+
+ /* Test for any printing wide character. */
+-extern int iswprint_l (wint_t __wc, __locale_t __locale) __THROW;
++extern int iswprint_l (wint_t __wc, locale_t __locale) __THROW;
+
+ /* Test for any printing wide character that is one of a
+ locale-specific et of wide characters for which neither `iswspace'
+ nor `iswalnum' is true. */
+-extern int iswpunct_l (wint_t __wc, __locale_t __locale) __THROW;
++extern int iswpunct_l (wint_t __wc, locale_t __locale) __THROW;
+
+ /* Test for any wide character that corresponds to a locale-specific
+ set of wide characters for which none of `iswalnum', `iswgraph', or
+ `iswpunct' is true. */
+-extern int iswspace_l (wint_t __wc, __locale_t __locale) __THROW;
++extern int iswspace_l (wint_t __wc, locale_t __locale) __THROW;
+
+ /* Test for any wide character that corresponds to an uppercase letter
+ or is one of a locale-specific set of wide character for which none
+ of `iswcntrl', `iswdigit', `iswpunct', or `iswspace' is true. */
+-extern int iswupper_l (wint_t __wc, __locale_t __locale) __THROW;
++extern int iswupper_l (wint_t __wc, locale_t __locale) __THROW;
+
+ /* Test for any wide character that corresponds to a hexadecimal-digit
+ character equivalent to that performed be the functions described
+ in the previous subclause. */
+-extern int iswxdigit_l (wint_t __wc, __locale_t __locale) __THROW;
++extern int iswxdigit_l (wint_t __wc, locale_t __locale) __THROW;
+
+ /* Test for any wide character that corresponds to a standard blank
+ wide character or a locale-specific set of wide characters for
+ which `iswalnum' is false. */
+-extern int iswblank_l (wint_t __wc, __locale_t __locale) __THROW;
++extern int iswblank_l (wint_t __wc, locale_t __locale) __THROW;
+
+ /* Construct value that describes a class of wide characters identified
+ by the string argument PROPERTY. */
+-extern wctype_t wctype_l (__const char *__property, __locale_t __locale)
++extern wctype_t wctype_l (__const char *__property, locale_t __locale)
+ __THROW;
+
+ /* Determine whether the wide-character WC has the property described by
+ DESC. */
+-extern int iswctype_l (wint_t __wc, wctype_t __desc, __locale_t __locale)
++extern int iswctype_l (wint_t __wc, wctype_t __desc, locale_t __locale)
+ __THROW;
+
+
+@@ -316,22 +312,21 @@
+ */
+
+ /* Converts an uppercase letter to the corresponding lowercase letter. */
+-extern wint_t towlower_l (wint_t __wc, __locale_t __locale) __THROW;
++extern wint_t towlower_l (wint_t __wc, locale_t __locale) __THROW;
+
+ /* Converts an lowercase letter to the corresponding uppercase letter. */
+-extern wint_t towupper_l (wint_t __wc, __locale_t __locale) __THROW;
++extern wint_t towupper_l (wint_t __wc, locale_t __locale) __THROW;
+
+ /* Construct value that describes a mapping between wide characters
+ identified by the string argument PROPERTY. */
+-extern wctrans_t wctrans_l (__const char *__property, __locale_t __locale)
++extern wctrans_t wctrans_l (__const char *__property, locale_t __locale)
+ __THROW;
+
+ /* Map the wide character WC using the mapping described by DESC. */
+ extern wint_t towctrans_l (wint_t __wc, wctrans_t __desc,
+- __locale_t __locale) __THROW;
++ locale_t __locale) __THROW;
+
+ # endif /* Use POSIX 2008. */
+-#endif
+
+ __END_DECLS
+
+Index: libunixlib/locale/localeconv.c
+===================================================================
+--- libunixlib/locale/localeconv.c (revision 7698)
++++ libunixlib/locale/localeconv.c (working copy)
+@@ -14,8 +14,6 @@
+
+ /* #define DEBUG */
+
+-int __setlocale_called = 1;
+-
+ static int
+ read_symbol (int reason_code, int territory)
+ {
+@@ -71,26 +69,44 @@
+ *grouping = new_grouping;
+ }
+
+-static struct lconv lc = { NULL, NULL, NULL, NULL, NULL,
+- NULL, NULL, NULL, NULL, NULL,
+- CHAR_MAX, CHAR_MAX, CHAR_MAX, CHAR_MAX,
+- CHAR_MAX, CHAR_MAX, CHAR_MAX, CHAR_MAX };
++void
++__localeconv_lconv_init (struct lconv *lc)
++{
++ memset(lc, 0, sizeof(*lc));
++ lc->int_frac_digits = lc->frac_digits = lc->p_cs_precedes =
++ lc->p_sep_by_space = lc->n_cs_precedes = lc->n_sep_by_space =
++ lc->p_sign_posn = lc->n_sign_posn = CHAR_MAX;
++}
+
+-/* Defined by POSIX as not threadsafe */
+-struct lconv *
+-localeconv (void)
++void
++__localeconv_lconv_fini (struct lconv *lc)
+ {
++ free(lc->decimal_point);
++ free(lc->thousands_sep);
++ free(lc->grouping);
++ free(lc->int_curr_symbol);
++ free(lc->currency_symbol);
++ free(lc->mon_decimal_point);
++ free(lc->mon_thousands_sep);
++ free(lc->mon_grouping);
++ free(lc->positive_sign);
++ free(lc->negative_sign);
++}
++
++void
++__localeconv_l (locale_t locobj)
++{
+ int numeric, monetary;
+
+ /* If setlocale has not been called since the last call to
+ localeconv, then the lconv structure will be the same. */
+- if (!__setlocale_called)
+- return &lc;
++ if (!locobj->lc_needs_refresh)
++ return;
+
+- __setlocale_called = 0;
++ locobj->lc_needs_refresh = 0;
+
+- numeric = __locale_territory[LC_NUMERIC];
+- monetary = __locale_territory[LC_MONETARY];
++ numeric = locobj->locale_territory[LC_NUMERIC];
++ monetary = locobj->locale_territory[LC_MONETARY];
+
+ /* See the PRMs regarding SWI Territory_ReadSymbols for the
+ meanings of the following numbers. */
+@@ -97,71 +113,80 @@
+ if (numeric == -1)
+ {
+ /* We're using the 'C' locale. */
+- free (lc.decimal_point);
+- lc.decimal_point = strdup (".");
+- free (lc.thousands_sep);
+- lc.thousands_sep = strdup ("");
+- free (lc.grouping);
+- lc.grouping = strdup ("");
++ free (locobj->lc.decimal_point);
++ locobj->lc.decimal_point = strdup (".");
++ free (locobj->lc.thousands_sep);
++ locobj->lc.thousands_sep = strdup ("");
++ free (locobj->lc.grouping);
++ locobj->lc.grouping = strdup ("");
+ }
+ else
+ {
+- free (lc.decimal_point);
+- lc.decimal_point = strdup ((char *) read_symbol (0, numeric));
+- free (lc.thousands_sep);
+- lc.thousands_sep = strdup ((char *) read_symbol (1, numeric));
+- read_byte_list (2, &lc.grouping, numeric);
++ free (locobj->lc.decimal_point);
++ locobj->lc.decimal_point = strdup ((char *) read_symbol (0, numeric));
++ free (locobj->lc.thousands_sep);
++ locobj->lc.thousands_sep = strdup ((char *) read_symbol (1, numeric));
++ read_byte_list (2, &locobj->lc.grouping, numeric);
+ }
+ if (monetary == -1)
+ {
+ /* We using the 'C' locale. Empty strings and CHAR_MAX means
+ that these fields are unspecified. */
+- free (lc.mon_decimal_point);
+- lc.mon_decimal_point = strdup ("");
+- free (lc.mon_thousands_sep);
+- lc.mon_thousands_sep = strdup ("");
+- free (lc.mon_grouping);
+- lc.mon_grouping = strdup ("");
+- lc.int_frac_digits = CHAR_MAX;
+- lc.frac_digits = CHAR_MAX;
+- free (lc.currency_symbol);
+- lc.currency_symbol = strdup ("");
+- free (lc.int_curr_symbol);
+- lc.int_curr_symbol = strdup ("");
+- lc.p_cs_precedes = CHAR_MAX;
+- lc.n_cs_precedes = CHAR_MAX;
+- lc.p_sep_by_space = CHAR_MAX;
+- lc.n_sep_by_space = CHAR_MAX;
+- free (lc.positive_sign);
+- lc.positive_sign = strdup ("");
+- free (lc.negative_sign);
+- lc.negative_sign = strdup ("");
+- lc.p_sign_posn = CHAR_MAX;
+- lc.n_sign_posn = CHAR_MAX;
++ free (locobj->lc.mon_decimal_point);
++ locobj->lc.mon_decimal_point = strdup ("");
++ free (locobj->lc.mon_thousands_sep);
++ locobj->lc.mon_thousands_sep = strdup ("");
++ free (locobj->lc.mon_grouping);
++ locobj->lc.mon_grouping = strdup ("");
++ locobj->lc.int_frac_digits = CHAR_MAX;
++ locobj->lc.frac_digits = CHAR_MAX;
++ free (locobj->lc.currency_symbol);
++ locobj->lc.currency_symbol = strdup ("");
++ free (locobj->lc.int_curr_symbol);
++ locobj->lc.int_curr_symbol = strdup ("");
++ locobj->lc.p_cs_precedes = CHAR_MAX;
++ locobj->lc.n_cs_precedes = CHAR_MAX;
++ locobj->lc.p_sep_by_space = CHAR_MAX;
++ locobj->lc.n_sep_by_space = CHAR_MAX;
++ free (locobj->lc.positive_sign);
++ locobj->lc.positive_sign = strdup ("");
++ free (locobj->lc.negative_sign);
++ locobj->lc.negative_sign = strdup ("");
++ locobj->lc.p_sign_posn = CHAR_MAX;
++ locobj->lc.n_sign_posn = CHAR_MAX;
+ }
+ else
+ {
+- free (lc.int_curr_symbol);
+- lc.int_curr_symbol = strdup ((char *)read_symbol (3, monetary));
+- free (lc.currency_symbol);
+- lc.currency_symbol = strdup ((char *)read_symbol (4, monetary));
+- free (lc.mon_decimal_point);
+- lc.mon_decimal_point = strdup ((char *)read_symbol (5, monetary));
+- free (lc.mon_thousands_sep);
+- lc.mon_thousands_sep = strdup ((char *)read_symbol (6, monetary));
+- read_byte_list (7, &lc.mon_grouping, monetary);
+- free (lc.positive_sign);
+- lc.positive_sign = strdup ((char *)read_symbol (8, monetary));
+- free (lc.negative_sign);
+- lc.negative_sign = strdup ((char *)read_symbol (9, monetary));
+- lc.int_frac_digits = (char)read_symbol (10, monetary);
+- lc.frac_digits = (char)read_symbol (11, monetary);
+- lc.p_cs_precedes = (char)read_symbol (12, monetary);
+- lc.p_sep_by_space = (char)read_symbol (13, monetary);
+- lc.n_cs_precedes = (char)read_symbol (14, monetary);
+- lc.n_sep_by_space = (char)read_symbol (15, monetary);
+- lc.p_sign_posn = (char)read_symbol (16, monetary);
+- lc.n_sign_posn = (char)read_symbol (17, monetary);
++ free (locobj->lc.int_curr_symbol);
++ locobj->lc.int_curr_symbol = strdup ((char *)read_symbol (3, monetary));
++ free (locobj->lc.currency_symbol);
++ locobj->lc.currency_symbol = strdup ((char *)read_symbol (4, monetary));
++ free (locobj->lc.mon_decimal_point);
++ locobj->lc.mon_decimal_point = strdup ((char *)read_symbol (5, monetary));
++ free (locobj->lc.mon_thousands_sep);
++ locobj->lc.mon_thousands_sep = strdup ((char *)read_symbol (6, monetary));
++ read_byte_list (7, &locobj->lc.mon_grouping, monetary);
++ free (locobj->lc.positive_sign);
++ locobj->lc.positive_sign = strdup ((char *)read_symbol (8, monetary));
++ free (locobj->lc.negative_sign);
++ locobj->lc.negative_sign = strdup ((char *)read_symbol (9, monetary));
++ locobj->lc.int_frac_digits = (char)read_symbol (10, monetary);
++ locobj->lc.frac_digits = (char)read_symbol (11, monetary);
++ locobj->lc.p_cs_precedes = (char)read_symbol (12, monetary);
++ locobj->lc.p_sep_by_space = (char)read_symbol (13, monetary);
++ locobj->lc.n_cs_precedes = (char)read_symbol (14, monetary);
++ locobj->lc.n_sep_by_space = (char)read_symbol (15, monetary);
++ locobj->lc.p_sign_posn = (char)read_symbol (16, monetary);
++ locobj->lc.n_sign_posn = (char)read_symbol (17, monetary);
+ }
+- return &lc;
++ return;
+ }
++
++/* Defined by POSIX as not threadsafe */
++struct lconv *
++localeconv (void)
++{
++ __localeconv_l (&__locale_global);
++
++ return &__locale_global.lc;
++}
+Index: libunixlib/locale/newlocale.c
+===================================================================
+--- libunixlib/locale/newlocale.c (revision 7698)
++++ libunixlib/locale/newlocale.c (working copy)
+@@ -1,17 +1,17 @@
+ /* Copyright (c) 2019 UnixLib Developers
+ */
+
++#include <ctype.h>
++#include <errno.h>
++#include <locale.h>
+ #include <stdlib.h>
+-#include <locale.h>
+ #include <stdio.h>
+-#include <errno.h>
++#include <string.h>
+
+-struct _locale {
+- struct lconv lc;
+-};
++#include <internal/unix.h>
+
+ /* This is supposed to be per-thread. */
+-static locale_t current_locale;
++static locale_t current_locale = LC_GLOBAL_LOCALE;
+
+ locale_t uselocale(locale_t newloc)
+ {
+@@ -27,20 +27,94 @@
+
+ void freelocale(locale_t locobj)
+ {
+- if (locobj)
++ if (locobj) {
++ __localeconv_lconv_fini(&locobj->lc);
+ free(locobj);
++ }
+ }
+
+ locale_t newlocale(int category_mask, const char *locale,
+ locale_t base)
+ {
+- locale_t loc = (locale_t)malloc(sizeof(*loc));
+- if (!loc) {
++ struct _locale tmp;
++
++ PTHREAD_UNSAFE
++
++ if ((category_mask & ~LC_ALL_MASK) || locale == NULL) {
++ __set_errno (EINVAL);
++ return 0;
++ }
++
++ /* The locale provided will be verified by __setlocale_l() */
++
++ /* Prepare the temporary locale we will modify */
++ if (base != 0 && base != LC_GLOBAL_LOCALE) {
++ memcpy(&tmp, base, sizeof(tmp));
++ } else {
++ if (base == LC_GLOBAL_LOCALE) {
++ /* Undefined: be helpful to client */
++ memcpy(&tmp, &__locale_global, sizeof(tmp));
++ } else {
++ /* Initialise to C locale */
++ __build_ctype_tables(&tmp, -2);
++ }
++ }
++
++ /* Now, apply the requested locale to each of the categories in the mask */
++ if (category_mask == LC_ALL_MASK) {
++ /* Special-case LC_ALL to handle the encoded locale string */
++ if (__setlocale_l(&tmp, LC_ALL, locale) == NULL) {
++ return 0;
++ }
++ } else {
++ int category = 0, mask = category_mask;
++ while (mask != 0) {
++ if (mask & 1) {
++ if (__setlocale_l(&tmp, category, locale) == NULL) {
++ return 0;
++ }
++ }
++ category++;
++ mask >>= 1;
++ }
++ }
++
++ /* Allocate the result, if necessary */
++ if (base == 0 || base == LC_GLOBAL_LOCALE) {
++ base = (locale_t)malloc(sizeof(*base));
++ if (!base) {
++ __set_errno (ENOMEM);
++ return 0;
++ }
++ }
++ /* Fill it in */
++ memcpy(base, &tmp, sizeof(tmp));
++
++ /* Mark the lconv data stale */
++ base->lc_needs_refresh = 1;
++
++ return base;
++}
++
++locale_t duplocale(locale_t locobj)
++{
++ locale_t loc;
++
++ loc = (locale_t) malloc(sizeof(*loc));
++ if (loc == NULL) {
+ __set_errno (ENOMEM);
+ return 0;
+ }
+
+- loc->lc = *localeconv();
++ if (locobj == LC_GLOBAL_LOCALE) {
++ memcpy(loc, &__locale_global, sizeof(*loc));
++ } else {
++ memcpy(loc, locobj, sizeof(*loc));
++ }
+
++ /* Invalidate lconv in the copy */
++ __localeconv_lconv_init(&loc->lc);
++ loc->lc_needs_refresh = 1;
++
+ return loc;
+ }
+Index: libunixlib/locale/nl_langinfo.c
+===================================================================
+--- libunixlib/locale/nl_langinfo.c (revision 7698)
++++ libunixlib/locale/nl_langinfo.c (working copy)
+@@ -24,3 +24,10 @@
+
+ return (char *)value;
+ }
++
++char *
++nl_langinfo_l (nl_item item, locale_t l)
++{
++ (void) l;
++ return nl_langinfo(item);
++}
+Index: libunixlib/locale/setlocale.c
+===================================================================
+--- libunixlib/locale/setlocale.c (revision 7698)
++++ libunixlib/locale/setlocale.c (working copy)
+@@ -195,7 +195,7 @@
+ }
+
+ static void
+-do_lc_all (char *buffer, int size)
++do_lc_all (locale_t locobj, char *buffer, int size)
+ {
+ char temp[64];
+ int category, same = 1;
+@@ -204,13 +204,13 @@
+ setlocale to set all locales. If all locales are
+ the same, then we can produce a very short string. */
+ for (category = 1; category < LC_ALL; ++category)
+- if (__locale_territory[0] != __locale_territory[category])
++ if (locobj->locale_territory[0] != locobj->locale_territory[category])
+ same = 0;
+
+ if (same)
+ {
+ /* All locales are set to the same territory. */
+- territory_name (__locale_territory[0], buffer, size);
++ territory_name (locobj->locale_territory[0], buffer, size);
+ }
+ else
+ {
+@@ -218,7 +218,7 @@
+ LC_CATEGORY=country;LC_CATEGORY=country; ... */
+ for (category = 0; category < LC_ALL; ++category)
+ {
+- territory_name (__locale_territory[category], temp, sizeof (temp));
++ territory_name (locobj->locale_territory[category], temp, sizeof (temp));
+ buffer = stpcpy (buffer, locale_names[category]);
+ *buffer++ = '=';
+ buffer = stpcpy (buffer, temp);
+@@ -230,15 +230,13 @@
+ }
+
+ char *
+-setlocale (int category, const char *locale)
++__setlocale_l (locale_t locobj, int category, const char *locale)
+ {
+ int new_territory, changed;
+ static char old_locale[256];
+
+- PTHREAD_UNSAFE
+-
+ /* This tells localeconv to re-read data for the lconv structure. */
+- __setlocale_called = 1;
++ locobj->lc_needs_refresh = 1;
+
+ if (locale == NULL)
+ {
+@@ -247,11 +245,11 @@
+ {
+ /* The locale string is specially encoded for LC_ALL so we
+ could restore all locales at any time. */
+- do_lc_all (old_locale, sizeof (old_locale));
++ do_lc_all (locobj, old_locale, sizeof (old_locale));
+ return old_locale;
+ }
+
+- territory_name (__locale_territory[category], old_locale, sizeof (old_locale));
++ territory_name (locobj->locale_territory[category], old_locale, sizeof (old_locale));
+ return old_locale;
+ }
+
+@@ -270,7 +268,7 @@
+ /* Encode the locale string, as we will be returning this
+ later. Remember, setlocale returns the locale settings
+ that are about to be changed. */
+- do_lc_all (old_locale, sizeof (old_locale));
++ do_lc_all (locobj, old_locale, sizeof (old_locale));
+
+ /* Check for an encoded (composite) name. Simply looking for
+ a semi-colon will verify this. */
+@@ -332,11 +330,11 @@
+
+ /* We now know all locales exist, so set them. */
+ for (category = 0; category < LC_ALL; ++category)
+- __locale_territory[category] = territory_number (newnames[category]);
++ locobj->locale_territory[category] = territory_number (newnames[category]);
+
+ /* Re-build the character type tables according to the new
+ locale settings. */
+- __build_ctype_tables (__locale_territory[LC_CTYPE]);
++ __build_ctype_tables (locobj, locobj->locale_territory[LC_CTYPE]);
+ return old_locale;
+ }
+ }
+@@ -359,9 +357,9 @@
+ /* Change the locale for all categories. old_locale was created
+ when we previously checked for a composite string. */
+ for (category = 0; category < LC_ALL; ++category)
+- if (__locale_territory[category] != new_territory)
++ if (locobj->locale_territory[category] != new_territory)
+ {
+- __locale_territory[category] = new_territory;
++ locobj->locale_territory[category] = new_territory;
+ changed = 1;
+ }
+ }
+@@ -368,12 +366,12 @@
+ else
+ {
+ /* Change the locale for just one category. */
+- territory_name (__locale_territory[category],
++ territory_name (locobj->locale_territory[category],
+ old_locale, sizeof (old_locale));
+
+- if (__locale_territory[category] != new_territory)
++ if (locobj->locale_territory[category] != new_territory)
+ {
+- __locale_territory[category] = new_territory;
++ locobj->locale_territory[category] = new_territory;
+ changed = 1;
+ }
+ }
+@@ -384,7 +382,16 @@
+ is changing. The GNU Java compiler is known to repeatedly call
+ setlocale. */
+ if (changed && (category == LC_ALL || category == LC_CTYPE))
+- __build_ctype_tables (new_territory);
++ __build_ctype_tables (locobj, new_territory);
+
+ return old_locale;
+ }
++
++char *
++setlocale (int category, const char *locale)
++{
++
++ PTHREAD_UNSAFE
++
++ return __setlocale_l(&__locale_global, category, locale);
++}
+Index: libunixlib/locale/strcoll.c
+===================================================================
+--- libunixlib/locale/strcoll.c (revision 7698)
++++ libunixlib/locale/strcoll.c (working copy)
+@@ -11,9 +11,15 @@
+ int
+ strcoll (const char *s1, const char *s2)
+ {
++ return strcoll_l (s1, s2, &__locale_global);
++}
++
++int
++strcoll_l (const char *s1, const char *s2, locale_t l)
++{
+ int regs[10];
+
+- regs[0] = __locale_territory[LC_COLLATE];
++ regs[0] = l->locale_territory[LC_COLLATE];
+ regs[1] = (int)s1;
+ regs[2] = (int)s2;
+ regs[3] = 0;
+@@ -21,3 +27,4 @@
+ __os_swi (Territory_Collate, regs);
+ return regs[0];
+ }
++
+Index: libunixlib/locale/strxfrm.c
+===================================================================
+--- libunixlib/locale/strxfrm.c (revision 7698)
++++ libunixlib/locale/strxfrm.c (working copy)
+@@ -11,9 +11,15 @@
+ size_t
+ strxfrm (char *to, const char *from, size_t size)
+ {
++ return strxfrm_l (to, from, size, &__locale_global);
++}
++
++size_t
++strxfrm_l (char *to, const char *from, size_t size, locale_t l)
++{
+ int regs[10];
+
+- regs[0] = __locale_territory[LC_COLLATE];
++ regs[0] = l->locale_territory[LC_COLLATE];
+ regs[1] = (int)to;
+ regs[2] = (int)from;
+ regs[3] = size;
+Index: libunixlib/locale/territory.c
+===================================================================
+--- libunixlib/locale/territory.c (revision 7698)
++++ libunixlib/locale/territory.c (nonexistent)
+@@ -1,10 +0,0 @@
+-/* __locale_territory
+- * Copyright (c) 2000-2006 UnixLib Developers
+- */
+-
+-#include <locale.h>
+-
+-/* Global used for all calls to the Territory module. These variable
+- contain the territory number as set by setlocale. A value of
+- -1 means use the C locale. */
+-int __locale_territory[LC_ALL + 1];
+Index: libunixlib/string/stricmp.c
+===================================================================
+--- libunixlib/string/stricmp.c (revision 7698)
++++ libunixlib/string/stricmp.c (working copy)
+@@ -4,6 +4,7 @@
+ #include <string.h>
+ #include <strings.h>
+ #include <ctype.h>
++#include <locale.h>
+
+ int
+ stricmp (const char *s1, const char *s2)
+@@ -26,3 +27,24 @@
+ return result;
+ }
+ strong_alias (stricmp, strcasecmp)
++
++int
++strcasecmp_l (const char *s1, const char *s2, locale_t locobj)
++{
++ const unsigned char *p1 = (const unsigned char *) s1;
++ const unsigned char *p2 = (const unsigned char *) s2;
++ int result = 0;
++
++ if (p1 == p2)
++ return result;
++
++ while (! result)
++ {
++ result = tolower_l (*p1, locobj) - tolower_l (*p2, locobj);
++ if (*p1++ == '\0')
++ break;
++ p2 ++;
++ }
++
++ return result;
++}
+Index: libunixlib/string/strnicmp.c
+===================================================================
+--- libunixlib/string/strnicmp.c (revision 7698)
++++ libunixlib/string/strnicmp.c (working copy)
+@@ -5,6 +5,7 @@
+ #include <string.h>
+ #include <strings.h>
+ #include <ctype.h>
++#include <locale.h>
+
+ int
+ strnicmp (const char *s1, const char *s2, size_t n)
+@@ -26,3 +27,22 @@
+ }
+ strong_alias (strnicmp, strncasecmp)
+
++int
++strncasecmp_l (const char *s1, const char *s2, size_t n, locale_t locobj)
++{
++ int i, j;
++
++ if (!n)
++ return 0;
++
++ do
++ {
++ i = *s1++, j = *s2++;
++ i = tolower_l (i, locobj);
++ j = tolower_l (j, locobj);
++ }
++ while (i && i == j && --n);
++
++ return i - j;
++}
++
+Index: libunixlib/sys/errlist.c
+===================================================================
+--- libunixlib/sys/errlist.c (revision 7698)
++++ libunixlib/sys/errlist.c (working copy)
+@@ -211,3 +211,10 @@
+
+ return 0;
+ }
++
++char *
++strerror_l (int errnum, locale_t l)
++{
++ (void) l;
++ return strerror (errnum);
++}
+Index: libunixlib/time/broken.c
+===================================================================
+--- libunixlib/time/broken.c (revision 7698)
++++ libunixlib/time/broken.c (working copy)
+@@ -49,7 +49,7 @@
+ #ifdef __TARGET_SCL__
+ -1,
+ #else
+- __locale_territory[LC_TIME],
++ __locale_global.locale_territory[LC_TIME],
+ #endif
+ riscos_time, ordinals);
+ }
+Index: libunixlib/time/gmtime_r.c
+===================================================================
+--- libunixlib/time/gmtime_r.c (revision 7698)
++++ libunixlib/time/gmtime_r.c (working copy)
+@@ -46,7 +46,7 @@
+ #ifdef __TARGET_SCL__
+ -1,
+ #else
+- __locale_territory[LC_TIME],
++ __locale_global.locale_territory[LC_TIME],
+ #endif
+ riscos_time, ordinals)) != NULL)
+ {
+Index: libunixlib/time/localtime_r.c
+===================================================================
+--- libunixlib/time/localtime_r.c (revision 7698)
++++ libunixlib/time/localtime_r.c (working copy)
+@@ -28,7 +28,7 @@
+ #ifdef __TARGET_SCL__
+ -1,
+ #else
+- __locale_territory[LC_TIME],
++ __locale_global.locale_territory[LC_TIME],
+ #endif
+ riscos_time, ordinals)) != NULL)
+ {
+Index: libunixlib/time/mktime.c
+===================================================================
+--- libunixlib/time/mktime.c (revision 7698)
++++ libunixlib/time/mktime.c (working copy)
+@@ -23,7 +23,7 @@
+ #ifdef __TARGET_SCL__
+ -1,
+ #else
+- __locale_territory[LC_TIME],
++ __locale_global.locale_territory[LC_TIME],
+ #endif
+ riscos_time,
+ ordinals)) != NULL)
+Index: libunixlib/time/stdtime.c
+===================================================================
+--- libunixlib/time/stdtime.c (revision 7698)
++++ libunixlib/time/stdtime.c (working copy)
+@@ -48,7 +48,7 @@
+ #ifdef __TARGET_SCL__
+ -1,
+ #else
+- __locale_territory[LC_TIME],
++ __locale_global.locale_territory[LC_TIME],
+ #endif
+ riscos_time,
+ result,
+Index: libunixlib/time/strftime.c
+===================================================================
+--- libunixlib/time/strftime.c (revision 7698)
++++ libunixlib/time/strftime.c (working copy)
+@@ -353,7 +353,7 @@
+ int regs[10];
+ char buffer[64];
+
+- regs[0] = __locale_territory[LC_TIME];
++ regs[0] = __locale_global.locale_territory[LC_TIME];
+ regs[1] = (int)timep;
+ regs[2] = (int)buffer;
+ regs[3] = sizeof (buffer) - 1;
+@@ -368,7 +368,7 @@
+ int regs[10];
+ char buffer[64];
+
+- regs[0] = __locale_territory[LC_TIME];
++ regs[0] = __locale_global.locale_territory[LC_TIME];
+ regs[1] = (int)timep;
+ regs[2] = (int)buffer;
+ regs[3] = sizeof (buffer) - 1;
+Index: libunixlib/time/tzset.c
+===================================================================
+--- libunixlib/time/tzset.c (revision 7698)
++++ libunixlib/time/tzset.c (working copy)
+@@ -36,7 +36,7 @@
+ /* Get timezone information for current territory. */
+ _kernel_swi_regs regs;
+ #ifndef __TARGET_SCL__
+- regs.r[0] = __locale_territory[LC_TIME];
++ regs.r[0] = __locale_global.locale_territory[LC_TIME];
+ #else
+ regs.r[0] = -1; /* Current territory. */
+ #endif
+Index: libunixlib/unix/unix.c
+===================================================================
+--- libunixlib/unix/unix.c (revision 7698)
++++ libunixlib/unix/unix.c (working copy)
+@@ -191,7 +191,7 @@
+ __pthread_prog_init ();
+ __unixlib_signal_initialise (__u);
+ /* Initialise ctype tables to the C locale. */
+- __build_ctype_tables (-2);
++ __build_ctype_tables (&__locale_global, -2);
+ /* Define and initialise the Unix I/O. */
+ initialise_unix_io ();
+ __stdioinit ();
+Index: libunixlib/vscript
+===================================================================
+--- libunixlib/vscript (revision 7698)
++++ libunixlib/vscript (working copy)
+@@ -58,6 +58,9 @@
+ __init_des_r;
+ __init_des;
+ __invalidate;
++ __locale_global;
++ __localeconv_lconv_init;
++ __localeconv_lconv_fini;
+ malloc_trim;
+ malloc_trim_unlocked;
+ malloc_unlocked;
+@@ -80,6 +83,7 @@
+ __res_vinit;
+ __runtime_features;
+ __setup_signalhandler_stack;
++ __setlocale_l;
+ __sdirinit;
+ __sfixinit;
+ __sfixfind;
+Index: libunixlib/wchar/wctype.c
+===================================================================
+--- libunixlib/wchar/wctype.c (revision 7698)
++++ libunixlib/wchar/wctype.c (working copy)
+@@ -4,6 +4,7 @@
+ */
+
+ #include <ctype.h>
++#include <locale.h>
+ #include <wctype.h>
+
+ int
+@@ -71,3 +72,69 @@
+ {
+ return isxdigit (wc);
+ }
++
++int
++iswalnum_l (wint_t wc, locale_t locale)
++{
++ return isalnum_l (wc, locale);
++}
++
++int
++iswalpha_l (wint_t wc, locale_t locale)
++{
++ return isalpha_l (wc, locale);
++}
++
++int
++iswcntrl_l (wint_t wc, locale_t locale)
++{
++ return iscntrl_l (wc, locale);
++}
++
++int
++iswdigit_l (wint_t wc, locale_t locale)
++{
++ return isdigit_l (wc, locale);
++}
++
++int
++iswgraph_l (wint_t wc, locale_t locale)
++{
++ return isgraph_l (wc, locale);
++}
++
++int
++iswprint_l (wint_t wc, locale_t locale)
++{
++ return isprint_l (wc, locale);
++}
++
++int
++iswpunct_l (wint_t wc, locale_t locale)
++{
++ return ispunct_l (wc, locale);
++}
++
++int
++iswspace_l (wint_t wc, locale_t locale)
++{
++ return isspace_l (wc, locale);
++}
++
++int
++iswxdigit_l (wint_t wc, locale_t locale)
++{
++ return isxdigit_l (wc, locale);
++}
++
++wint_t
++towlower_l (wint_t wc, locale_t locale)
++{
++ return tolower_l (wc, locale);
++}
++
++wint_t
++towupper_l (wint_t wc, locale_t locale)
++{
++ return toupper_l (wc, locale);
++}
+Index: libunixlib/wchar/wmissing.c
+===================================================================
+--- libunixlib/wchar/wmissing.c (revision 7698)
++++ libunixlib/wchar/wmissing.c (working copy)
+@@ -1,7 +1,7 @@
++#include <locale.h>
++#include <stdio.h>
+ #include <stdlib.h>
+ #include <wctype.h>
+-#include <wctype.h>
+-#include <stdio.h>
+
+ int iswupper (wint_t __wc)
+ {
+@@ -9,13 +9,26 @@
+ abort();
+ }
+
+-unsigned long int wcstoul (__const wchar_t *__restrict __nptr,
+- wchar_t **__restrict __endptr, int __base)
++int
++iswupper_l (wint_t wc, locale_t locale)
+ {
+ printf("%s: Not implemented\n", __func__);
+ abort();
+ }
+
++int iswlower (wint_t __wc)
++{
++ printf("%s: Not implemented\n", __func__);
++ abort();
++}
++
++int
++iswlower_l (wint_t wc, locale_t locale)
++{
++ printf("%s: Not implemented\n", __func__);
++ abort();
++}
++
+ int wcscoll (__const wchar_t *__s1, __const wchar_t *__s2)
+ {
+ printf("%s: Not implemented\n", __func__);
+@@ -22,12 +35,47 @@
+ abort();
+ }
+
+-int iswlower (wint_t __wc)
++int wcscoll_l (__const wchar_t *__s1, __const wchar_t *__s2,
++ locale_t loc)
+ {
+ printf("%s: Not implemented\n", __func__);
+ abort();
+ }
+
++int wcscasecmp (__const wchar_t *__s1, __const wchar_t *__s2)
++{
++ printf("%s: Not implemented\n", __func__);
++ abort();
++}
++
++int wcsncasecmp (__const wchar_t *__s1, __const wchar_t *__s2,
++ size_t __n)
++{
++ printf("%s: Not implemented\n", __func__);
++ abort();
++}
++
++int wcscasecmp_l (__const wchar_t *__s1, __const wchar_t *__s2,
++ locale_t __loc)
++{
++ printf("%s: Not implemented\n", __func__);
++ abort();
++}
++
++int wcsncasecmp_l (__const wchar_t *__s1, __const wchar_t *__s2,
++ size_t __n, locale_t __loc)
++{
++ printf("%s: Not implemented\n", __func__);
++ abort();
++}
++
++unsigned long int wcstoul (__const wchar_t *__restrict __nptr,
++ wchar_t **__restrict __endptr, int __base)
++{
++ printf("%s: Not implemented\n", __func__);
++ abort();
++}
++
+ long long int wcstoll (__const wchar_t *__restrict __nptr,
+ wchar_t **__restrict __endptr, int __base)
+ {
+@@ -63,6 +111,13 @@
+ abort();
+ }
+
++size_t wcsxfrm_l (wchar_t *__s1, __const wchar_t *__s2,
++ size_t __n, locale_t __loc)
++{
++ printf("%s: Not implemented\n", __func__);
++ abort();
++}
++
+ float wcstof (__const wchar_t *__restrict __nptr,
+ wchar_t **__restrict __endptr)
+ {
+@@ -83,6 +138,13 @@
+ abort();
+ }
+
++int
++iswblank_l (wint_t __wc, locale_t __locale)
++{
++ printf("%s: Not implemented\n", __func__);
++ abort();
++}
++
+ int iswctype (wint_t __wc, wctype_t __desc)
+ {
+ printf("%s: Not implemented\n", __func__);
+@@ -89,6 +151,12 @@
+ abort();
+ }
+
++int iswctype_l (wint_t __wc, wctype_t __desc, locale_t __locale)
++{
++ printf("%s: Not implemented\n", __func__);
++ abort();
++}
++
+ unsigned long long int wcstoull (__const wchar_t *__restrict __nptr,
+ wchar_t **__restrict __endptr,
+ int __base)
+@@ -116,6 +184,12 @@
+ abort();
+ }
+
++wctype_t wctype_l (__const char *__property, locale_t __locale)
++{
++ printf("%s: Not implemented\n", __func__);
++ abort();
++}
++
+ wint_t ungetwc(wint_t wc, FILE *stream)
+ {
+ printf("%s: Not implemented\n", __func__);