Back to index

glibc  2.9
uselocale.c
Go to the documentation of this file.
00001 /* uselocale -- fetch and set the current per-thread locale
00002    Copyright (C) 2002, 2004, 2007, 2008 Free Software Foundation, Inc.
00003    This file is part of the GNU C Library.
00004 
00005    The GNU C Library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Lesser General Public
00007    License as published by the Free Software Foundation; either
00008    version 2.1 of the License, or (at your option) any later version.
00009 
00010    The GNU C Library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Lesser General Public License for more details.
00014 
00015    You should have received a copy of the GNU Lesser General Public
00016    License along with the GNU C Library; if not, write to the Free
00017    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00018    02111-1307 USA.  */
00019 
00020 #include <locale.h>
00021 #include "localeinfo.h"
00022 #include <ctype.h>
00023 
00024 /* Switch the current thread's locale to DATASET.
00025    If DATASET is null, instead just return the current setting.
00026    The special value LC_GLOBAL_LOCALE is the initial setting
00027    for all threads, and means the thread uses the global
00028    setting controlled by `setlocale'.  */
00029 locale_t
00030 __uselocale (locale_t newloc)
00031 {
00032   locale_t oldloc = _NL_CURRENT_LOCALE;
00033 
00034   if (newloc != NULL)
00035     {
00036       const locale_t locobj
00037        = newloc == LC_GLOBAL_LOCALE ? &_nl_global_locale : newloc;
00038       __libc_tsd_set (__locale_t, LOCALE, locobj);
00039 
00040 #ifdef NL_CURRENT_INDIRECT
00041       /* Now we must update all the per-category thread-local variables to
00042         point into the new current locale for this thread.  The magic
00043         symbols _nl_current_LC_FOO_used are defined to meaningless values
00044         if _nl_current_LC_FOO was linked in.  By using weak references to
00045         both symbols and testing the address of _nl_current_LC_FOO_used,
00046         we can avoid accessing the _nl_current_LC_FOO thread-local
00047         variable at all when no code referring to it was linked in.  We
00048         need the special bogus symbol because while TLS symbols can be
00049         weak, there is no reasonable way to test for the default-zero
00050         value as with a heap symbol (taking the address would just use
00051         some bogus offset from our thread pointer).  */
00052 
00053 # define DEFINE_CATEGORY(category, category_name, items, a) \
00054       {                                                                     \
00055        extern char _nl_current_##category##_used;                           \
00056        weak_extern (_nl_current_##category##_used)                          \
00057        weak_extern (_nl_current_##category)                                 \
00058        if (&_nl_current_##category##_used != 0)                      \
00059          _nl_current_##category = &locobj->__locales[category];             \
00060       }
00061 # include "categories.def"
00062 # undef       DEFINE_CATEGORY
00063 #endif
00064 
00065       /* Update the special tsd cache of some locale data.  */
00066       __libc_tsd_set (const uint16_t *, CTYPE_B, (void *) locobj->__ctype_b);
00067       __libc_tsd_set (const int32_t *, CTYPE_TOLOWER,
00068                     (void *) locobj->__ctype_tolower);
00069       __libc_tsd_set (const int32_t *, CTYPE_TOUPPER,
00070                     (void *) locobj->__ctype_toupper);
00071     }
00072 
00073   return oldloc == &_nl_global_locale ? LC_GLOBAL_LOCALE : oldloc;
00074 }
00075 libc_hidden_def (__uselocale)
00076 weak_alias (__uselocale, uselocale)