aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoland McGrath <roland@gnu.org>2002-08-04 01:41:55 +0000
committerRoland McGrath <roland@gnu.org>2002-08-04 01:41:55 +0000
commit30c14c31ae6ac7c8db692fc23d0901e4d479f7af (patch)
tree25e403cd215f6d2ca484ae20a51ae41019ce19db
parent* include/search.h: Use libc_hidden_proto for hsearch_r, lfind. (diff)
downloadglibc-30c14c31ae6ac7c8db692fc23d0901e4d479f7af.tar.gz
glibc-30c14c31ae6ac7c8db692fc23d0901e4d479f7af.tar.bz2
glibc-30c14c31ae6ac7c8db692fc23d0901e4d479f7af.zip
* 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.
-rw-r--r--ChangeLog48
-rw-r--r--include/locale.h5
-rw-r--r--intl/dcigettext.c2
-rw-r--r--locale/Makefile4
-rw-r--r--locale/Versions7
-rw-r--r--locale/duplocale.c1
-rw-r--r--locale/findlocale.c4
-rw-r--r--locale/freelocale.c1
-rw-r--r--locale/locale.h21
-rw-r--r--locale/localeinfo.h67
-rw-r--r--locale/localename.c42
-rw-r--r--locale/newlocale.c12
-rw-r--r--locale/setlocale.c46
-rw-r--r--locale/uselocale.c52
-rw-r--r--locale/xlocale.c57
15 files changed, 305 insertions, 64 deletions
diff --git a/ChangeLog b/ChangeLog
index e69a58930c..3025aeab19 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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.
diff --git a/include/locale.h b/include/locale.h
index a79888139b..b339953a93 100644
--- a/include/locale.h
+++ b/include/locale.h
@@ -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
diff --git a/intl/dcigettext.c b/intl/dcigettext.c
index eb74ac2704..344736e9de 100644
--- a/intl/dcigettext.c
+++ b/intl/dcigettext.c
@@ -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
diff --git a/locale/Makefile b/locale/Makefile
index 3b3af99171..ebcf7bd668 100644
--- a/locale/Makefile
+++ b/locale/Makefile
@@ -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
diff --git a/locale/Versions b/locale/Versions
index 094a392fac..bb875f84a4 100644
--- a/locale/Versions
+++ b/locale/Versions
@@ -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;
}
}
diff --git a/locale/duplocale.c b/locale/duplocale.c
index efbacbb724..f8e8e7299e 100644
--- a/locale/duplocale.c
+++ b/locale/duplocale.c
@@ -61,3 +61,4 @@ __duplocale (__locale_t dataset)
return result;
}
+weak_alias (__duplocale, duplocale)
diff --git a/locale/findlocale.c b/locale/findlocale.c
index 004f93b725..75784bab9f 100644
--- a/locale/findlocale.c
+++ b/locale/findlocale.c
@@ -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
diff --git a/locale/freelocale.c b/locale/freelocale.c
index 282d83853a..de7e554c84 100644
--- a/locale/freelocale.c
+++ b/locale/freelocale.c
@@ -48,3 +48,4 @@ __freelocale (__locale_t dataset)
/* It's done. */
__libc_lock_unlock (__libc_setlocale_lock);
}
+weak_alias (__freelocale, freelocale)
diff --git a/locale/locale.h b/locale/locale.h
index 9133038178..34463fd55e 100644
--- a/locale/locale.h
+++ b/locale/locale.h
@@ -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
diff --git a/locale/localeinfo.h b/locale/localeinfo.h
index 3a43469c84..97471e9be5 100644
--- a/locale/localeinfo.h
+++ b/locale/localeinfo.h
@@ -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
diff --git a/locale/localename.c b/locale/localename.c
new file mode 100644
index 0000000000..045cc712d2
--- /dev/null
+++ b/locale/localename.c
@@ -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
+}
diff --git a/locale/newlocale.c b/locale/newlocale.c
index 6306ba2a8a..1442f86e81 100644
--- a/locale/newlocale.c
+++ b/locale/newlocale.c
@@ -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)
diff --git a/locale/setlocale.c b/locale/setlocale.c
index 87573024d3..50963d152c 100644
--- a/locale/setlocale.c
+++ b/locale/setlocale.c
@@ -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. */
diff --git a/locale/uselocale.c b/locale/uselocale.c
new file mode 100644
index 0000000000..1e819381de
--- /dev/null
+++ b/locale/uselocale.c
@@ -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
diff --git a/locale/xlocale.c b/locale/xlocale.c
index 79ec548473..daea563ff1 100644
--- a/locale/xlocale.c
+++ b/locale/xlocale.c
@@ -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