1 | /* Define current locale data for LC_CTYPE category. |
2 | Copyright (C) 1995-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 "localeinfo.h" |
20 | #include <ctype.h> |
21 | #include <endian.h> |
22 | #include <stdint.h> |
23 | |
24 | _NL_CURRENT_DEFINE (LC_CTYPE); |
25 | |
26 | /* We are called after loading LC_CTYPE data to load it into |
27 | the variables used by the ctype.h macros. */ |
28 | |
29 | |
30 | |
31 | void |
32 | _nl_postload_ctype (void) |
33 | { |
34 | #define current(type,x,offset) \ |
35 | ((const type *) _NL_CURRENT (LC_CTYPE, _NL_CTYPE_##x) + offset) |
36 | |
37 | const union locale_data_value *const ctypes |
38 | = _nl_global_locale.__locales[LC_CTYPE]->values; |
39 | |
40 | /* These thread-local variables are defined in ctype-info.c. |
41 | The declarations here must match those in localeinfo.h. |
42 | |
43 | These point into arrays of 384, so they can be indexed by any `unsigned |
44 | char' value [0,255]; by EOF (-1); or by any `signed char' value |
45 | [-128,-1). ISO C requires that the ctype functions work for `unsigned |
46 | char' values and for EOF; we also support negative `signed char' values |
47 | for broken old programs. The case conversion arrays are of `int's |
48 | rather than `unsigned char's because tolower (EOF) must be EOF, which |
49 | doesn't fit into an `unsigned char'. But today more important is that |
50 | the arrays are also used for multi-byte character sets. |
51 | |
52 | First we update the special members of _nl_global_locale as newlocale |
53 | would. This is necessary for uselocale (LC_GLOBAL_LOCALE) to find these |
54 | values properly. */ |
55 | |
56 | _nl_global_locale.__ctype_b = (const unsigned short int *) |
57 | ctypes[_NL_ITEM_INDEX (_NL_CTYPE_CLASS)].string + 128; |
58 | _nl_global_locale.__ctype_tolower = (const int *) |
59 | ctypes[_NL_ITEM_INDEX (_NL_CTYPE_TOLOWER)].string + 128; |
60 | _nl_global_locale.__ctype_toupper = (const int *) |
61 | ctypes[_NL_ITEM_INDEX (_NL_CTYPE_TOUPPER)].string + 128; |
62 | |
63 | /* Next we must set the thread-local caches if and only if this thread is |
64 | in fact using the global locale. */ |
65 | if (_NL_CURRENT_LOCALE == &_nl_global_locale) |
66 | { |
67 | __libc_tsd_set (const uint16_t *, CTYPE_B, |
68 | (void *) _nl_global_locale.__ctype_b); |
69 | __libc_tsd_set (const int32_t *, CTYPE_TOUPPER, |
70 | (void *) _nl_global_locale.__ctype_toupper); |
71 | __libc_tsd_set (const int32_t *, CTYPE_TOLOWER, |
72 | (void *) _nl_global_locale.__ctype_tolower); |
73 | } |
74 | |
75 | #include <shlib-compat.h> |
76 | #if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3) |
77 | /* We must use the exported names to access these so we are sure to |
78 | be accessing the main executable's copy if it has COPY relocs. */ |
79 | |
80 | extern const unsigned short int *__ctype_b; /* Characteristics. */ |
81 | extern const __int32_t *__ctype_tolower; /* Case conversions. */ |
82 | extern const __int32_t *__ctype_toupper; /* Case conversions. */ |
83 | |
84 | extern const uint32_t *__ctype32_b; |
85 | extern const uint32_t *__ctype32_toupper; |
86 | extern const uint32_t *__ctype32_tolower; |
87 | |
88 | /* We need the .symver declarations these macros generate so that |
89 | our references are explicitly bound to the versioned symbol names |
90 | rather than the unadorned names that are not exported. When the |
91 | linker sees these bound to local symbols (as the unexported names are) |
92 | then it doesn't generate a proper relocation to the global symbols. |
93 | We need those relocations so that a versioned definition with a COPY |
94 | reloc in an executable will override the libc.so definition. */ |
95 | |
96 | compat_symbol_reference (libc, __ctype_b, __ctype_b, GLIBC_2_0); |
97 | compat_symbol_reference (libc, __ctype_tolower, __ctype_tolower, GLIBC_2_0); |
98 | compat_symbol_reference (libc, __ctype_toupper, __ctype_toupper, GLIBC_2_0); |
99 | compat_symbol_reference (libc, __ctype32_b, __ctype32_b, GLIBC_2_0); |
100 | compat_symbol_reference (libc, __ctype32_tolower, __ctype32_tolower, |
101 | GLIBC_2_2); |
102 | compat_symbol_reference (libc, __ctype32_toupper, __ctype32_toupper, |
103 | GLIBC_2_2); |
104 | |
105 | __ctype_b = current (uint16_t, CLASS, 128); |
106 | __ctype_toupper = current (int32_t, TOUPPER, 128); |
107 | __ctype_tolower = current (int32_t, TOLOWER, 128); |
108 | __ctype32_b = current (uint32_t, CLASS32, 0); |
109 | __ctype32_toupper = current (uint32_t, TOUPPER32, 0); |
110 | __ctype32_tolower = current (uint32_t, TOLOWER32, 0); |
111 | #endif |
112 | } |
113 | |