summaryrefslogtreecommitdiff
path: root/locale/setlocale.c
diff options
context:
space:
mode:
authorRoland McGrath <roland@gnu.org>2002-08-28 10:39:23 +0000
committerRoland McGrath <roland@gnu.org>2002-08-28 10:39:23 +0000
commit1a0d874ed44e1fe59470497d65af8822a1b3abb8 (patch)
treee182578150b4cc6ad70d2e39fba0baeea4e1ad49 /locale/setlocale.c
parentd10c64301e56bd9cb77f5f480ba62df683ddbc5f (diff)
Make uselocale support static linking.
* locale/xlocale.c: Revert changes putting _nl_global_locale here. This file again just defines _nl_C_locobj. (_nl_C_locobj): Use a categories.def iterator in the initializer. * locale/global-locale.c: New file. Define _nl_global_locale here, using all weak references in the initializer. * locale/Makefile (aux): Add global-locale. * locale/localeinfo.h (_nl_global_locale, _NL_CURRENT_LOCALE): Make these unconditional, along with the tsd decl. [!SHARED && HAVE___THREAD && HAVE_WEAK_SYMBOLS] (NL_CURRENT_INDIRECT): Define it under these conditions. [NL_CURRENT_INDIRECT]: Test this instead of [! SHARED]. Don't declare _nl_current. Declare _nl_current_LC_FOO as `extern __thread struct locale_data *const *'. [NL_CURRENT_INDIRECT] (_NL_CURRENT_DATA, _NL_CURRENT, _NL_CURRENT_WSTR): Add indirection. [NL_CURRENT_INDIRECT] (_NL_CURRENT_DEFINE): Rewritten. Define the thread variable _nl_current_LC_FOO and also a special absolute symbol _nl_current_LC_FOO_used. * locale/uselocale.c (__uselocale) [NL_CURRENT_INDIRECT]: Set each _nl_current_LC_FOO symbol to point into the new locale, using weak references to test if _nl_current_LC_FOO_used was linked in. * locale/setlocale.c [! SHARED]: Replace this conditional ... [NL_CURRENT_INDIRECT]: ... with this one. (_nl_current, _nl_C): Variables removed. [NL_CURRENT_INDIRECT] (_nl_current_used): New variable, table of weak references to _nl_current_LC_FOO_used. [NL_CURRENT_INDIRECT] (CATEGORY_USED): Define using that table. (free_category): New function, broken out of ... (free_mem): ... here. Call that. (free_mem) [NL_CURRENT_INDIRECT]: Use a categories.def iterator instead of a loop. __USING_NAMESPACE_C99 depending on _GLIBCPP_USE_NAMESPACES.
Diffstat (limited to 'locale/setlocale.c')
-rw-r--r--locale/setlocale.c139
1 files changed, 68 insertions, 71 deletions
diff --git a/locale/setlocale.c b/locale/setlocale.c
index 3c80379cf9..296903f24c 100644
--- a/locale/setlocale.c
+++ b/locale/setlocale.c
@@ -27,55 +27,39 @@
#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.
- extern const struct locale_data _nl_C_CATEGORY;
- This contains the built-in "C"/"POSIX" locale's data for CATEGORY.
- 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"
-#undef DEFINE_CATEGORY
-
-/* Array indexed by category of pointers to _nl_current_CATEGORY slots.
- Elements are zero for categories whose data is never used. */
-struct locale_data * *const _nl_current[] =
- {
-#define DEFINE_CATEGORY(category, category_name, items, a) \
- [category] = &_nl_current_##category,
-#include "categories.def"
-#undef DEFINE_CATEGORY
- /* We need this additional element to simplify the code. It must
- simply be != NULL. */
- [LC_ALL] = (struct locale_data **) ~0ul
- };
-
-/* Array indexed by category of pointers to _nl_C_CATEGORY slots.
- Elements are zero for categories whose data is never used. */
-struct locale_data *const _nl_C[] attribute_hidden =
+#ifdef NL_CURRENT_INDIRECT
+
+/* For each category declare a special external symbol
+ _nl_current_CATEGORY_used with a weak reference.
+ This symbol will is defined in lc-CATEGORY.c and will be linked in
+ if anything uses _nl_current_CATEGORY (also defined in that module).
+ Also use a weak reference for the _nl_current_CATEGORY thread variable. */
+
+# define DEFINE_CATEGORY(category, category_name, items, a) \
+ extern char _nl_current_##category##_used; \
+ weak_extern (_nl_current_##category##_used) \
+ weak_extern (_nl_current_##category)
+# include "categories.def"
+# undef DEFINE_CATEGORY
+
+/* Now define a table of flags based on those special weak symbols' values.
+ _nl_current_used[CATEGORY] will be zero if _nl_current_CATEGORY is not
+ linked in. */
+static char *const _nl_current_used[] =
{
-#define DEFINE_CATEGORY(category, category_name, items, a) \
- [category] = &_nl_C_##category,
-#include "categories.def"
-#undef DEFINE_CATEGORY
+# define DEFINE_CATEGORY(category, category_name, items, a) \
+ [category] = &_nl_current_##category##_used,
+# include "categories.def"
+# undef DEFINE_CATEGORY
};
-# define CATEGORY_USED(category) (_nl_current[category] != NULL)
+# define CATEGORY_USED(category) (_nl_current_used[category] != 0)
#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
@@ -211,13 +195,7 @@ setdata (int category, struct locale_data *data)
{
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]) ();
}
@@ -444,38 +422,57 @@ setlocale (int category, const char *locale)
}
libc_hidden_def (setlocale)
+static void
+free_category (int category,
+ struct locale_data *here, struct locale_data *c_data)
+{
+ struct loaded_l10nfile *runp = _nl_locale_file_list[category];
+
+ /* If this category is already "C" don't do anything. */
+ if (here != c_data)
+ {
+ /* We have to be prepared that sometime later we still
+ might need the locale information. */
+ setdata (category, c_data);
+ setname (category, _nl_C_name);
+ }
+
+ while (runp != NULL)
+ {
+ struct loaded_l10nfile *curr = runp;
+ struct locale_data *data = (struct locale_data *) runp->data;
+
+ if (data != NULL && data != c_data)
+ _nl_unload_locale (data);
+ runp = runp->next;
+ free ((char *) curr->filename);
+ free (curr);
+ }
+}
+
static void __attribute__ ((unused))
free_mem (void)
{
+#ifdef NL_CURRENT_INDIRECT
+ /* We don't use the loop because we want to have individual weak
+ symbol references here. */
+# define DEFINE_CATEGORY(category, category_name, items, a) \
+ if (CATEGORY_USED (category)) \
+ { \
+ extern struct locale_data _nl_C_##category; \
+ weak_extern (_nl_C_##category) \
+ free_category (category, *_nl_current_##category, &_nl_C_##category); \
+ }
+# include "categories.def"
+# undef DEFINE_CATEGORY
+#else
int category;
for (category = 0; category < __LC_LAST; ++category)
if (category != LC_ALL)
- {
- 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. */
- if (here != _nl_C[category])
- {
- /* We have to be prepared that sometime later we still
- might need the locale information. */
- setdata (category, _nl_C[category]);
- setname (category, _nl_C_name);
- }
-
- while (runp != NULL)
- {
- struct loaded_l10nfile *curr = runp;
- struct locale_data *data = (struct locale_data *) runp->data;
-
- if (data != NULL && data != _nl_C[category])
- _nl_unload_locale (data);
- runp = runp->next;
- free ((char *) curr->filename);
- free (curr);
- }
- }
+ free_category (category, _NL_CURRENT_DATA (category),
+ _nl_C_locobj.__locales[category]);
+#endif
setname (LC_ALL, _nl_C_name);