Change loadlocale to fill a __locale_t given as parameter

Don't use global variables.  This allows to call loadlocale from
the yet to be created newlocale().

Rename _thr_locale_t to __locale_t (these locales are not restricted
to threads so the name is misleading).

Along these lines, fix _set_ctype to take a __locale_t as parameter.

Signed-off by: Corinna Vinschen <corinna@vinschen.de>
This commit is contained in:
Corinna Vinschen 2016-07-21 20:49:42 +02:00
parent d16a56306d
commit 1498c79db8
12 changed files with 87 additions and 88 deletions

View File

@ -36,6 +36,7 @@ static char sccsid[] = "@(#)ctype_.c 5.6 (Berkeley) 6/1/90";
#endif /* LIBC_SCCS and not lint */ #endif /* LIBC_SCCS and not lint */
#include <ctype.h> #include <ctype.h>
#include "../locale/setlocale.h"
#define _CTYPE_DATA_0_127 \ #define _CTYPE_DATA_0_127 \
_C, _C, _C, _C, _C, _C, _C, _C, \ _C, _C, _C, _C, _C, _C, _C, _C, \
@ -148,7 +149,7 @@ char *__ctype_ptr__ = (char *) _ctype_;
compatibility with applications built under older Cygwin releases. */ compatibility with applications built under older Cygwin releases. */
#ifndef __CYGWIN__ #ifndef __CYGWIN__
void void
__set_ctype (struct _reent *, const char *charset) __set_ctype (struct __locale_t *loc, const char *charset)
{ {
#if defined(_MB_EXTENDED_CHARSETS_ISO) || defined(_MB_EXTENDED_CHARSETS_WINDOWS) #if defined(_MB_EXTENDED_CHARSETS_ISO) || defined(_MB_EXTENDED_CHARSETS_WINDOWS)
int idx; int idx;
@ -184,15 +185,21 @@ __set_ctype (struct _reent *, const char *charset)
if (!ctype_ptr) if (!ctype_ptr)
{ {
# if defined(ALLOW_NEGATIVE_CTYPE_INDEX) # if defined(ALLOW_NEGATIVE_CTYPE_INDEX)
ctype_ptr = _ctype_b; ctype_ptr = _ctype_b;
# else # else
ctype_ptr = _ctype_; ctype_ptr = _ctype_;
# endif # endif
} }
# if defined(ALLOW_NEGATIVE_CTYPE_INDEX) # if defined(ALLOW_NEGATIVE_CTYPE_INDEX)
__ctype_ptr__ = ctype_ptr + 127; if (loc)
loc->ctype_ptr = ctype_ptr + 127;
else
__ctype_ptr__ = ctype_ptr + 127;
# else # else
__ctype_ptr__ = ctype_ptr; if (loc)
loc->ctype_ptr = ctype_ptr;
else
__ctype_ptr__ = ctype_ptr;
# endif # endif
} }
#endif /* !__CYGWIN__ */ #endif /* !__CYGWIN__ */

View File

@ -29,10 +29,10 @@
#define LC_TIME_MASK (1 << LC_TIME) #define LC_TIME_MASK (1 << LC_TIME)
#define LC_MESSAGES_MASK (1 << LC_MESSAGES) #define LC_MESSAGES_MASK (1 << LC_MESSAGES)
#define LC_GLOBAL_LOCALE ((struct _thr_locale_t *) -1) #define LC_GLOBAL_LOCALE ((struct __locale_t *) -1)
struct _thr_locale_t; struct __locale_t;
typedef struct _thr_locale_t *locale_t; typedef struct __locale_t *locale_t;
#endif #endif
_BEGIN_STD_C _BEGIN_STD_C

View File

@ -40,7 +40,7 @@ struct _reent;
/* TODO: This structure type isn't defined yet. It's supposed to be used /* TODO: This structure type isn't defined yet. It's supposed to be used
by locale-specific functions in case a per-thread locale per SUSv4 has by locale-specific functions in case a per-thread locale per SUSv4 has
been specified. */ been specified. */
struct _thr_locale_t; struct __locale_t;
/* /*
* If _REENT_SMALL is defined, we make struct _reent as small as possible, * If _REENT_SMALL is defined, we make struct _reent as small as possible,
@ -391,7 +391,7 @@ struct _reent
/* TODO */ /* TODO */
int _unspecified_locale_info; /* unused, reserved for locale stuff */ int _unspecified_locale_info; /* unused, reserved for locale stuff */
struct _thr_locale_t *_locale;/* per-thread locale */ struct __locale_t *_locale;/* per-thread locale */
struct _mprec *_mp; struct _mprec *_mp;
@ -584,7 +584,7 @@ struct _reent
/* TODO */ /* TODO */
int _unspecified_locale_info; /* unused, reserved for locale stuff */ int _unspecified_locale_info; /* unused, reserved for locale stuff */
struct _thr_locale_t *_locale;/* per-thread locale */ struct __locale_t *_locale;/* per-thread locale */
int __sdidinit; /* 1 means stdio has been init'd */ int __sdidinit; /* 1 means stdio has been init'd */

View File

@ -52,7 +52,7 @@ static char _ctype_locale_buf[_CTYPE_BUF_SIZE];
/* NULL locale indicates global locale (called from setlocale) */ /* NULL locale indicates global locale (called from setlocale) */
int int
__ctype_load_locale (struct _thr_locale_t *locale, const char *name, __ctype_load_locale (struct __locale_t *locale, const char *name,
void *f_wctomb, const char *charset, int mb_cur_max) void *f_wctomb, const char *charset, int mb_cur_max)
{ {
int ret; int ret;

View File

@ -60,7 +60,7 @@ static char *_messages_locale_buf;
#endif #endif
int int
__messages_load_locale (struct _thr_locale_t *locale, const char *name, __messages_load_locale (struct __locale_t *locale, const char *name,
void *f_wctomb, const char *charset) void *f_wctomb, const char *charset)
{ {
int ret; int ret;

View File

@ -89,7 +89,7 @@ cnv(const char *str) {
#endif #endif
int int
__monetary_load_locale (struct _thr_locale_t *locale, const char *name , __monetary_load_locale (struct __locale_t *locale, const char *name ,
void *f_wctomb, const char *charset) void *f_wctomb, const char *charset)
{ {
int ret; int ret;

View File

@ -51,7 +51,7 @@ static char *_numeric_locale_buf;
#endif #endif
int int
__numeric_load_locale (struct _thr_locale_t *locale, const char *name , __numeric_load_locale (struct __locale_t *locale, const char *name ,
void *f_wctomb, const char *charset) void *f_wctomb, const char *charset)
{ {
int ret; int ret;

View File

@ -226,7 +226,7 @@ static char *categories[_LC_LAST] = {
*/ */
char __default_locale[ENCODING_LEN + 1] = DEFAULT_LOCALE; char __default_locale[ENCODING_LEN + 1] = DEFAULT_LOCALE;
struct _thr_locale_t __global_locale = struct __locale_t __global_locale =
{ {
{ "C", "C", DEFAULT_LOCALE, "C", "C", "C", "C", }, { "C", "C", DEFAULT_LOCALE, "C", "C", "C", "C", },
#ifdef __CYGWIN__ #ifdef __CYGWIN__
@ -260,19 +260,12 @@ struct _thr_locale_t __global_locale =
#endif #endif
}; };
/*
* The locales we are going to try and load. These are only temporary
* variables and only used in setlocale.
*/
static char new_categories[_LC_LAST][ENCODING_LEN + 1];
static char saved_categories[_LC_LAST][ENCODING_LEN + 1];
/* Renamed from current_locale_string to make clear this is only the /* Renamed from current_locale_string to make clear this is only the
*global* string for setlocale (LC_ALL, NULL). There's no equivalent *global* string for setlocale (LC_ALL, NULL). There's no equivalent
functionality for uselocale. */ functionality for uselocale. */
static char global_locale_string[_LC_LAST * (ENCODING_LEN + 1/*"/"*/ + 1)]; static char global_locale_string[_LC_LAST * (ENCODING_LEN + 1/*"/"*/ + 1)];
static char *currentlocale(void); static char *currentlocale (void);
static char *loadlocale(struct _reent *, int); static char *loadlocale (struct __locale_t *, int, const char *);
static const char *__get_locale_env(struct _reent *, int); static const char *__get_locale_env(struct _reent *, int);
#endif /* _MB_CAPABLE */ #endif /* _MB_CAPABLE */
@ -283,6 +276,9 @@ _DEFUN(_setlocale_r, (p, category, locale),
int category _AND int category _AND
_CONST char *locale) _CONST char *locale)
{ {
static char new_categories[_LC_LAST][ENCODING_LEN + 1];
static char saved_categories[_LC_LAST][ENCODING_LEN + 1];
#ifndef _MB_CAPABLE #ifndef _MB_CAPABLE
if (locale) if (locale)
{ {
@ -396,21 +392,23 @@ _DEFUN(_setlocale_r, (p, category, locale),
} }
if (category != LC_ALL) if (category != LC_ALL)
return loadlocale (p, category); return loadlocale (__get_global_locale (), category,
new_categories[category]);
for (i = 1; i < _LC_LAST; ++i) for (i = 1; i < _LC_LAST; ++i)
{ {
strcpy (saved_categories[i], __global_locale.categories[i]); strcpy (saved_categories[i], __global_locale.categories[i]);
if (loadlocale (p, i) == NULL) if (loadlocale (__get_global_locale (), i, new_categories[i]) == NULL)
{ {
saverr = p->_errno; saverr = p->_errno;
for (j = 1; j < i; j++) for (j = 1; j < i; j++)
{ {
strcpy (new_categories[j], saved_categories[j]); strcpy (new_categories[j], saved_categories[j]);
if (loadlocale (p, j) == NULL) if (loadlocale (__get_global_locale (), j, new_categories[j])
== NULL)
{ {
strcpy (new_categories[j], "C"); strcpy (new_categories[j], "C");
loadlocale (p, j); loadlocale (__get_global_locale (), j, new_categories[j]);
} }
} }
p->_errno = saverr; p->_errno = saverr;
@ -423,7 +421,7 @@ _DEFUN(_setlocale_r, (p, category, locale),
#ifdef _MB_CAPABLE #ifdef _MB_CAPABLE
static char * static char *
currentlocale() currentlocale ()
{ {
int i; int i;
@ -444,10 +442,10 @@ currentlocale()
#ifdef _MB_CAPABLE #ifdef _MB_CAPABLE
extern void __set_ctype (struct _reent *, const char *charset); extern void __set_ctype (struct __locale_t *, const char *charset);
static char * static char *
loadlocale(struct _reent *p, int category) loadlocale (struct __locale_t *loc, int category, const char *new_locale)
{ {
/* At this point a full-featured system would just load the locale /* At this point a full-featured system would just load the locale
specific data from the locale files. specific data from the locale files.
@ -467,8 +465,8 @@ loadlocale(struct _reent *p, int category)
int cjknarrow = 0; int cjknarrow = 0;
/* Avoid doing everything twice if nothing has changed. */ /* Avoid doing everything twice if nothing has changed. */
if (!strcmp (new_categories[category], __global_locale.categories[category])) if (!strcmp (new_locale, loc->categories[category]))
return __global_locale.categories[category]; return loc->categories[category];
#ifdef __CYGWIN__ #ifdef __CYGWIN__
/* This additional code handles the case that the incoming locale string /* This additional code handles the case that the incoming locale string
@ -485,7 +483,7 @@ loadlocale(struct _reent *p, int category)
restart: restart:
if (!locale) if (!locale)
locale = new_categories[category]; locale = new_locale;
else if (locale != tmp_locale) else if (locale != tmp_locale)
{ {
locale = __set_locale_from_locale_alias (locale, tmp_locale); locale = __set_locale_from_locale_alias (locale, tmp_locale);
@ -494,7 +492,7 @@ restart:
} }
# define FAIL goto restart # define FAIL goto restart
#else #else
locale = new_categories[category]; locale = new_locale;
# define FAIL return NULL # define FAIL return NULL
#endif #endif
@ -662,7 +660,7 @@ restart:
c += 4; c += 4;
if (*c == '-') if (*c == '-')
++c; ++c;
val = _strtol_r (p, c, &end, 10); val = strtol (c, &end, 10);
if (val < 1 || val > 16 || val == 12 || *end) if (val < 1 || val > 16 || val == 12 || *end)
FAIL; FAIL;
strcpy (charset, "ISO-8859-"); strcpy (charset, "ISO-8859-");
@ -685,7 +683,7 @@ restart:
if (charset[1] != 'P' && charset[1] != 'p') if (charset[1] != 'P' && charset[1] != 'p')
FAIL; FAIL;
strncpy (charset, "CP", 2); strncpy (charset, "CP", 2);
val = _strtol_r (p, charset + 2, &end, 10); val = strtol (charset + 2, &end, 10);
if (*end) if (*end)
FAIL; FAIL;
switch (val) switch (val)
@ -860,60 +858,54 @@ restart:
{ {
case LC_CTYPE: case LC_CTYPE:
#ifndef __HAVE_LOCALE_INFO__ #ifndef __HAVE_LOCALE_INFO__
strcpy (__global_locale.ctype_codeset, charset); strcpy (loc->ctype_codeset, charset);
__global_locale.mb_cur_max[0] = mbc_max; loc->mb_cur_max[0] = mbc_max;
#endif #endif
#ifdef __CYGWIN__ #ifdef __CYGWIN__
__mb_cur_max = mbc_max; /* Only for backward compat */ __mb_cur_max = mbc_max; /* Only for backward compat */
#endif #endif
__global_locale.wctomb = l_wctomb; loc->wctomb = l_wctomb;
__global_locale.mbtowc = l_mbtowc; loc->mbtowc = l_mbtowc;
__set_ctype (NULL, charset); __set_ctype (loc == __get_global_locale () ? NULL : loc, charset);
/* Determine the width for the "CJK Ambiguous Width" category of /* Determine the width for the "CJK Ambiguous Width" category of
characters. This is used in wcwidth(). Assume single width for characters. This is used in wcwidth(). Assume single width for
single-byte charsets, and double width for multi-byte charsets single-byte charsets, and double width for multi-byte charsets
other than UTF-8. For UTF-8, use double width for the East Asian other than UTF-8. For UTF-8, use double width for the East Asian
languages ("ja", "ko", "zh"), and single width for everything else. languages ("ja", "ko", "zh"), and single width for everything else.
Single width can also be forced with the "@cjknarrow" modifier. */ Single width can also be forced with the "@cjknarrow" modifier. */
__global_locale.cjk_lang = !cjknarrow loc->cjk_lang = !cjknarrow && mbc_max > 1
&& mbc_max > 1 && (charset[0] != 'U'
&& (charset[0] != 'U' || strncmp (locale, "ja", 2) == 0
|| strncmp (locale, "ja", 2) == 0 || strncmp (locale, "ko", 2) == 0
|| strncmp (locale, "ko", 2) == 0 || strncmp (locale, "zh", 2) == 0);
|| strncmp (locale, "zh", 2) == 0);
#ifdef __HAVE_LOCALE_INFO__ #ifdef __HAVE_LOCALE_INFO__
ret = __ctype_load_locale (__get_global_locale (), locale, ret = __ctype_load_locale (loc, locale, (void *) l_wctomb, charset,
(void *) l_wctomb, charset, mbc_max); mbc_max);
#endif /* __HAVE_LOCALE_INFO__ */ #endif /* __HAVE_LOCALE_INFO__ */
break; break;
case LC_MESSAGES: case LC_MESSAGES:
#ifdef __HAVE_LOCALE_INFO__ #ifdef __HAVE_LOCALE_INFO__
ret = __messages_load_locale (__get_global_locale (), locale, ret = __messages_load_locale (loc, locale, (void *) l_wctomb, charset);
(void *) l_wctomb, charset);
if (!ret) if (!ret)
#else #else
strcpy (__global_locale.message_codeset, charset); strcpy (loc->message_codeset, charset);
#endif /* __HAVE_LOCALE_INFO__ */ #endif /* __HAVE_LOCALE_INFO__ */
break; break;
#ifdef __HAVE_LOCALE_INFO__ #ifdef __HAVE_LOCALE_INFO__
#ifdef __CYGWIN__ #ifdef __CYGWIN__
/* Right now only Cygwin supports a __collate_load_locale function at all. */ /* Right now only Cygwin supports a __collate_load_locale function at all. */
case LC_COLLATE: case LC_COLLATE:
ret = __collate_load_locale (__get_global_locale (), locale, ret = __collate_load_locale (loc, locale, (void *) l_mbtowc, charset);
(void *) l_mbtowc, charset);
break; break;
#endif #endif
case LC_MONETARY: case LC_MONETARY:
ret = __monetary_load_locale (__get_global_locale (), locale, ret = __monetary_load_locale (loc, locale, (void *) l_wctomb, charset);
(void *) l_wctomb, charset);
break; break;
case LC_NUMERIC: case LC_NUMERIC:
ret = __numeric_load_locale (__get_global_locale (), locale, ret = __numeric_load_locale (loc, locale, (void *) l_wctomb, charset);
(void *) l_wctomb, charset);
break; break;
case LC_TIME: case LC_TIME:
ret = __time_load_locale (__get_global_locale (), locale, ret = __time_load_locale (loc, locale, (void *) l_wctomb, charset);
(void *) l_wctomb, charset);
break; break;
#endif /* __HAVE_LOCALE_INFO__ */ #endif /* __HAVE_LOCALE_INFO__ */
default: default:
@ -923,11 +915,11 @@ restart:
if (ret) if (ret)
FAIL; FAIL;
#endif /* __HAVE_LOCALE_INFO__ */ #endif /* __HAVE_LOCALE_INFO__ */
return strcpy(__global_locale.categories[category], new_categories[category]); return strcpy(loc->categories[category], new_locale);
} }
static const char * static const char *
__get_locale_env(struct _reent *p, int category) __get_locale_env (struct _reent *p, int category)
{ {
const char *env; const char *env;
@ -951,7 +943,7 @@ __get_locale_env(struct _reent *p, int category)
#endif /* _MB_CAPABLE */ #endif /* _MB_CAPABLE */
int int
_DEFUN_VOID(__locale_mb_cur_max) _DEFUN_VOID (__locale_mb_cur_max)
{ {
#ifdef __HAVE_LOCALE_INFO__ #ifdef __HAVE_LOCALE_INFO__
return __get_current_ctype_locale ()->mb_cur_max[0]; return __get_current_ctype_locale ()->mb_cur_max[0];
@ -962,7 +954,7 @@ _DEFUN_VOID(__locale_mb_cur_max)
#ifdef __HAVE_LOCALE_INFO__ #ifdef __HAVE_LOCALE_INFO__
char * char *
_DEFUN_VOID(__locale_ctype_ptr) _DEFUN_VOID (__locale_ctype_ptr)
{ {
/* Only check if the current thread/reent has a locale. ctype_ptr is unused /* Only check if the current thread/reent has a locale. ctype_ptr is unused
in __global_locale, rather the global variable __ctype_ptr__ is used. */ in __global_locale, rather the global variable __ctype_ptr__ is used. */
@ -973,8 +965,8 @@ _DEFUN_VOID(__locale_ctype_ptr)
#endif #endif
struct lconv * struct lconv *
_DEFUN(_localeconv_r, (data), _DEFUN (_localeconv_r, (data),
struct _reent *data) struct _reent *data)
{ {
#ifdef __HAVE_LOCALE_INFO__ #ifdef __HAVE_LOCALE_INFO__
const struct lc_numeric_T *n = __get_current_numeric_locale (); const struct lc_numeric_T *n = __get_current_numeric_locale ();
@ -1020,15 +1012,15 @@ _DEFUN(_localeconv_r, (data),
#ifndef _REENT_ONLY #ifndef _REENT_ONLY
char * char *
_DEFUN(setlocale, (category, locale), _DEFUN (setlocale, (category, locale),
int category _AND int category _AND
_CONST char *locale) _CONST char *locale)
{ {
return _setlocale_r (_REENT, category, locale); return _setlocale_r (_REENT, category, locale);
} }
struct lconv * struct lconv *
_DEFUN_VOID(localeconv) _DEFUN_VOID (localeconv)
{ {
return _localeconv_r (_REENT); return _localeconv_r (_REENT);
} }

View File

@ -165,7 +165,7 @@ struct lc_collate_T
extern const struct lc_collate_T _C_collate_locale; extern const struct lc_collate_T _C_collate_locale;
#endif #endif
struct _thr_locale_t struct __locale_t
{ {
char categories[_LC_LAST][ENCODING_LEN + 1]; char categories[_LC_LAST][ENCODING_LEN + 1];
int (*wctomb) (struct _reent *, char *, wchar_t, int (*wctomb) (struct _reent *, char *, wchar_t,
@ -197,18 +197,18 @@ struct _thr_locale_t
#endif #endif
}; };
extern struct _thr_locale_t __global_locale; extern struct __locale_t __global_locale;
/* In POSIX terms the global locale is the process-wide locale. Use this /* In POSIX terms the global locale is the process-wide locale. Use this
function to always refer to the global locale. */ function to always refer to the global locale. */
_ELIDABLE_INLINE struct _thr_locale_t * _ELIDABLE_INLINE struct __locale_t *
__get_global_locale () __get_global_locale ()
{ {
return &__global_locale; return &__global_locale;
} }
/* Per REENT locale. This is newlib-internal. */ /* Per REENT locale. This is newlib-internal. */
_ELIDABLE_INLINE struct _thr_locale_t * _ELIDABLE_INLINE struct __locale_t *
__get_locale_r (struct _reent *r) __get_locale_r (struct _reent *r)
{ {
return r->_locale; return r->_locale;
@ -218,7 +218,7 @@ __get_locale_r (struct _reent *r)
using locale info without providing a locale as parameter (*_l functions). using locale info without providing a locale as parameter (*_l functions).
The current locale is either the locale of the current thread, if the The current locale is either the locale of the current thread, if the
thread called uselocale, or the global locale if not. */ thread called uselocale, or the global locale if not. */
_ELIDABLE_INLINE struct _thr_locale_t * _ELIDABLE_INLINE struct __locale_t *
__get_current_locale () __get_current_locale ()
{ {
return _REENT->_locale ?: &__global_locale; return _REENT->_locale ?: &__global_locale;
@ -292,18 +292,18 @@ __locale_cjk_lang (void)
#endif #endif
} }
int __ctype_load_locale (struct _thr_locale_t *, const char *, void *, int __ctype_load_locale (struct __locale_t *, const char *, void *,
const char *, int); const char *, int);
int __monetary_load_locale (struct _thr_locale_t *, const char *, void *, int __monetary_load_locale (struct __locale_t *, const char *, void *,
const char *); const char *);
int __numeric_load_locale (struct _thr_locale_t *, const char *, void *, int __numeric_load_locale (struct __locale_t *, const char *, void *,
const char *); const char *);
int __time_load_locale (struct _thr_locale_t *, const char *, void *, int __time_load_locale (struct __locale_t *, const char *, void *,
const char *); const char *);
int __messages_load_locale (struct _thr_locale_t *, const char *, void *, int __messages_load_locale (struct __locale_t *, const char *, void *,
const char *); const char *);
#ifdef __CYGWIN__ #ifdef __CYGWIN__
int __collate_load_locale (struct _thr_locale_t *, const char *, void *, int __collate_load_locale (struct __locale_t *, const char *, void *,
const char *); const char *);
extern void __set_charset_from_locale (const char *locale, char *charset); extern void __set_charset_from_locale (const char *locale, char *charset);

View File

@ -152,7 +152,7 @@ static char *time_locale_buf;
#endif #endif
int int
__time_load_locale (struct _thr_locale_t *locale, const char *name, __time_load_locale (struct __locale_t *locale, const char *name,
void *f_wctomb, const char *charset) void *f_wctomb, const char *charset)
{ {
int ret; int ret;

View File

@ -19,7 +19,7 @@ extern const char __ctype_cp[22][128 + 256]; /* Newlib */
extern const char __ctype_iso[15][128 + 256]; /* Newlib */ extern const char __ctype_iso[15][128 + 256]; /* Newlib */
void void
__set_ctype (struct _reent *reent, const char *charset) __set_ctype (struct __locale_t *loc, const char *charset)
{ {
int idx; int idx;
char *ctype_ptr = NULL; char *ctype_ptr = NULL;
@ -63,8 +63,8 @@ __set_ctype (struct _reent *reent, const char *charset)
} }
ctype_ptr = (char *) _ctype_b; ctype_ptr = (char *) _ctype_b;
} }
if (reent) if (loc)
__get_locale_r (reent)->ctype_ptr = ctype_ptr + 127; loc->ctype_ptr = ctype_ptr + 127;
else else
__ctype_ptr__ = ctype_ptr + 127; __ctype_ptr__ = ctype_ptr + 127;
} }

View File

@ -1070,7 +1070,7 @@ __set_lc_messages_from_win (const char *name,
LC_COLLATE locale information. This is subsequently accessed by the LC_COLLATE locale information. This is subsequently accessed by the
below functions strcoll, strxfrm, wcscoll, wcsxfrm. */ below functions strcoll, strxfrm, wcscoll, wcsxfrm. */
extern "C" int extern "C" int
__collate_load_locale (struct _thr_locale_t *locale, const char *name, __collate_load_locale (struct __locale_t *locale, const char *name,
void *f_mbtowc, const char *charset) void *f_mbtowc, const char *charset)
{ {
const struct lc_collate_T *ccop; const struct lc_collate_T *ccop;