Blame locale/uselocale.c

Packit Service 82fcde
/* uselocale -- fetch and set the current per-thread locale
Packit Service 82fcde
   Copyright (C) 2002-2018 Free Software Foundation, Inc.
Packit Service 82fcde
   This file is part of the GNU C Library.
Packit Service 82fcde
Packit Service 82fcde
   The GNU C Library is free software; you can redistribute it and/or
Packit Service 82fcde
   modify it under the terms of the GNU Lesser General Public
Packit Service 82fcde
   License as published by the Free Software Foundation; either
Packit Service 82fcde
   version 2.1 of the License, or (at your option) any later version.
Packit Service 82fcde
Packit Service 82fcde
   The GNU C Library is distributed in the hope that it will be useful,
Packit Service 82fcde
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 82fcde
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service 82fcde
   Lesser General Public License for more details.
Packit Service 82fcde
Packit Service 82fcde
   You should have received a copy of the GNU Lesser General Public
Packit Service 82fcde
   License along with the GNU C Library; if not, see
Packit Service 82fcde
   <http://www.gnu.org/licenses/>.  */
Packit Service 82fcde
Packit Service 82fcde
#include <locale.h>
Packit Service 82fcde
#include "localeinfo.h"
Packit Service 82fcde
#include <ctype.h>
Packit Service 82fcde
Packit Service 82fcde
/* Switch the current thread's locale to DATASET.
Packit Service 82fcde
   If DATASET is null, instead just return the current setting.
Packit Service 82fcde
   The special value LC_GLOBAL_LOCALE is the initial setting
Packit Service 82fcde
   for all threads, and means the thread uses the global
Packit Service 82fcde
   setting controlled by `setlocale'.  */
Packit Service 82fcde
locale_t
Packit Service 82fcde
__uselocale (locale_t newloc)
Packit Service 82fcde
{
Packit Service 82fcde
  locale_t oldloc = _NL_CURRENT_LOCALE;
Packit Service 82fcde
Packit Service 82fcde
  if (newloc != NULL)
Packit Service 82fcde
    {
Packit Service 82fcde
      const locale_t locobj
Packit Service 82fcde
	= newloc == LC_GLOBAL_LOCALE ? &_nl_global_locale : newloc;
Packit Service 82fcde
      __libc_tsd_set (locale_t, LOCALE, locobj);
Packit Service 82fcde
Packit Service 82fcde
#ifdef NL_CURRENT_INDIRECT
Packit Service 82fcde
      /* Now we must update all the per-category thread-local variables to
Packit Service 82fcde
	 point into the new current locale for this thread.  The magic
Packit Service 82fcde
	 symbols _nl_current_LC_FOO_used are defined to meaningless values
Packit Service 82fcde
	 if _nl_current_LC_FOO was linked in.  By using weak references to
Packit Service 82fcde
	 both symbols and testing the address of _nl_current_LC_FOO_used,
Packit Service 82fcde
	 we can avoid accessing the _nl_current_LC_FOO thread-local
Packit Service 82fcde
	 variable at all when no code referring to it was linked in.  We
Packit Service 82fcde
	 need the special bogus symbol because while TLS symbols can be
Packit Service 82fcde
	 weak, there is no reasonable way to test for the default-zero
Packit Service 82fcde
	 value as with a heap symbol (taking the address would just use
Packit Service 82fcde
	 some bogus offset from our thread pointer).  */
Packit Service 82fcde
Packit Service 82fcde
# define DEFINE_CATEGORY(category, category_name, items, a) \
Packit Service 82fcde
      {									      \
Packit Service 82fcde
	extern char _nl_current_##category##_used;			      \
Packit Service 82fcde
	weak_extern (_nl_current_##category##_used)			      \
Packit Service 82fcde
	weak_extern (_nl_current_##category)				      \
Packit Service 82fcde
	if (&_nl_current_##category##_used != 0)			      \
Packit Service 82fcde
	  _nl_current_##category = &locobj->__locales[category];	      \
Packit Service 82fcde
      }
Packit Service 82fcde
# include "categories.def"
Packit Service 82fcde
# undef	DEFINE_CATEGORY
Packit Service 82fcde
#endif
Packit Service 82fcde
Packit Service 82fcde
      /* Update the special tsd cache of some locale data.  */
Packit Service 82fcde
      __libc_tsd_set (const uint16_t *, CTYPE_B, (void *) locobj->__ctype_b);
Packit Service 82fcde
      __libc_tsd_set (const int32_t *, CTYPE_TOLOWER,
Packit Service 82fcde
		      (void *) locobj->__ctype_tolower);
Packit Service 82fcde
      __libc_tsd_set (const int32_t *, CTYPE_TOUPPER,
Packit Service 82fcde
		      (void *) locobj->__ctype_toupper);
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  return oldloc == &_nl_global_locale ? LC_GLOBAL_LOCALE : oldloc;
Packit Service 82fcde
}
Packit Service 82fcde
libc_hidden_def (__uselocale)
Packit Service 82fcde
weak_alias (__uselocale, uselocale)