(root)/
glibc-2.38/
locale/
uselocale.c
       1  /* uselocale -- fetch and set the current per-thread locale
       2     Copyright (C) 2002-2023 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, see
      17     <https://www.gnu.org/licenses/>.  */
      18  
      19  #include <locale.h>
      20  #include "localeinfo.h"
      21  #include <ctype.h>
      22  
      23  /* Switch the current thread's locale to DATASET.
      24     If DATASET is null, instead just return the current setting.
      25     The special value LC_GLOBAL_LOCALE is the initial setting
      26     for all threads, and means the thread uses the global
      27     setting controlled by `setlocale'.  */
      28  locale_t
      29  __uselocale (locale_t newloc)
      30  {
      31    locale_t oldloc = _NL_CURRENT_LOCALE;
      32  
      33    if (newloc != NULL)
      34      {
      35        const locale_t locobj
      36  	= newloc == LC_GLOBAL_LOCALE ? &_nl_global_locale : newloc;
      37        __libc_tsd_set (locale_t, LOCALE, locobj);
      38  
      39  #ifdef NL_CURRENT_INDIRECT
      40        /* Now we must update all the per-category thread-local variables to
      41  	 point into the new current locale for this thread.  The magic
      42  	 symbols _nl_current_LC_FOO_used are defined to meaningless values
      43  	 if _nl_current_LC_FOO was linked in.  By using weak references to
      44  	 both symbols and testing the address of _nl_current_LC_FOO_used,
      45  	 we can avoid accessing the _nl_current_LC_FOO thread-local
      46  	 variable at all when no code referring to it was linked in.  We
      47  	 need the special bogus symbol because while TLS symbols can be
      48  	 weak, there is no reasonable way to test for the default-zero
      49  	 value as with a heap symbol (taking the address would just use
      50  	 some bogus offset from our thread pointer).  */
      51  
      52  # define DEFINE_CATEGORY(category, category_name, items, a) \
      53        {									      \
      54  	extern char _nl_current_##category##_used;			      \
      55  	weak_extern (_nl_current_##category##_used)			      \
      56  	weak_extern (_nl_current_##category)				      \
      57  	if (&_nl_current_##category##_used != 0)			      \
      58  	  _nl_current_##category = &locobj->__locales[category];	      \
      59        }
      60  # include "categories.def"
      61  # undef	DEFINE_CATEGORY
      62  #endif
      63  
      64        /* Update the special tsd cache of some locale data.  */
      65        __libc_tsd_set (const uint16_t *, CTYPE_B, (void *) locobj->__ctype_b);
      66        __libc_tsd_set (const int32_t *, CTYPE_TOLOWER,
      67  		      (void *) locobj->__ctype_tolower);
      68        __libc_tsd_set (const int32_t *, CTYPE_TOUPPER,
      69  		      (void *) locobj->__ctype_toupper);
      70      }
      71  
      72    return oldloc == &_nl_global_locale ? LC_GLOBAL_LOCALE : oldloc;
      73  }
      74  libc_hidden_def (__uselocale)
      75  weak_alias (__uselocale, uselocale)