1 | /* Declarations for internal libc locale interfaces |
2 | Copyright (C) 1995-2021 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 | #ifndef _LOCALEINFO_H |
20 | #define _LOCALEINFO_H 1 |
21 | |
22 | #include <stddef.h> |
23 | #include <langinfo.h> |
24 | #include <limits.h> |
25 | #include <locale.h> |
26 | #include <time.h> |
27 | #include <stdint.h> |
28 | #include <sys/types.h> |
29 | |
30 | #include <intl/loadinfo.h> /* For loaded_l10nfile definition. */ |
31 | |
32 | /* Magic number at the beginning of a locale data file for CATEGORY. */ |
33 | #define LIMAGIC(category) \ |
34 | (category == LC_COLLATE \ |
35 | ? ((unsigned int) (0x20051014 ^ (category))) \ |
36 | : category == LC_CTYPE \ |
37 | ? ((unsigned int) (0x20090720 ^ (category))) \ |
38 | : ((unsigned int) (0x20031115 ^ (category)))) |
39 | |
40 | /* Two special weight constants for the collation data. */ |
41 | #define IGNORE_CHAR 2 |
42 | |
43 | /* We use a special value for the usage counter in `__locale_data' to |
44 | signal that this data must never be removed anymore. */ |
45 | #define MAX_USAGE_COUNT (UINT_MAX - 1) |
46 | #define UNDELETABLE UINT_MAX |
47 | |
48 | /* Structure describing locale data in core for a category. */ |
49 | struct __locale_data |
50 | { |
51 | const char *name; |
52 | const char *filedata; /* Region mapping the file data. */ |
53 | off_t filesize; /* Size of the file (and the region). */ |
54 | enum /* Flavor of storage used for those. */ |
55 | { |
56 | ld_malloced, /* Both are malloc'd. */ |
57 | ld_mapped, /* name is malloc'd, filedata mmap'd */ |
58 | ld_archive /* Both point into mmap'd archive regions. */ |
59 | } alloc; |
60 | |
61 | /* This provides a slot for category-specific code to cache data computed |
62 | about this locale. That code can set a cleanup function to deallocate |
63 | the data. */ |
64 | struct |
65 | { |
66 | void (*cleanup) (struct __locale_data *); |
67 | union |
68 | { |
69 | void *data; |
70 | struct lc_time_data *time; |
71 | const struct gconv_fcts *ctype; |
72 | }; |
73 | } private; |
74 | |
75 | unsigned int usage_count; /* Counter for users. */ |
76 | |
77 | int use_translit; /* Nonzero if the mb*towv*() and wc*tomb() |
78 | functions should use transliteration. */ |
79 | |
80 | unsigned int nstrings; /* Number of strings below. */ |
81 | union locale_data_value |
82 | { |
83 | const uint32_t *wstr; |
84 | const char *string; |
85 | unsigned int word; /* Note endian issues vs 64-bit pointers. */ |
86 | } |
87 | values __flexarr; /* Items, usually pointers into `filedata'. */ |
88 | }; |
89 | |
90 | /* This alignment is used for 32-bit integers in locale files, both |
91 | those that are explicitly int32_t or uint32_t and those that are |
92 | wchar_t, regardless of the (possibly smaller) alignment required |
93 | for such integers on a particular host. */ |
94 | #define LOCFILE_ALIGN sizeof (int32_t) |
95 | #define LOCFILE_ALIGN_MASK (LOCFILE_ALIGN - 1) |
96 | #define LOCFILE_ALIGN_UP(x) (((x) + LOCFILE_ALIGN - 1) \ |
97 | & ~LOCFILE_ALIGN_MASK) |
98 | #define LOCFILE_ALIGNED_P(x) (((x) & LOCFILE_ALIGN_MASK) == 0) |
99 | |
100 | /* We know three kinds of collation sorting rules. */ |
101 | enum coll_sort_rule |
102 | { |
103 | illegal_0__, |
104 | sort_forward, |
105 | sort_backward, |
106 | illegal_3__, |
107 | sort_position, |
108 | sort_forward_position, |
109 | sort_backward_position, |
110 | sort_mask |
111 | }; |
112 | |
113 | /* We can map the types of the entries into a few categories. */ |
114 | enum value_type |
115 | { |
116 | none, |
117 | string, |
118 | stringarray, |
119 | byte, |
120 | bytearray, |
121 | word, |
122 | stringlist, |
123 | wordarray, |
124 | wstring, |
125 | wstringarray, |
126 | wstringlist |
127 | }; |
128 | |
129 | |
130 | /* Definitions for `era' information from LC_TIME. */ |
131 | #define ERA_NAME_FORMAT_MEMBERS 4 |
132 | #define ERA_M_NAME 0 |
133 | #define ERA_M_FORMAT 1 |
134 | #define ERA_W_NAME 2 |
135 | #define ERA_W_FORMAT 3 |
136 | |
137 | |
138 | /* Structure to access `era' information from LC_TIME. */ |
139 | struct era_entry |
140 | { |
141 | uint32_t direction; /* Contains '+' or '-'. */ |
142 | int32_t offset; |
143 | int32_t start_date[3]; |
144 | int32_t stop_date[3]; |
145 | const char *era_name; |
146 | const char *era_format; |
147 | const wchar_t *era_wname; |
148 | const wchar_t *era_wformat; |
149 | int absolute_direction; |
150 | /* absolute direction: |
151 | +1 indicates that year number is higher in the future. (like A.D.) |
152 | -1 indicates that year number is higher in the past. (like B.C.) */ |
153 | }; |
154 | |
155 | /* Structure caching computed data about information from LC_TIME. |
156 | The `private.time' member of `struct __locale_data' points to this. */ |
157 | struct lc_time_data |
158 | { |
159 | struct era_entry *eras; |
160 | size_t num_eras; |
161 | int era_initialized; |
162 | |
163 | const char **alt_digits; |
164 | const wchar_t **walt_digits; |
165 | int alt_digits_initialized; |
166 | int walt_digits_initialized; |
167 | }; |
168 | |
169 | |
170 | /* LC_CTYPE specific: |
171 | Hardwired indices for standard wide character translation mappings. */ |
172 | enum |
173 | { |
174 | __TOW_toupper = 0, |
175 | __TOW_tolower = 1 |
176 | }; |
177 | |
178 | |
179 | /* LC_CTYPE specific: |
180 | Access a wide character class with a single character index. |
181 | _ISCTYPE (c, desc) = iswctype (btowc (c), desc). |
182 | c must be an `unsigned char'. desc must be a nonzero wctype_t. */ |
183 | #define _ISCTYPE(c, desc) \ |
184 | (((((const uint32_t *) (desc)) - 8)[(c) >> 5] >> ((c) & 0x1f)) & 1) |
185 | |
186 | /* Category name handling variables. Concatenate all the strings in a |
187 | single object to minimize relocations. Individual strings can be |
188 | accessed using _nl_category_names. */ |
189 | #define CATNAMEMF(line) CATNAMEMF1 (line) |
190 | #define CATNAMEMF1(line) str##line |
191 | extern const struct catnamestr_t |
192 | { |
193 | #define DEFINE_CATEGORY(category, category_name, items, a) \ |
194 | char CATNAMEMF (__LINE__)[sizeof (category_name)]; |
195 | #include "categories.def" |
196 | #undef DEFINE_CATEGORY |
197 | } _nl_category_names attribute_hidden; |
198 | extern const uint8_t _nl_category_name_idxs[__LC_LAST] attribute_hidden; |
199 | extern const uint8_t _nl_category_name_sizes[__LC_LAST] attribute_hidden; |
200 | |
201 | /* Return the name of the category INDEX, which must be nonnegative |
202 | and less than _LC_LAST. */ |
203 | static inline const char * |
204 | _nl_category_names_get (int index) |
205 | { |
206 | return (const char *) &_nl_category_names + _nl_category_name_idxs[index]; |
207 | } |
208 | |
209 | /* Name of the standard locales. */ |
210 | extern const char _nl_C_name[] attribute_hidden; |
211 | extern const char _nl_POSIX_name[] attribute_hidden; |
212 | |
213 | /* The standard codeset. */ |
214 | extern const char _nl_C_codeset[] attribute_hidden; |
215 | |
216 | /* This is the internal locale_t object that holds the global locale |
217 | controlled by calls to setlocale. A thread's TSD locale pointer |
218 | points to this when `uselocale (LC_GLOBAL_LOCALE)' is in effect. */ |
219 | extern struct __locale_struct _nl_global_locale attribute_hidden; |
220 | |
221 | /* This fetches the thread-local locale_t pointer, either one set with |
222 | uselocale or &_nl_global_locale. */ |
223 | #define _NL_CURRENT_LOCALE (__libc_tsd_get (locale_t, LOCALE)) |
224 | #include <libc-tsd.h> |
225 | __libc_tsd_define (extern, locale_t, LOCALE) |
226 | |
227 | |
228 | /* For static linking it is desireable to avoid always linking in the code |
229 | and data for every category when we can tell at link time that they are |
230 | unused. We can manage this playing some tricks with weak references. |
231 | But with thread-local locale settings, it becomes quite ungainly unless |
232 | we can use __thread variables. So only in that case do we attempt this. */ |
233 | #ifndef SHARED |
234 | # include <tls.h> |
235 | # define NL_CURRENT_INDIRECT 1 |
236 | #endif |
237 | |
238 | #ifdef NL_CURRENT_INDIRECT |
239 | |
240 | /* For each category declare the thread-local variable for the current |
241 | locale data. This has an extra indirection so it points at the |
242 | __locales[CATEGORY] element in either _nl_global_locale or the current |
243 | locale object set by uselocale, which points at the actual data. The |
244 | reason for having these variables is so that references to particular |
245 | categories will link in the lc-CATEGORY.c module to define this symbol, |
246 | and we arrange that linking that module is what brings in all the code |
247 | associated with this category. */ |
248 | #define DEFINE_CATEGORY(category, category_name, items, a) \ |
249 | extern __thread struct __locale_data *const *_nl_current_##category \ |
250 | attribute_hidden attribute_tls_model_ie; |
251 | #include "categories.def" |
252 | #undef DEFINE_CATEGORY |
253 | |
254 | /* Return a pointer to the current `struct __locale_data' for CATEGORY. */ |
255 | #define _NL_CURRENT_DATA(category) (*_nl_current_##category) |
256 | |
257 | /* Extract the current CATEGORY locale's string for ITEM. */ |
258 | #define _NL_CURRENT(category, item) \ |
259 | ((*_nl_current_##category)->values[_NL_ITEM_INDEX (item)].string) |
260 | |
261 | /* Extract the current CATEGORY locale's string for ITEM. */ |
262 | #define _NL_CURRENT_WSTR(category, item) \ |
263 | ((wchar_t *) (*_nl_current_##category)->values[_NL_ITEM_INDEX (item)].wstr) |
264 | |
265 | /* Extract the current CATEGORY locale's word for ITEM. */ |
266 | #define _NL_CURRENT_WORD(category, item) \ |
267 | ((uint32_t) (*_nl_current_##category)->values[_NL_ITEM_INDEX (item)].word) |
268 | |
269 | /* This is used in lc-CATEGORY.c to define _nl_current_CATEGORY. The symbol |
270 | _nl_current_CATEGORY_used is set to a value unequal to zero to mark this |
271 | category as used. On S390 the used relocation to load the symbol address |
272 | can only handle even addresses. */ |
273 | #define _NL_CURRENT_DEFINE(category) \ |
274 | __thread struct __locale_data *const *_nl_current_##category \ |
275 | attribute_hidden = &_nl_global_locale.__locales[category]; \ |
276 | asm (".globl " __SYMBOL_PREFIX "_nl_current_" #category "_used\n" \ |
277 | _NL_CURRENT_DEFINE_ABS (_nl_current_##category##_used, 2)); |
278 | #ifdef HAVE_ASM_SET_DIRECTIVE |
279 | # define _NL_CURRENT_DEFINE_ABS(sym, val) ".set " #sym ", " #val |
280 | #else |
281 | # define _NL_CURRENT_DEFINE_ABS(sym, val) #sym " = " #val |
282 | #endif |
283 | |
284 | #else |
285 | |
286 | /* All categories are always loaded in the shared library, so there is no |
287 | point in having lots of separate symbols for linking. */ |
288 | |
289 | /* Return a pointer to the current `struct __locale_data' for CATEGORY. */ |
290 | # define _NL_CURRENT_DATA(category) \ |
291 | (_NL_CURRENT_LOCALE->__locales[category]) |
292 | |
293 | /* Extract the current CATEGORY locale's string for ITEM. */ |
294 | # define _NL_CURRENT(category, item) \ |
295 | (_NL_CURRENT_DATA (category)->values[_NL_ITEM_INDEX (item)].string) |
296 | |
297 | /* Extract the current CATEGORY locale's string for ITEM. */ |
298 | # define _NL_CURRENT_WSTR(category, item) \ |
299 | ((wchar_t *) _NL_CURRENT_DATA (category)->values[_NL_ITEM_INDEX (item)].wstr) |
300 | |
301 | /* Extract the current CATEGORY locale's word for ITEM. */ |
302 | # define _NL_CURRENT_WORD(category, item) \ |
303 | ((uint32_t) _NL_CURRENT_DATA (category)->values[_NL_ITEM_INDEX (item)].word) |
304 | |
305 | /* This is used in lc-CATEGORY.c to define _nl_current_CATEGORY. */ |
306 | # define _NL_CURRENT_DEFINE(category) \ |
307 | /* No per-category variable here. */ |
308 | |
309 | #endif |
310 | |
311 | /* Extract CATEGORY locale's string for ITEM. */ |
312 | static inline const char * |
313 | _nl_lookup (locale_t l, int category, int item) |
314 | { |
315 | return l->__locales[category]->values[_NL_ITEM_INDEX (item)].string; |
316 | } |
317 | |
318 | /* Extract CATEGORY locale's wide string for ITEM. */ |
319 | static inline const wchar_t * |
320 | _nl_lookup_wstr (locale_t l, int category, int item) |
321 | { |
322 | return (wchar_t *) l->__locales[category] |
323 | ->values[_NL_ITEM_INDEX (item)].wstr; |
324 | } |
325 | |
326 | /* Extract the CATEGORY locale's word for ITEM. */ |
327 | static inline uint32_t |
328 | _nl_lookup_word (locale_t l, int category, int item) |
329 | { |
330 | return l->__locales[category]->values[_NL_ITEM_INDEX (item)].word; |
331 | } |
332 | |
333 | /* Default search path if no LOCPATH environment variable. */ |
334 | extern const char _nl_default_locale_path[] attribute_hidden; |
335 | |
336 | /* Load the locale data for CATEGORY from the file specified by *NAME. |
337 | If *NAME is "", use environment variables as specified by POSIX, and |
338 | fill in *NAME with the actual name used. If LOCALE_PATH is not null, |
339 | those directories are searched for the locale files. If it's null, |
340 | the locale archive is checked first and then _nl_default_locale_path |
341 | is searched for locale files. */ |
342 | extern struct __locale_data *_nl_find_locale (const char *locale_path, |
343 | size_t locale_path_len, |
344 | int category, const char **name) |
345 | attribute_hidden; |
346 | |
347 | /* Try to load the file described by FILE. */ |
348 | extern void _nl_load_locale (struct loaded_l10nfile *file, int category) |
349 | attribute_hidden; |
350 | |
351 | /* Free all resource. */ |
352 | extern void _nl_unload_locale (struct __locale_data *locale) attribute_hidden; |
353 | |
354 | /* Free the locale and give back all memory if the usage count is one. */ |
355 | extern void _nl_remove_locale (int locale, struct __locale_data *data) |
356 | attribute_hidden; |
357 | |
358 | /* Find the locale *NAMEP in the locale archive, and return the |
359 | internalized data structure for its CATEGORY data. If this locale has |
360 | already been loaded from the archive, just returns the existing data |
361 | structure. If successful, sets *NAMEP to point directly into the mapped |
362 | archive string table; that way, the next call can short-circuit strcmp. */ |
363 | extern struct __locale_data *_nl_load_locale_from_archive (int category, |
364 | const char **namep) |
365 | attribute_hidden; |
366 | |
367 | /* Subroutine of setlocale's __libc_subfreeres hook. */ |
368 | extern void _nl_archive_subfreeres (void) attribute_hidden; |
369 | |
370 | /* Subroutine of gconv-db's __libc_subfreeres hook. */ |
371 | extern void _nl_locale_subfreeres (void) attribute_hidden; |
372 | |
373 | /* Validate the contents of a locale file and set up the in-core |
374 | data structure to point into the data. This leaves the `alloc' |
375 | and `name' fields uninitialized, for the caller to fill in. |
376 | If any bogons are detected in the data, this will refuse to |
377 | intern it, and return a null pointer instead. */ |
378 | extern struct __locale_data *_nl_intern_locale_data (int category, |
379 | const void *data, |
380 | size_t datasize) |
381 | attribute_hidden; |
382 | |
383 | |
384 | /* Return `era' entry which corresponds to TP. Used in strftime. */ |
385 | extern struct era_entry *_nl_get_era_entry (const struct tm *tp, |
386 | struct __locale_data *lc_time) |
387 | attribute_hidden; |
388 | |
389 | /* Return `era' cnt'th entry . Used in strptime. */ |
390 | extern struct era_entry *_nl_select_era_entry (int cnt, |
391 | struct __locale_data *lc_time) |
392 | attribute_hidden; |
393 | |
394 | /* Return `alt_digit' which corresponds to NUMBER. Used in strftime. */ |
395 | extern const char *_nl_get_alt_digit (unsigned int number, |
396 | struct __locale_data *lc_time) |
397 | attribute_hidden; |
398 | |
399 | /* Similar, but now for wide characters. */ |
400 | extern const wchar_t *_nl_get_walt_digit (unsigned int number, |
401 | struct __locale_data *lc_time) |
402 | attribute_hidden; |
403 | |
404 | /* Parse string as alternative digit and return numeric value. */ |
405 | extern int _nl_parse_alt_digit (const char **strp, |
406 | struct __locale_data *lc_time) |
407 | attribute_hidden; |
408 | |
409 | /* Postload processing. */ |
410 | extern void _nl_postload_ctype (void); |
411 | |
412 | /* Functions used for the `private.cleanup' hook. */ |
413 | extern void _nl_cleanup_time (struct __locale_data *) attribute_hidden; |
414 | |
415 | |
416 | #endif /* localeinfo.h */ |
417 | |