summary refs log tree commit diff
path: root/locale/uselocale.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/uselocale.c
parentd10c64301e56bd9cb77f5f480ba62df683ddbc5f (diff)
downloadglibc-1a0d874ed44e1fe59470497d65af8822a1b3abb8.tar.gz
glibc-1a0d874ed44e1fe59470497d65af8822a1b3abb8.tar.xz
glibc-1a0d874ed44e1fe59470497d65af8822a1b3abb8.zip
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/uselocale.c')
-rw-r--r--locale/uselocale.c42
1 files changed, 30 insertions, 12 deletions
diff --git a/locale/uselocale.c b/locale/uselocale.c
index 1e819381de..d5e53113c1 100644
--- a/locale/uselocale.c
+++ b/locale/uselocale.c
@@ -20,8 +20,6 @@
 #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
@@ -35,18 +33,38 @@ __uselocale (locale_t newloc)
       locale_t loc = __libc_tsd_get (LOCALE);
       return loc == &_nl_global_locale ? LC_GLOBAL_LOCALE : loc;
     }
-  if (newloc == LC_GLOBAL_LOCALE)
+  else
     {
-      __libc_tsd_set (LOCALE, &_nl_global_locale);
-      return LC_GLOBAL_LOCALE;
+      const locale_t locobj
+	= newloc == LC_GLOBAL_LOCALE ? &_nl_global_locale : newloc;
+      __libc_tsd_set (LOCALE, locobj);
+
+#ifdef NL_CURRENT_INDIRECT
+      /* Now we must update all the per-category thread-local variables to
+	 point into the new current locale for this thread.  The magic
+	 symbols _nl_current_LC_FOO_used are defined to meaningless values
+	 if _nl_current_LC_FOO was linked in.  By using weak references to
+	 both symbols and testing the address of _nl_current_LC_FOO_used,
+	 we can avoid accessing the _nl_current_LC_FOO thread-local
+	 variable at all when no code referring to it was linked in.  We
+	 need the special bogus symbol because while TLS symbols can be
+	 weak, there is no reasonable way to test for the default-zero
+	 value as with a heap symbol (taking the address would just use
+	 some bogus offset from our thread pointer).  */
+
+# 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)				      \
+	if (&_nl_current_##category##_used != 0)			      \
+	  _nl_current_##category = &locobj->__locales[category];	      \
+      }
+# include "categories.def"
+# undef	DEFINE_CATEGORY
+#endif
     }
-  __libc_tsd_set (LOCALE, newloc);
+
   return newloc;
 }
 weak_alias (__uselocale, uselocale)
-
-#else
-
-# warning uselocale not implemented for static linking yet
-
-#endif