
1: /* uselocale -- fetch and set the current per-thread locale 2: Copyright (C) 2002, 2004, 2007 Free Software Foundation, Inc. 3: This file is part of the GNU C Library. 4: 5: The GNU C Library is free software; you can redistribute it and/or 6: modify it under the terms of the GNU Lesser General Public 7: License as published by the Free Software Foundation; either 8: version 2.1 of the License, or (at your option) any later version. 9: 10: The GNU C Library is distributed in the hope that it will be useful, 11: but WITHOUT ANY WARRANTY; without even the implied warranty of 12: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13: Lesser General Public License for more details. 14: 15: You should have received a copy of the GNU Lesser General Public 16: License along with the GNU C Library; if not, write to the Free 17: Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 18: 02111-1307 USA. */ 19: 20: #include <locale.h> 21: #include "localeinfo.h" 22: #include <ctype.h> 23: 24: /* Switch the current thread's locale to DATASET. 25: If DATASET is null, instead just return the current setting. 26: The special value LC_GLOBAL_LOCALE is the initial setting 27: for all threads, and means the thread uses the global 28: setting controlled by `setlocale'. */ 29: locale_t 30: __uselocale (locale_t newloc) 31: { 32: locale_t oldloc = _NL_CURRENT_LOCALE; 33: 34: if (newloc != NULL) 35: { 36: const locale_t locobj 37: = newloc == LC_GLOBAL_LOCALE ? &_nl_global_locale : newloc; 38: __libc_tsd_set (LOCALE, locobj); 39: 40: #ifdef NL_CURRENT_INDIRECT 41: /* Now we must update all the per-category thread-local variables to 42: point into the new current locale for this thread. The magic 43: symbols _nl_current_LC_FOO_used are defined to meaningless values 44: if _nl_current_LC_FOO was linked in. By using weak references to 45: both symbols and testing the address of _nl_current_LC_FOO_used, 46: we can avoid accessing the _nl_current_LC_FOO thread-local 47: variable at all when no code referring to it was linked in. We 48: need the special bogus symbol because while TLS symbols can be 49: weak, there is no reasonable way to test for the default-zero 50: value as with a heap symbol (taking the address would just use 51: some bogus offset from our thread pointer). */ 52: 53: # define DEFINE_CATEGORY(category, category_name, items, a) \ 54: { \ 55: extern char _nl_current_##category##_used; \ 56: weak_extern (_nl_current_##category##_used) \ 57: weak_extern (_nl_current_##category) \ 58: if (&_nl_current_##category##_used != 0) \ 59: _nl_current_##category = &locobj->__locales[category]; \ 60: } 61: # include "categories.def" 62: # undef DEFINE_CATEGORY 63: #endif 64: 65: /* Update the special tsd cache of some locale data. */ 66: __libc_tsd_set (CTYPE_B, (void *) locobj->__ctype_b); 67: __libc_tsd_set (CTYPE_TOLOWER, (void *) locobj->__ctype_tolower); 68: __libc_tsd_set (CTYPE_TOUPPER, (void *) locobj->__ctype_toupper); 69: } 70: 71: return oldloc == &_nl_global_locale ? LC_GLOBAL_LOCALE : oldloc; 72: } 73: libc_hidden_def (__uselocale) 74: weak_alias (__uselocale, uselocale)