aboutsummaryrefslogtreecommitdiff
path: root/locale
diff options
context:
space:
mode:
Diffstat (limited to 'locale')
-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
12 files changed, 251 insertions, 63 deletions
diff --git a/locale/Makefile b/locale/Makefile
index 3b3af99..ebcf7bd 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 094a392..bb875f8 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 efbacbb..f8e8e72 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 004f93b..75784ba 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 282d838..de7e554 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 9133038..34463fd 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 3a43469..97471e9 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 0000000..045cc71
--- /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 6306ba2..1442f86 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 8757302..50963d1 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 0000000..1e81938
--- /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 79ec548..daea563 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