Blame locale/lc-ctype.c

Packit 6c4009
/* Define current locale data for LC_CTYPE category.
Packit 6c4009
   Copyright (C) 1995-2018 Free Software Foundation, Inc.
Packit 6c4009
   This file is part of the GNU C Library.
Packit 6c4009
Packit 6c4009
   The GNU C Library is free software; you can redistribute it and/or
Packit 6c4009
   modify it under the terms of the GNU Lesser General Public
Packit 6c4009
   License as published by the Free Software Foundation; either
Packit 6c4009
   version 2.1 of the License, or (at your option) any later version.
Packit 6c4009
Packit 6c4009
   The GNU C Library is distributed in the hope that it will be useful,
Packit 6c4009
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 6c4009
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 6c4009
   Lesser General Public License for more details.
Packit 6c4009
Packit 6c4009
   You should have received a copy of the GNU Lesser General Public
Packit 6c4009
   License along with the GNU C Library; if not, see
Packit 6c4009
   <http://www.gnu.org/licenses/>.  */
Packit 6c4009
Packit 6c4009
#include "localeinfo.h"
Packit 6c4009
#include <ctype.h>
Packit 6c4009
#include <endian.h>
Packit 6c4009
#include <stdint.h>
Packit 6c4009
Packit 6c4009
_NL_CURRENT_DEFINE (LC_CTYPE);
Packit 6c4009
Packit 6c4009
/* We are called after loading LC_CTYPE data to load it into
Packit 6c4009
   the variables used by the ctype.h macros.  */
Packit 6c4009
Packit 6c4009
Packit 6c4009
Packit 6c4009
void
Packit 6c4009
_nl_postload_ctype (void)
Packit 6c4009
{
Packit 6c4009
#define current(type,x,offset) \
Packit 6c4009
  ((const type *) _NL_CURRENT (LC_CTYPE, _NL_CTYPE_##x) + offset)
Packit 6c4009
Packit 6c4009
  const union locale_data_value *const ctypes
Packit 6c4009
    = _nl_global_locale.__locales[LC_CTYPE]->values;
Packit 6c4009
Packit 6c4009
/* These thread-local variables are defined in ctype-info.c.
Packit 6c4009
   The declarations here must match those in localeinfo.h.
Packit 6c4009
Packit 6c4009
   These point into arrays of 384, so they can be indexed by any `unsigned
Packit 6c4009
   char' value [0,255]; by EOF (-1); or by any `signed char' value
Packit 6c4009
   [-128,-1).  ISO C requires that the ctype functions work for `unsigned
Packit 6c4009
   char' values and for EOF; we also support negative `signed char' values
Packit 6c4009
   for broken old programs.  The case conversion arrays are of `int's
Packit 6c4009
   rather than `unsigned char's because tolower (EOF) must be EOF, which
Packit 6c4009
   doesn't fit into an `unsigned char'.  But today more important is that
Packit 6c4009
   the arrays are also used for multi-byte character sets.
Packit 6c4009
Packit 6c4009
   First we update the special members of _nl_global_locale as newlocale
Packit 6c4009
   would.  This is necessary for uselocale (LC_GLOBAL_LOCALE) to find these
Packit 6c4009
   values properly.  */
Packit 6c4009
Packit 6c4009
  _nl_global_locale.__ctype_b = (const unsigned short int *)
Packit 6c4009
    ctypes[_NL_ITEM_INDEX (_NL_CTYPE_CLASS)].string + 128;
Packit 6c4009
  _nl_global_locale.__ctype_tolower = (const int *)
Packit 6c4009
    ctypes[_NL_ITEM_INDEX (_NL_CTYPE_TOLOWER)].string + 128;
Packit 6c4009
  _nl_global_locale.__ctype_toupper = (const int *)
Packit 6c4009
    ctypes[_NL_ITEM_INDEX (_NL_CTYPE_TOUPPER)].string + 128;
Packit 6c4009
Packit 6c4009
  /* Next we must set the thread-local caches if and only if this thread is
Packit 6c4009
     in fact using the global locale.  */
Packit 6c4009
  if (_NL_CURRENT_LOCALE == &_nl_global_locale)
Packit 6c4009
    {
Packit 6c4009
      __libc_tsd_set (const uint16_t *, CTYPE_B,
Packit 6c4009
		      (void *) _nl_global_locale.__ctype_b);
Packit 6c4009
      __libc_tsd_set (const int32_t *, CTYPE_TOUPPER,
Packit 6c4009
		      (void *) _nl_global_locale.__ctype_toupper);
Packit 6c4009
      __libc_tsd_set (const int32_t *, CTYPE_TOLOWER,
Packit 6c4009
		      (void *) _nl_global_locale.__ctype_tolower);
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
#include <shlib-compat.h>
Packit 6c4009
#if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3)
Packit 6c4009
  /* We must use the exported names to access these so we are sure to
Packit 6c4009
     be accessing the main executable's copy if it has COPY relocs.  */
Packit 6c4009
Packit 6c4009
  extern const unsigned short int *__ctype_b; /* Characteristics.  */
Packit 6c4009
  extern const __int32_t *__ctype_tolower; /* Case conversions.  */
Packit 6c4009
  extern const __int32_t *__ctype_toupper; /* Case conversions.  */
Packit 6c4009
Packit 6c4009
  extern const uint32_t *__ctype32_b;
Packit 6c4009
  extern const uint32_t *__ctype32_toupper;
Packit 6c4009
  extern const uint32_t *__ctype32_tolower;
Packit 6c4009
Packit 6c4009
  /* We need the .symver declarations these macros generate so that
Packit 6c4009
     our references are explicitly bound to the versioned symbol names
Packit 6c4009
     rather than the unadorned names that are not exported.  When the
Packit 6c4009
     linker sees these bound to local symbols (as the unexported names are)
Packit 6c4009
     then it doesn't generate a proper relocation to the global symbols.
Packit 6c4009
     We need those relocations so that a versioned definition with a COPY
Packit 6c4009
     reloc in an executable will override the libc.so definition.  */
Packit 6c4009
Packit 6c4009
compat_symbol (libc, __ctype_b, __ctype_b, GLIBC_2_0);
Packit 6c4009
compat_symbol (libc, __ctype_tolower, __ctype_tolower, GLIBC_2_0);
Packit 6c4009
compat_symbol (libc, __ctype_toupper, __ctype_toupper, GLIBC_2_0);
Packit 6c4009
compat_symbol (libc, __ctype32_b, __ctype32_b, GLIBC_2_0);
Packit 6c4009
compat_symbol (libc, __ctype32_tolower, __ctype32_tolower, GLIBC_2_2);
Packit 6c4009
compat_symbol (libc, __ctype32_toupper, __ctype32_toupper, GLIBC_2_2);
Packit 6c4009
Packit 6c4009
  __ctype_b = current (uint16_t, CLASS, 128);
Packit 6c4009
  __ctype_toupper = current (int32_t, TOUPPER, 128);
Packit 6c4009
  __ctype_tolower = current (int32_t, TOLOWER, 128);
Packit 6c4009
  __ctype32_b = current (uint32_t, CLASS32, 0);
Packit 6c4009
  __ctype32_toupper = current (uint32_t, TOUPPER32, 0);
Packit 6c4009
  __ctype32_tolower = current (uint32_t, TOLOWER32, 0);
Packit 6c4009
#endif
Packit 6c4009
}