* locale/setlocale.c (_nl_current_names): Variable moved ...

* locale/localename.c (_nl_current_names): ... here, new file.
	Make it global, with attribute_hidden.
	* locale/localeinfo.h: Declare it.
	* locale/Makefile (aux): Add localename.
	* locale/localename.c (__current_locale_name): New function.
	* include/locale.h (__current_locale_name): Declare it.
	* intl/dcigettext.c (guess_category_value): Use that instead of
	calling setlocale.

	* locale/locale.h [__USE_GNU] (locale_t): New type alias of __locale_t.
	[__USE_GNU] (newlocale, duplocale, freelocale, uselocale): New decls.
	[__USE_GNU] (LC_GLOBAL_LOCALE): New macro.
	* locale/newlocale.c: Add alias to __ name.
	* locale/duplocale.c: Likewise.
	* locale/freelocale.c: Likewise.
	* locale/uselocale.c: New file.
	* locale/Makefile (routines): Add it.
	* locale/Versions (libc: GLIBC_2.3): New set.
	Add newlocale, duplocale, freelocale, uselocale.
	(libc: GLIBC_PRIVATE): Add __uselocale.

	* locale/localeinfo.h [SHARED]
	(_NL_CURRENT_LOCALE): New macro, defined to fetch a tsd value.
	(_NL_CURRENT_DATA): Define using that.
	(_NL_CURRENT, _NL_CURRENT_WSTR, _NL_CURRENT_WORD): Define using that.
	(_NL_CURRENT_DEFINE): Define to empty.
	[! SHARED]: Decls of _nl_current_CATEGORY and _nl_current
	conditionalized on this.
	* locale/xlocale.c (NL_C_INTIIALIZER): New macro,
	taking initializer of _nl_C_locobj.
	[SHARED] (_nl_global_locale): New variable, using that initializer.
	(_nl_C_locobj): Use new macro for initialzier.
	* locale/setlocale.c [! SHARED] (_nl_current): Conditionalize on this.
	[! SHARED] (CATEGORY_USED): New macro.
	[SHARED] (CATEGORY_USED, _nl_C): New macros.
	(setdata, setlocale): Use that macro instead of examining _nl_current.
	(setdata): Set the slot in _nl_global_locale.
	Conditionalize setting of _nl_current on [! SHARED].
	* locale/findlocale.c [SHARED] (_nl_C): Define as a macro instead of
	declaration as an extern.
	* locale/newlocale.c (__newlocale): Use _nl_C_locobj instead of _nl_C.

	* include/locale.h: Use libc_hidden_proto for setlocale.
	* locale/setlocale.c: Add libc_hidden_def.

	* locale/setlocale.c (free_mem): Use _NL_CURRENT_DATA.
This commit is contained in:
Roland McGrath 2002-08-04 01:41:55 +00:00
parent 509d1b6842
commit 30c14c31ae
15 changed files with 305 additions and 64 deletions

View File

@ -1,5 +1,53 @@
2002-08-03 Roland McGrath <roland@redhat.com>
* locale/setlocale.c (_nl_current_names): Variable moved ...
* locale/localename.c (_nl_current_names): ... here, new file.
Make it global, with attribute_hidden.
* locale/localeinfo.h: Declare it.
* locale/Makefile (aux): Add localename.
* locale/localename.c (__current_locale_name): New function.
* include/locale.h (__current_locale_name): Declare it.
* intl/dcigettext.c (guess_category_value): Use that instead of
calling setlocale.
* locale/locale.h [__USE_GNU] (locale_t): New type alias of __locale_t.
[__USE_GNU] (newlocale, duplocale, freelocale, uselocale): New decls.
[__USE_GNU] (LC_GLOBAL_LOCALE): New macro.
* locale/newlocale.c: Add alias to __ name.
* locale/duplocale.c: Likewise.
* locale/freelocale.c: Likewise.
* locale/uselocale.c: New file.
* locale/Makefile (routines): Add it.
* locale/Versions (libc: GLIBC_2.3): New set.
Add newlocale, duplocale, freelocale, uselocale.
(libc: GLIBC_PRIVATE): Add __uselocale.
* locale/localeinfo.h [SHARED]
(_NL_CURRENT_LOCALE): New macro, defined to fetch a tsd value.
(_NL_CURRENT_DATA): Define using that.
(_NL_CURRENT, _NL_CURRENT_WSTR, _NL_CURRENT_WORD): Define using that.
(_NL_CURRENT_DEFINE): Define to empty.
[! SHARED]: Decls of _nl_current_CATEGORY and _nl_current
conditionalized on this.
* locale/xlocale.c (NL_C_INTIIALIZER): New macro,
taking initializer of _nl_C_locobj.
[SHARED] (_nl_global_locale): New variable, using that initializer.
(_nl_C_locobj): Use new macro for initialzier.
* locale/setlocale.c [! SHARED] (_nl_current): Conditionalize on this.
[! SHARED] (CATEGORY_USED): New macro.
[SHARED] (CATEGORY_USED, _nl_C): New macros.
(setdata, setlocale): Use that macro instead of examining _nl_current.
(setdata): Set the slot in _nl_global_locale.
Conditionalize setting of _nl_current on [! SHARED].
* locale/findlocale.c [SHARED] (_nl_C): Define as a macro instead of
declaration as an extern.
* locale/newlocale.c (__newlocale): Use _nl_C_locobj instead of _nl_C.
* include/locale.h: Use libc_hidden_proto for setlocale.
* locale/setlocale.c: Add libc_hidden_def.
* locale/setlocale.c (free_mem): Use _NL_CURRENT_DATA.
* include/search.h: Use libc_hidden_proto for hsearch_r, lfind.
* misc/hsearch_r.c: Add libc_hidden_def.
* misc/lsearch.c: Likewise.

View File

@ -1,6 +1,8 @@
#ifndef _LOCALE_H
#include <locale/locale.h>
libc_hidden_proto (setlocale)
/* This has to be changed whenever a new locale is defined. */
#define __LC_LAST 13
@ -12,4 +14,7 @@ extern struct __locale_struct _nl_C_locobj attribute_hidden;
/* Now define the internal interfaces. */
extern struct lconv *__localeconv (void);
/* Fetch the name of the current locale set in the given category. */
extern const char *__current_locale_name (int category) attribute_hidden;
#endif

View File

@ -1059,7 +1059,7 @@ guess_category_value (category, categoryname)
`LC_xxx', and `LANG'. On some systems this can be done by the
`setlocale' function itself. */
#ifdef _LIBC
retval = setlocale (category, NULL);
retval = __current_locale_name (category);
#else
retval = _nl_locale_name (category, categoryname);
#endif

View File

@ -37,12 +37,12 @@ distribute = localeinfo.h categories.def iso-639.def iso-3166.def \
3level.h charmap-dir.h locarchive.c)
routines = setlocale findlocale loadlocale localeconv nl_langinfo \
nl_langinfo_l mb_cur_max \
newlocale duplocale freelocale
newlocale duplocale freelocale uselocale
tests = tst-C-locale
categories = ctype messages monetary numeric time paper name \
address telephone measurement identification collate
aux = $(categories:%=lc-%) $(categories:%=C-%) SYS_libc C_name \
xlocale
xlocale localename
others = localedef locale
#others-static = localedef locale
install-bin = localedef locale

View File

@ -46,9 +46,16 @@ libc {
# missing function from the experimental locale implementation
__nl_langinfo_l;
}
GLIBC_2.3 {
# the new "experimental" interface is now public
newlocale; duplocale; freelocale; uselocale;
}
GLIBC_PRIVATE {
# global variables
__collate_element_hash; __collate_element_strings;
__collate_symbol_classes; __collate_symbol_hash; __collate_symbol_strings;
# this internal name is used by libpthread
__uselocale;
}
}

View File

@ -61,3 +61,4 @@ __duplocale (__locale_t dataset)
return result;
}
weak_alias (__duplocale, duplocale)

View File

@ -30,8 +30,12 @@
#include "../iconv/gconv_charset.h"
#ifndef SHARED
/* Constant data defined in setlocale.c. */
extern struct locale_data *const _nl_C[] attribute_hidden;
#else
# define _nl_C (_nl_C_locobj.__locales)
#endif
/* For each category we keep a list of records for the locale files

View File

@ -48,3 +48,4 @@ __freelocale (__locale_t dataset)
/* It's done. */
__libc_lock_unlock (__libc_setlocale_lock);
}
weak_alias (__freelocale, freelocale)

View File

@ -1,4 +1,4 @@
/* Copyright (C) 1991,92,1995-1999,2000,2001 Free Software Foundation, Inc.
/* Copyright (C) 1991,92,95-99,2000,01,02 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
@ -140,6 +140,8 @@ extern struct lconv *localeconv (void) __THROW;
/* Get locale datatype definition. */
# include <xlocale.h>
typedef __locale_t locale_t;
/* Return a reference to a data structure representing a set of locale
datasets. Unlike for the CATEGORY parameter for `setlocale' the
CATEGORY_MASK parameter here uses a single bit for each category.
@ -148,14 +150,31 @@ extern struct lconv *localeconv (void) __THROW;
record is replaced. */
extern __locale_t __newlocale (int __category_mask, __const char *__locale,
__locale_t __base) __THROW;
extern __locale_t newlocale (int __category_mask, __const char *__locale,
__locale_t __base) __THROW;
/* Return a duplicate of the set of locale in DATASET. All usage
counters are increased if necessary. */
extern __locale_t __duplocale (__locale_t __dataset) __THROW;
extern __locale_t duplocale (__locale_t __dataset) __THROW;
/* Free the data associated with a locale dataset previously returned
by a call to `setlocale_r'. */
extern void __freelocale (__locale_t __dataset) __THROW;
extern void freelocale (__locale_t __dataset) __THROW;
/* Switch the current thread's locale to DATASET.
If DATASET is null, instead just return the current setting.
The special value LC_GLOBAL_LOCALE is the initial setting
for all threads and can also be installed any time, meaning
the thread uses the global settings controlled by `setlocale'. */
extern __locale_t __uselocale (__locale_t __dataset) __THROW;
extern __locale_t uselocale (__locale_t __dataset) __THROW;
/* This value can be passed to `uselocale' and may be returned by it.
Passing this value to any other function has undefined behavior. */
# define LC_GLOBAL_LOCALE ((__locale_t) -1L)
#endif
__END_DECLS

View File

@ -138,18 +138,8 @@ enum
#define _ISCTYPE(c, desc) \
(((((const uint32_t *) (desc)) - 8)[(c) >> 5] >> ((c) & 0x1f)) & 1)
/* For each category declare the variable for the current locale data. */
/* XXX _nl_current_LC_CTYPE and _nl_current_LC_COLLATE were exported
but where are they used? */
#define DEFINE_CATEGORY(category, category_name, items, a) \
extern struct locale_data *_nl_current_##category attribute_hidden;
#include "categories.def"
#undef DEFINE_CATEGORY
extern const char *const _nl_category_names[__LC_LAST] attribute_hidden;
extern const size_t _nl_category_name_sizes[__LC_LAST] attribute_hidden;
extern struct locale_data * *const _nl_current[__LC_LAST] attribute_hidden;
/* Name of the standard locales. */
extern const char _nl_C_name[] attribute_hidden;
@ -158,9 +148,25 @@ extern const char _nl_POSIX_name[] attribute_hidden;
/* The standard codeset. */
extern const char _nl_C_codeset[] attribute_hidden;
/* Name of current locale for each individual category.
Each is malloc'd unless it is _nl_C_name. */
extern const char *_nl_current_names[] attribute_hidden;
#ifndef SHARED
/* For each category declare the variable for the current locale data. */
/* XXX _nl_current_LC_CTYPE and _nl_current_LC_COLLATE were exported
but where are they used? */
#define DEFINE_CATEGORY(category, category_name, items, a) \
extern struct locale_data *_nl_current_##category attribute_hidden;
#include "categories.def"
#undef DEFINE_CATEGORY
extern struct locale_data * *const _nl_current[__LC_LAST] attribute_hidden;
/* Return a pointer to the current `struct locale_data' for CATEGORY. */
#define _NL_CURRENT_DATA(category) \
((const struct locale_data *) _nl_current_##category)
#define _NL_CURRENT_DATA(category) _nl_current_##category
/* Hackety hack, don't talk back. */
#define _nl_current_category (*_nl_current[category])
/* Extract the current CATEGORY locale's string for ITEM. */
#define _NL_CURRENT(category, item) \
@ -179,6 +185,43 @@ extern const char _nl_C_codeset[] attribute_hidden;
extern struct locale_data _nl_C_##category attribute_hidden; \
struct locale_data *_nl_current_##category = &_nl_C_##category
#else
/* All categories are always loaded in the shared library, so there is no
point in having lots of separate symbols for linking. */
# include <bits/libc-tsd.h>
__libc_tsd_define (extern, LOCALE)
extern struct __locale_struct _nl_global_locale attribute_hidden;
# define _NL_CURRENT_LOCALE \
((__locale_t) __libc_tsd_get (LOCALE))
/* Return a pointer to the current `struct locale_data' for CATEGORY. */
# define _NL_CURRENT_DATA(category) \
(_NL_CURRENT_LOCALE->__locales[category])
/* Extract the current CATEGORY locale's string for ITEM. */
# define _NL_CURRENT(category, item) \
(_NL_CURRENT_DATA (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_DATA (category)->values[_NL_ITEM_INDEX (item)].wstr)
/* Extract the current CATEGORY locale's word for ITEM. */
# define _NL_CURRENT_WORD(category, item) \
(_NL_CURRENT_DATA (category)->values[_NL_ITEM_INDEX (item)].word)
/* This is used in lc-CATEGORY.c to define _nl_current_CATEGORY. */
# define _NL_CURRENT_DEFINE(category) \
/* No per-category variable here. */
#endif
/* Load the locale data for CATEGORY from the file specified by *NAME.
If *NAME is "", use environment variables as specified by POSIX,
and fill in *NAME with the actual name used. The directories

42
locale/localename.c Normal file
View File

@ -0,0 +1,42 @@
/* current locale setting names
Copyright (C) 2002 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, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include "localeinfo.h"
/* Name of current locale for each individual category.
Each is malloc'd unless it is _nl_C_name. */
const char *_nl_current_names[] attribute_hidden =
{
#define DEFINE_CATEGORY(category, category_name, items, a) \
[category] = _nl_C_name,
#include "categories.def"
#undef DEFINE_CATEGORY
[LC_ALL] = _nl_C_name /* For LC_ALL. */
};
const char *
attribute_hidden
__current_locale_name (int category)
{
#if 0
return _NL_CURRENT_DATA (category)->name;
#else
return _nl_current_names[category];
#endif
}

View File

@ -26,9 +26,6 @@
#include "localeinfo.h"
/* Constant data defined in setlocale.c. */
extern struct locale_data *const _nl_C[] attribute_hidden;
/* Use this when we come along an error. */
#define ERROR_RETURN \
do { \
@ -65,12 +62,8 @@ __newlocale (int category_mask, const char *locale, __locale_t base)
if (base != NULL)
result = *base;
else
{
/* Fill with pointers to C locale data. */
for (cnt = 0; cnt < __LC_LAST; ++cnt)
if (cnt != LC_ALL)
result.__locales[cnt] = _nl_C[cnt];
}
/* Fill with pointers to C locale data. */
result = _nl_C_locobj;
/* If no category is to be set we return BASE if available or a
dataset using the C locale data. */
@ -184,3 +177,4 @@ __newlocale (int category_mask, const char *locale, __locale_t base)
return result_ptr;
}
weak_alias (__newlocale, newlocale)

View File

@ -27,6 +27,8 @@
#include "localeinfo.h"
#ifndef SHARED
/* For each category declare two external variables (with weak references):
extern const struct locale_data *_nl_current_CATEGORY;
This points to the current locale's in-core data for CATEGORY.
@ -35,6 +37,8 @@
Both are weak references; if &_nl_current_CATEGORY is zero,
then nothing is using the locale data. */
#define DEFINE_CATEGORY(category, category_name, items, a) \
weak_extern (_nl_current_##category) \
weak_extern (_nl_C_##category) \
extern struct locale_data *_nl_current_##category; \
extern struct locale_data _nl_C_##category;
#include "categories.def"
@ -63,6 +67,19 @@ struct locale_data *const _nl_C[] attribute_hidden =
#undef DEFINE_CATEGORY
};
# define CATEGORY_USED(category) (_nl_current[category] != NULL)
#else
/* The shared library always loads all the categories,
and the current global settings are kept in _nl_global_locale. */
# define _nl_C (_nl_C_locobj.__locales)
# define CATEGORY_USED(category) (1)
#endif
/* Define an array of category names (also the environment variable names),
indexed by integral category. */
@ -105,18 +122,6 @@ static void (*const _nl_category_postload[]) (void) =
};
/* Name of current locale for each individual category.
Each is malloc'd unless it is nl_C_name. */
static const char *_nl_current_names[] =
{
#define DEFINE_CATEGORY(category, category_name, items, a) \
[category] = _nl_C_name,
#include "categories.def"
#undef DEFINE_CATEGORY
[LC_ALL] = _nl_C_name /* For LC_ALL. */
};
/* Lock for protecting global data. */
__libc_lock_define_initialized (, __libc_setlocale_lock attribute_hidden)
@ -200,20 +205,24 @@ setname (int category, const char *name)
_nl_current_names[category] = name;
}
/* Put DATA in *_nl_current[CATEGORY]. */
static inline void
setdata (int category, struct locale_data *data)
{
if (_nl_current[category] != NULL)
if (CATEGORY_USED (category))
{
#ifdef SHARED
_nl_global_locale.__locales[category] = data;
#endif
#ifndef SHARED
# warning when uselocale exists it will need the line above too
*_nl_current[category] = data;
#endif
if (_nl_category_postload[category])
(*_nl_category_postload[category]) ();
}
}
char *
setlocale (int category, const char *locale)
{
@ -371,7 +380,7 @@ setlocale (int category, const char *locale)
/* Protect global data. */
__libc_lock_lock (__libc_setlocale_lock);
if (_nl_current[category] != NULL)
if (CATEGORY_USED (category))
{
/* Only actually load the data if anything will use it. */
newdata = _nl_find_locale (locale_path, locale_path_len, category,
@ -409,7 +418,7 @@ setlocale (int category, const char *locale)
}
else
{
if (_nl_current[category] != NULL)
if (CATEGORY_USED (category))
setdata (category, newdata);
setname (category, newname[0]);
@ -429,6 +438,7 @@ setlocale (int category, const char *locale)
return (char *) newname[0];
}
}
libc_hidden_def (setlocale)
static void __attribute__ ((unused))
free_mem (void)
@ -438,7 +448,7 @@ free_mem (void)
for (category = 0; category < __LC_LAST; ++category)
if (category != LC_ALL)
{
struct locale_data *here = *_nl_current[category];
struct locale_data *here = _NL_CURRENT_DATA (category);
struct loaded_l10nfile *runp = _nl_locale_file_list[category];
/* If this category is already "C" don't do anything. */

52
locale/uselocale.c Normal file
View File

@ -0,0 +1,52 @@
/* uselocale -- fetch and set the current per-thread locale
Copyright (C) 2002 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, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
#include <locale.h>
#include "localeinfo.h"
#ifdef SHARED
/* Switch the current thread's locale to DATASET.
If DATASET is null, instead just return the current setting.
The special value LC_GLOBAL_LOCALE is the initial setting
for all threads, and means the thread uses the global
setting controlled by `setlocale'. */
locale_t
__uselocale (locale_t newloc)
{
if (newloc == NULL)
{
locale_t loc = __libc_tsd_get (LOCALE);
return loc == &_nl_global_locale ? LC_GLOBAL_LOCALE : loc;
}
if (newloc == LC_GLOBAL_LOCALE)
{
__libc_tsd_set (LOCALE, &_nl_global_locale);
return LC_GLOBAL_LOCALE;
}
__libc_tsd_set (LOCALE, newloc);
return newloc;
}
weak_alias (__uselocale, uselocale)
#else
# warning uselocale not implemented for static linking yet
#endif

View File

@ -32,24 +32,39 @@ extern const char _nl_C_LC_CTYPE_toupper[] attribute_hidden;
extern const char _nl_C_LC_CTYPE_tolower[] attribute_hidden;
struct __locale_struct _nl_C_locobj attribute_hidden =
{
.__locales =
{
[LC_CTYPE] = &_nl_C_LC_CTYPE,
[LC_NUMERIC] = &_nl_C_LC_NUMERIC,
[LC_TIME] = &_nl_C_LC_TIME,
[LC_COLLATE] = &_nl_C_LC_COLLATE,
[LC_MONETARY] = &_nl_C_LC_MONETARY,
[LC_MESSAGES] = &_nl_C_LC_MESSAGES,
[LC_PAPER] = &_nl_C_LC_PAPER,
[LC_NAME] = &_nl_C_LC_NAME,
[LC_ADDRESS] = &_nl_C_LC_ADDRESS,
[LC_TELEPHONE] = &_nl_C_LC_TELEPHONE,
[LC_MEASUREMENT] = &_nl_C_LC_MEASUREMENT,
[LC_IDENTIFICATION] = &_nl_C_LC_IDENTIFICATION
},
.__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
};
#define NL_C_INITIALIZER \
{ \
.__locales = \
{ \
[LC_CTYPE] = &_nl_C_LC_CTYPE, \
[LC_NUMERIC] = &_nl_C_LC_NUMERIC, \
[LC_TIME] = &_nl_C_LC_TIME, \
[LC_COLLATE] = &_nl_C_LC_COLLATE, \
[LC_MONETARY] = &_nl_C_LC_MONETARY, \
[LC_MESSAGES] = &_nl_C_LC_MESSAGES, \
[LC_PAPER] = &_nl_C_LC_PAPER, \
[LC_NAME] = &_nl_C_LC_NAME, \
[LC_ADDRESS] = &_nl_C_LC_ADDRESS, \
[LC_TELEPHONE] = &_nl_C_LC_TELEPHONE, \
[LC_MEASUREMENT] = &_nl_C_LC_MEASUREMENT, \
[LC_IDENTIFICATION] = &_nl_C_LC_IDENTIFICATION \
}, \
.__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 \
}
struct __locale_struct _nl_C_locobj attribute_hidden = NL_C_INITIALIZER;
#ifdef SHARED
struct __locale_struct _nl_global_locale attribute_hidden = NL_C_INITIALIZER;
# if USE_TLS && HAVE___THREAD
/* The tsd macros don't permit an initializer. */
__thread void *__libc_tsd_LOCALE = &_nl_global_locale;
# else
__libc_tsd_define (, LOCALE)
void *__libc_tsd_LOCALE_data = &_nl_global_locale;
# endif
#endif