Update copyright dates with scripts/update-copyrights
[glibc.git] / intl / loadmsgcat.c
blob992489758c18e87359df4150266cdd75d1fa84be
1 /* Load needed message catalogs.
2 Copyright (C) 1995-2023 Free Software Foundation, Inc.
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU Lesser General Public License as published by
6 the Free Software Foundation; either version 2.1 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU Lesser General Public License for more details.
14 You should have received a copy of the GNU Lesser General Public License
15 along with this program. If not, see <https://www.gnu.org/licenses/>. */
17 /* Tell glibc's <string.h> to provide a prototype for mempcpy().
18 This must come before <config.h> because <config.h> may include
19 <features.h>, and once <features.h> has been included, it's too late. */
20 #ifndef _GNU_SOURCE
21 # define _GNU_SOURCE 1
22 #endif
24 #ifdef HAVE_CONFIG_H
25 # include <config.h>
26 #endif
28 #include <assert.h>
29 #include <ctype.h>
30 #include <errno.h>
31 #include <fcntl.h>
32 #include <sys/types.h>
33 #include <sys/stat.h>
35 #include <stdlib.h>
36 #include <string.h>
38 #if defined HAVE_UNISTD_H || defined _LIBC
39 # include <unistd.h>
40 #endif
42 #ifdef _LIBC
43 # include <langinfo.h>
44 # include <locale.h>
45 #endif
47 #if (defined HAVE_MMAP && defined HAVE_MUNMAP && !defined DISALLOW_MMAP) \
48 || (defined _LIBC && defined _POSIX_MAPPED_FILES)
49 # include <sys/mman.h>
50 # undef HAVE_MMAP
51 # define HAVE_MMAP 1
52 #else
53 # undef HAVE_MMAP
54 #endif
56 #if defined HAVE_STDINT_H_WITH_UINTMAX || defined _LIBC
57 # include <stdint.h>
58 #endif
59 #if defined HAVE_INTTYPES_H || defined _LIBC
60 # include <inttypes.h>
61 #endif
63 #include "gmo.h"
64 #include "gettextP.h"
65 #include "hash-string.h"
66 #include "plural-exp.h"
68 #ifdef _LIBC
69 # include "../locale/localeinfo.h"
70 # include <not-cancel.h>
71 #endif
73 /* Handle multi-threaded applications. */
74 #ifdef _LIBC
75 # include <libc-lock.h>
76 #else
77 # include "lock.h"
78 #endif
80 #ifdef _LIBC
81 # define PRI_MACROS_BROKEN 0
82 #endif
84 /* Provide fallback values for macros that ought to be defined in <inttypes.h>.
85 Note that our fallback values need not be literal strings, because we don't
86 use them with preprocessor string concatenation. */
87 #if !defined PRId8 || PRI_MACROS_BROKEN
88 # undef PRId8
89 # define PRId8 "d"
90 #endif
91 #if !defined PRIi8 || PRI_MACROS_BROKEN
92 # undef PRIi8
93 # define PRIi8 "i"
94 #endif
95 #if !defined PRIo8 || PRI_MACROS_BROKEN
96 # undef PRIo8
97 # define PRIo8 "o"
98 #endif
99 #if !defined PRIu8 || PRI_MACROS_BROKEN
100 # undef PRIu8
101 # define PRIu8 "u"
102 #endif
103 #if !defined PRIx8 || PRI_MACROS_BROKEN
104 # undef PRIx8
105 # define PRIx8 "x"
106 #endif
107 #if !defined PRIX8 || PRI_MACROS_BROKEN
108 # undef PRIX8
109 # define PRIX8 "X"
110 #endif
111 #if !defined PRId16 || PRI_MACROS_BROKEN
112 # undef PRId16
113 # define PRId16 "d"
114 #endif
115 #if !defined PRIi16 || PRI_MACROS_BROKEN
116 # undef PRIi16
117 # define PRIi16 "i"
118 #endif
119 #if !defined PRIo16 || PRI_MACROS_BROKEN
120 # undef PRIo16
121 # define PRIo16 "o"
122 #endif
123 #if !defined PRIu16 || PRI_MACROS_BROKEN
124 # undef PRIu16
125 # define PRIu16 "u"
126 #endif
127 #if !defined PRIx16 || PRI_MACROS_BROKEN
128 # undef PRIx16
129 # define PRIx16 "x"
130 #endif
131 #if !defined PRIX16 || PRI_MACROS_BROKEN
132 # undef PRIX16
133 # define PRIX16 "X"
134 #endif
135 #if !defined PRId32 || PRI_MACROS_BROKEN
136 # undef PRId32
137 # define PRId32 "d"
138 #endif
139 #if !defined PRIi32 || PRI_MACROS_BROKEN
140 # undef PRIi32
141 # define PRIi32 "i"
142 #endif
143 #if !defined PRIo32 || PRI_MACROS_BROKEN
144 # undef PRIo32
145 # define PRIo32 "o"
146 #endif
147 #if !defined PRIu32 || PRI_MACROS_BROKEN
148 # undef PRIu32
149 # define PRIu32 "u"
150 #endif
151 #if !defined PRIx32 || PRI_MACROS_BROKEN
152 # undef PRIx32
153 # define PRIx32 "x"
154 #endif
155 #if !defined PRIX32 || PRI_MACROS_BROKEN
156 # undef PRIX32
157 # define PRIX32 "X"
158 #endif
159 #if !defined PRId64 || PRI_MACROS_BROKEN
160 # undef PRId64
161 # define PRId64 (sizeof (long) == 8 ? "ld" : "lld")
162 #endif
163 #if !defined PRIi64 || PRI_MACROS_BROKEN
164 # undef PRIi64
165 # define PRIi64 (sizeof (long) == 8 ? "li" : "lli")
166 #endif
167 #if !defined PRIo64 || PRI_MACROS_BROKEN
168 # undef PRIo64
169 # define PRIo64 (sizeof (long) == 8 ? "lo" : "llo")
170 #endif
171 #if !defined PRIu64 || PRI_MACROS_BROKEN
172 # undef PRIu64
173 # define PRIu64 (sizeof (long) == 8 ? "lu" : "llu")
174 #endif
175 #if !defined PRIx64 || PRI_MACROS_BROKEN
176 # undef PRIx64
177 # define PRIx64 (sizeof (long) == 8 ? "lx" : "llx")
178 #endif
179 #if !defined PRIX64 || PRI_MACROS_BROKEN
180 # undef PRIX64
181 # define PRIX64 (sizeof (long) == 8 ? "lX" : "llX")
182 #endif
183 #if !defined PRIdLEAST8 || PRI_MACROS_BROKEN
184 # undef PRIdLEAST8
185 # define PRIdLEAST8 "d"
186 #endif
187 #if !defined PRIiLEAST8 || PRI_MACROS_BROKEN
188 # undef PRIiLEAST8
189 # define PRIiLEAST8 "i"
190 #endif
191 #if !defined PRIoLEAST8 || PRI_MACROS_BROKEN
192 # undef PRIoLEAST8
193 # define PRIoLEAST8 "o"
194 #endif
195 #if !defined PRIuLEAST8 || PRI_MACROS_BROKEN
196 # undef PRIuLEAST8
197 # define PRIuLEAST8 "u"
198 #endif
199 #if !defined PRIxLEAST8 || PRI_MACROS_BROKEN
200 # undef PRIxLEAST8
201 # define PRIxLEAST8 "x"
202 #endif
203 #if !defined PRIXLEAST8 || PRI_MACROS_BROKEN
204 # undef PRIXLEAST8
205 # define PRIXLEAST8 "X"
206 #endif
207 #if !defined PRIdLEAST16 || PRI_MACROS_BROKEN
208 # undef PRIdLEAST16
209 # define PRIdLEAST16 "d"
210 #endif
211 #if !defined PRIiLEAST16 || PRI_MACROS_BROKEN
212 # undef PRIiLEAST16
213 # define PRIiLEAST16 "i"
214 #endif
215 #if !defined PRIoLEAST16 || PRI_MACROS_BROKEN
216 # undef PRIoLEAST16
217 # define PRIoLEAST16 "o"
218 #endif
219 #if !defined PRIuLEAST16 || PRI_MACROS_BROKEN
220 # undef PRIuLEAST16
221 # define PRIuLEAST16 "u"
222 #endif
223 #if !defined PRIxLEAST16 || PRI_MACROS_BROKEN
224 # undef PRIxLEAST16
225 # define PRIxLEAST16 "x"
226 #endif
227 #if !defined PRIXLEAST16 || PRI_MACROS_BROKEN
228 # undef PRIXLEAST16
229 # define PRIXLEAST16 "X"
230 #endif
231 #if !defined PRIdLEAST32 || PRI_MACROS_BROKEN
232 # undef PRIdLEAST32
233 # define PRIdLEAST32 "d"
234 #endif
235 #if !defined PRIiLEAST32 || PRI_MACROS_BROKEN
236 # undef PRIiLEAST32
237 # define PRIiLEAST32 "i"
238 #endif
239 #if !defined PRIoLEAST32 || PRI_MACROS_BROKEN
240 # undef PRIoLEAST32
241 # define PRIoLEAST32 "o"
242 #endif
243 #if !defined PRIuLEAST32 || PRI_MACROS_BROKEN
244 # undef PRIuLEAST32
245 # define PRIuLEAST32 "u"
246 #endif
247 #if !defined PRIxLEAST32 || PRI_MACROS_BROKEN
248 # undef PRIxLEAST32
249 # define PRIxLEAST32 "x"
250 #endif
251 #if !defined PRIXLEAST32 || PRI_MACROS_BROKEN
252 # undef PRIXLEAST32
253 # define PRIXLEAST32 "X"
254 #endif
255 #if !defined PRIdLEAST64 || PRI_MACROS_BROKEN
256 # undef PRIdLEAST64
257 # define PRIdLEAST64 PRId64
258 #endif
259 #if !defined PRIiLEAST64 || PRI_MACROS_BROKEN
260 # undef PRIiLEAST64
261 # define PRIiLEAST64 PRIi64
262 #endif
263 #if !defined PRIoLEAST64 || PRI_MACROS_BROKEN
264 # undef PRIoLEAST64
265 # define PRIoLEAST64 PRIo64
266 #endif
267 #if !defined PRIuLEAST64 || PRI_MACROS_BROKEN
268 # undef PRIuLEAST64
269 # define PRIuLEAST64 PRIu64
270 #endif
271 #if !defined PRIxLEAST64 || PRI_MACROS_BROKEN
272 # undef PRIxLEAST64
273 # define PRIxLEAST64 PRIx64
274 #endif
275 #if !defined PRIXLEAST64 || PRI_MACROS_BROKEN
276 # undef PRIXLEAST64
277 # define PRIXLEAST64 PRIX64
278 #endif
279 #if !defined PRIdFAST8 || PRI_MACROS_BROKEN
280 # undef PRIdFAST8
281 # define PRIdFAST8 "d"
282 #endif
283 #if !defined PRIiFAST8 || PRI_MACROS_BROKEN
284 # undef PRIiFAST8
285 # define PRIiFAST8 "i"
286 #endif
287 #if !defined PRIoFAST8 || PRI_MACROS_BROKEN
288 # undef PRIoFAST8
289 # define PRIoFAST8 "o"
290 #endif
291 #if !defined PRIuFAST8 || PRI_MACROS_BROKEN
292 # undef PRIuFAST8
293 # define PRIuFAST8 "u"
294 #endif
295 #if !defined PRIxFAST8 || PRI_MACROS_BROKEN
296 # undef PRIxFAST8
297 # define PRIxFAST8 "x"
298 #endif
299 #if !defined PRIXFAST8 || PRI_MACROS_BROKEN
300 # undef PRIXFAST8
301 # define PRIXFAST8 "X"
302 #endif
303 #if !defined PRIdFAST16 || PRI_MACROS_BROKEN
304 # undef PRIdFAST16
305 # define PRIdFAST16 "d"
306 #endif
307 #if !defined PRIiFAST16 || PRI_MACROS_BROKEN
308 # undef PRIiFAST16
309 # define PRIiFAST16 "i"
310 #endif
311 #if !defined PRIoFAST16 || PRI_MACROS_BROKEN
312 # undef PRIoFAST16
313 # define PRIoFAST16 "o"
314 #endif
315 #if !defined PRIuFAST16 || PRI_MACROS_BROKEN
316 # undef PRIuFAST16
317 # define PRIuFAST16 "u"
318 #endif
319 #if !defined PRIxFAST16 || PRI_MACROS_BROKEN
320 # undef PRIxFAST16
321 # define PRIxFAST16 "x"
322 #endif
323 #if !defined PRIXFAST16 || PRI_MACROS_BROKEN
324 # undef PRIXFAST16
325 # define PRIXFAST16 "X"
326 #endif
327 #if !defined PRIdFAST32 || PRI_MACROS_BROKEN
328 # undef PRIdFAST32
329 # define PRIdFAST32 "d"
330 #endif
331 #if !defined PRIiFAST32 || PRI_MACROS_BROKEN
332 # undef PRIiFAST32
333 # define PRIiFAST32 "i"
334 #endif
335 #if !defined PRIoFAST32 || PRI_MACROS_BROKEN
336 # undef PRIoFAST32
337 # define PRIoFAST32 "o"
338 #endif
339 #if !defined PRIuFAST32 || PRI_MACROS_BROKEN
340 # undef PRIuFAST32
341 # define PRIuFAST32 "u"
342 #endif
343 #if !defined PRIxFAST32 || PRI_MACROS_BROKEN
344 # undef PRIxFAST32
345 # define PRIxFAST32 "x"
346 #endif
347 #if !defined PRIXFAST32 || PRI_MACROS_BROKEN
348 # undef PRIXFAST32
349 # define PRIXFAST32 "X"
350 #endif
351 #if !defined PRIdFAST64 || PRI_MACROS_BROKEN
352 # undef PRIdFAST64
353 # define PRIdFAST64 PRId64
354 #endif
355 #if !defined PRIiFAST64 || PRI_MACROS_BROKEN
356 # undef PRIiFAST64
357 # define PRIiFAST64 PRIi64
358 #endif
359 #if !defined PRIoFAST64 || PRI_MACROS_BROKEN
360 # undef PRIoFAST64
361 # define PRIoFAST64 PRIo64
362 #endif
363 #if !defined PRIuFAST64 || PRI_MACROS_BROKEN
364 # undef PRIuFAST64
365 # define PRIuFAST64 PRIu64
366 #endif
367 #if !defined PRIxFAST64 || PRI_MACROS_BROKEN
368 # undef PRIxFAST64
369 # define PRIxFAST64 PRIx64
370 #endif
371 #if !defined PRIXFAST64 || PRI_MACROS_BROKEN
372 # undef PRIXFAST64
373 # define PRIXFAST64 PRIX64
374 #endif
375 #if !defined PRIdMAX || PRI_MACROS_BROKEN
376 # undef PRIdMAX
377 # define PRIdMAX (sizeof (uintmax_t) == sizeof (long) ? "ld" : "lld")
378 #endif
379 #if !defined PRIiMAX || PRI_MACROS_BROKEN
380 # undef PRIiMAX
381 # define PRIiMAX (sizeof (uintmax_t) == sizeof (long) ? "li" : "lli")
382 #endif
383 #if !defined PRIoMAX || PRI_MACROS_BROKEN
384 # undef PRIoMAX
385 # define PRIoMAX (sizeof (uintmax_t) == sizeof (long) ? "lo" : "llo")
386 #endif
387 #if !defined PRIuMAX || PRI_MACROS_BROKEN
388 # undef PRIuMAX
389 # define PRIuMAX (sizeof (uintmax_t) == sizeof (long) ? "lu" : "llu")
390 #endif
391 #if !defined PRIxMAX || PRI_MACROS_BROKEN
392 # undef PRIxMAX
393 # define PRIxMAX (sizeof (uintmax_t) == sizeof (long) ? "lx" : "llx")
394 #endif
395 #if !defined PRIXMAX || PRI_MACROS_BROKEN
396 # undef PRIXMAX
397 # define PRIXMAX (sizeof (uintmax_t) == sizeof (long) ? "lX" : "llX")
398 #endif
399 #if !defined PRIdPTR || PRI_MACROS_BROKEN
400 # undef PRIdPTR
401 # define PRIdPTR \
402 (sizeof (void *) == sizeof (long) ? "ld" : \
403 sizeof (void *) == sizeof (int) ? "d" : \
404 "lld")
405 #endif
406 #if !defined PRIiPTR || PRI_MACROS_BROKEN
407 # undef PRIiPTR
408 # define PRIiPTR \
409 (sizeof (void *) == sizeof (long) ? "li" : \
410 sizeof (void *) == sizeof (int) ? "i" : \
411 "lli")
412 #endif
413 #if !defined PRIoPTR || PRI_MACROS_BROKEN
414 # undef PRIoPTR
415 # define PRIoPTR \
416 (sizeof (void *) == sizeof (long) ? "lo" : \
417 sizeof (void *) == sizeof (int) ? "o" : \
418 "llo")
419 #endif
420 #if !defined PRIuPTR || PRI_MACROS_BROKEN
421 # undef PRIuPTR
422 # define PRIuPTR \
423 (sizeof (void *) == sizeof (long) ? "lu" : \
424 sizeof (void *) == sizeof (int) ? "u" : \
425 "llu")
426 #endif
427 #if !defined PRIxPTR || PRI_MACROS_BROKEN
428 # undef PRIxPTR
429 # define PRIxPTR \
430 (sizeof (void *) == sizeof (long) ? "lx" : \
431 sizeof (void *) == sizeof (int) ? "x" : \
432 "llx")
433 #endif
434 #if !defined PRIXPTR || PRI_MACROS_BROKEN
435 # undef PRIXPTR
436 # define PRIXPTR \
437 (sizeof (void *) == sizeof (long) ? "lX" : \
438 sizeof (void *) == sizeof (int) ? "X" : \
439 "llX")
440 #endif
442 /* @@ end of prolog @@ */
444 #ifdef _LIBC
445 /* Rename the non ISO C functions. This is required by the standard
446 because some ISO C functions will require linking with this object
447 file and the name space must not be polluted. */
448 # define open(name, flags) __open_nocancel (name, flags)
449 # define close(fd) __close_nocancel_nostatus (fd)
450 # define read(fd, buf, n) __read_nocancel (fd, buf, n)
451 # define mmap(addr, len, prot, flags, fd, offset) \
452 __mmap (addr, len, prot, flags, fd, offset)
453 # define munmap(addr, len) __munmap (addr, len)
454 #endif
456 /* For systems that distinguish between text and binary I/O.
457 O_BINARY is usually declared in <fcntl.h>. */
458 #if !defined O_BINARY && defined _O_BINARY
459 /* For MSC-compatible compilers. */
460 # define O_BINARY _O_BINARY
461 # define O_TEXT _O_TEXT
462 #endif
463 #ifdef __BEOS__
464 /* BeOS 5 has O_BINARY and O_TEXT, but they have no effect. */
465 # undef O_BINARY
466 # undef O_TEXT
467 #endif
468 /* On reasonable systems, binary I/O is the default. */
469 #ifndef O_BINARY
470 # define O_BINARY 0
471 #endif
474 /* We need a sign, whether a new catalog was loaded, which can be associated
475 with all translations. This is important if the translations are
476 cached by one of GCC's features. */
477 int _nl_msg_cat_cntr;
480 /* Expand a system dependent string segment. Return NULL if unsupported. */
481 static const char *
482 get_sysdep_segment_value (const char *name)
484 /* Test for an ISO C 99 section 7.8.1 format string directive.
485 Syntax:
486 P R I { d | i | o | u | x | X }
487 { { | LEAST | FAST } { 8 | 16 | 32 | 64 } | MAX | PTR } */
488 /* We don't use a table of 14 times 6 'const char *' strings here, because
489 data relocations cost startup time. */
490 if (name[0] == 'P' && name[1] == 'R' && name[2] == 'I')
492 if (name[3] == 'd' || name[3] == 'i' || name[3] == 'o' || name[3] == 'u'
493 || name[3] == 'x' || name[3] == 'X')
495 if (name[4] == '8' && name[5] == '\0')
497 if (name[3] == 'd')
498 return PRId8;
499 if (name[3] == 'i')
500 return PRIi8;
501 if (name[3] == 'o')
502 return PRIo8;
503 if (name[3] == 'u')
504 return PRIu8;
505 if (name[3] == 'x')
506 return PRIx8;
507 if (name[3] == 'X')
508 return PRIX8;
509 abort ();
511 if (name[4] == '1' && name[5] == '6' && name[6] == '\0')
513 if (name[3] == 'd')
514 return PRId16;
515 if (name[3] == 'i')
516 return PRIi16;
517 if (name[3] == 'o')
518 return PRIo16;
519 if (name[3] == 'u')
520 return PRIu16;
521 if (name[3] == 'x')
522 return PRIx16;
523 if (name[3] == 'X')
524 return PRIX16;
525 abort ();
527 if (name[4] == '3' && name[5] == '2' && name[6] == '\0')
529 if (name[3] == 'd')
530 return PRId32;
531 if (name[3] == 'i')
532 return PRIi32;
533 if (name[3] == 'o')
534 return PRIo32;
535 if (name[3] == 'u')
536 return PRIu32;
537 if (name[3] == 'x')
538 return PRIx32;
539 if (name[3] == 'X')
540 return PRIX32;
541 abort ();
543 if (name[4] == '6' && name[5] == '4' && name[6] == '\0')
545 if (name[3] == 'd')
546 return PRId64;
547 if (name[3] == 'i')
548 return PRIi64;
549 if (name[3] == 'o')
550 return PRIo64;
551 if (name[3] == 'u')
552 return PRIu64;
553 if (name[3] == 'x')
554 return PRIx64;
555 if (name[3] == 'X')
556 return PRIX64;
557 abort ();
559 if (name[4] == 'L' && name[5] == 'E' && name[6] == 'A'
560 && name[7] == 'S' && name[8] == 'T')
562 if (name[9] == '8' && name[10] == '\0')
564 if (name[3] == 'd')
565 return PRIdLEAST8;
566 if (name[3] == 'i')
567 return PRIiLEAST8;
568 if (name[3] == 'o')
569 return PRIoLEAST8;
570 if (name[3] == 'u')
571 return PRIuLEAST8;
572 if (name[3] == 'x')
573 return PRIxLEAST8;
574 if (name[3] == 'X')
575 return PRIXLEAST8;
576 abort ();
578 if (name[9] == '1' && name[10] == '6' && name[11] == '\0')
580 if (name[3] == 'd')
581 return PRIdLEAST16;
582 if (name[3] == 'i')
583 return PRIiLEAST16;
584 if (name[3] == 'o')
585 return PRIoLEAST16;
586 if (name[3] == 'u')
587 return PRIuLEAST16;
588 if (name[3] == 'x')
589 return PRIxLEAST16;
590 if (name[3] == 'X')
591 return PRIXLEAST16;
592 abort ();
594 if (name[9] == '3' && name[10] == '2' && name[11] == '\0')
596 if (name[3] == 'd')
597 return PRIdLEAST32;
598 if (name[3] == 'i')
599 return PRIiLEAST32;
600 if (name[3] == 'o')
601 return PRIoLEAST32;
602 if (name[3] == 'u')
603 return PRIuLEAST32;
604 if (name[3] == 'x')
605 return PRIxLEAST32;
606 if (name[3] == 'X')
607 return PRIXLEAST32;
608 abort ();
610 if (name[9] == '6' && name[10] == '4' && name[11] == '\0')
612 if (name[3] == 'd')
613 return PRIdLEAST64;
614 if (name[3] == 'i')
615 return PRIiLEAST64;
616 if (name[3] == 'o')
617 return PRIoLEAST64;
618 if (name[3] == 'u')
619 return PRIuLEAST64;
620 if (name[3] == 'x')
621 return PRIxLEAST64;
622 if (name[3] == 'X')
623 return PRIXLEAST64;
624 abort ();
627 if (name[4] == 'F' && name[5] == 'A' && name[6] == 'S'
628 && name[7] == 'T')
630 if (name[8] == '8' && name[9] == '\0')
632 if (name[3] == 'd')
633 return PRIdFAST8;
634 if (name[3] == 'i')
635 return PRIiFAST8;
636 if (name[3] == 'o')
637 return PRIoFAST8;
638 if (name[3] == 'u')
639 return PRIuFAST8;
640 if (name[3] == 'x')
641 return PRIxFAST8;
642 if (name[3] == 'X')
643 return PRIXFAST8;
644 abort ();
646 if (name[8] == '1' && name[9] == '6' && name[10] == '\0')
648 if (name[3] == 'd')
649 return PRIdFAST16;
650 if (name[3] == 'i')
651 return PRIiFAST16;
652 if (name[3] == 'o')
653 return PRIoFAST16;
654 if (name[3] == 'u')
655 return PRIuFAST16;
656 if (name[3] == 'x')
657 return PRIxFAST16;
658 if (name[3] == 'X')
659 return PRIXFAST16;
660 abort ();
662 if (name[8] == '3' && name[9] == '2' && name[10] == '\0')
664 if (name[3] == 'd')
665 return PRIdFAST32;
666 if (name[3] == 'i')
667 return PRIiFAST32;
668 if (name[3] == 'o')
669 return PRIoFAST32;
670 if (name[3] == 'u')
671 return PRIuFAST32;
672 if (name[3] == 'x')
673 return PRIxFAST32;
674 if (name[3] == 'X')
675 return PRIXFAST32;
676 abort ();
678 if (name[8] == '6' && name[9] == '4' && name[10] == '\0')
680 if (name[3] == 'd')
681 return PRIdFAST64;
682 if (name[3] == 'i')
683 return PRIiFAST64;
684 if (name[3] == 'o')
685 return PRIoFAST64;
686 if (name[3] == 'u')
687 return PRIuFAST64;
688 if (name[3] == 'x')
689 return PRIxFAST64;
690 if (name[3] == 'X')
691 return PRIXFAST64;
692 abort ();
695 if (name[4] == 'M' && name[5] == 'A' && name[6] == 'X'
696 && name[7] == '\0')
698 if (name[3] == 'd')
699 return PRIdMAX;
700 if (name[3] == 'i')
701 return PRIiMAX;
702 if (name[3] == 'o')
703 return PRIoMAX;
704 if (name[3] == 'u')
705 return PRIuMAX;
706 if (name[3] == 'x')
707 return PRIxMAX;
708 if (name[3] == 'X')
709 return PRIXMAX;
710 abort ();
712 if (name[4] == 'P' && name[5] == 'T' && name[6] == 'R'
713 && name[7] == '\0')
715 if (name[3] == 'd')
716 return PRIdPTR;
717 if (name[3] == 'i')
718 return PRIiPTR;
719 if (name[3] == 'o')
720 return PRIoPTR;
721 if (name[3] == 'u')
722 return PRIuPTR;
723 if (name[3] == 'x')
724 return PRIxPTR;
725 if (name[3] == 'X')
726 return PRIXPTR;
727 abort ();
731 /* Test for a glibc specific printf() format directive flag. */
732 if (name[0] == 'I' && name[1] == '\0')
734 #if defined _LIBC \
735 || ((__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2)) \
736 && !defined __UCLIBC__)
737 /* The 'I' flag, in numeric format directives, replaces ASCII digits
738 with the 'outdigits' defined in the LC_CTYPE locale facet. This is
739 used for Farsi (Persian), some Indic languages, and maybe Arabic. */
740 return "I";
741 #else
742 return "";
743 #endif
745 /* Other system dependent strings are not valid. */
746 return NULL;
749 /* Load the message catalogs specified by FILENAME. If it is no valid
750 message catalog do nothing. */
751 void
752 _nl_load_domain (struct loaded_l10nfile *domain_file,
753 struct binding *domainbinding)
755 __libc_lock_define_initialized_recursive (static, lock);
756 int fd = -1;
757 size_t size;
758 #ifdef _LIBC
759 struct __stat64_t64 st;
760 #else
761 struct stat st;
762 #endif
763 struct mo_file_header *data = (struct mo_file_header *) -1;
764 int use_mmap = 0;
765 struct loaded_domain *domain;
766 int revision;
767 const char *nullentry;
768 size_t nullentrylen;
770 __libc_lock_lock_recursive (lock);
771 if (domain_file->decided != 0)
773 /* There are two possibilities:
775 + this is the same thread calling again during this initialization
776 via _nl_find_msg. We have initialized everything this call needs.
778 + this is another thread which tried to initialize this object.
779 Not necessary anymore since if the lock is available this
780 is finished.
782 goto done;
785 domain_file->decided = -1;
786 domain_file->data = NULL;
788 /* Note that it would be useless to store domainbinding in domain_file
789 because domainbinding might be == NULL now but != NULL later (after
790 a call to bind_textdomain_codeset). */
792 /* If the record does not represent a valid locale the FILENAME
793 might be NULL. This can happen when according to the given
794 specification the locale file name is different for XPG and CEN
795 syntax. */
796 if (domain_file->filename == NULL)
797 goto out;
799 /* Try to open the addressed file. */
800 fd = open (domain_file->filename, O_RDONLY | O_BINARY);
801 if (fd == -1)
802 goto out;
804 /* We must know about the size of the file. */
805 if (
806 #ifdef _LIBC
807 __glibc_unlikely (__fstat64_time64 (fd, &st) != 0)
808 #else
809 __builtin_expect (fstat (fd, &st) != 0, 0)
810 #endif
811 || __builtin_expect ((size = (size_t) st.st_size) != st.st_size, 0)
812 || __builtin_expect (size < sizeof (struct mo_file_header), 0))
813 /* Something went wrong. */
814 goto out;
816 #ifdef HAVE_MMAP
817 /* Now we are ready to load the file. If mmap() is available we try
818 this first. If not available or it failed we try to load it. */
819 data = (struct mo_file_header *) mmap (NULL, size, PROT_READ,
820 MAP_PRIVATE, fd, 0);
822 if (__builtin_expect (data != MAP_FAILED, 1))
824 /* mmap() call was successful. */
825 close (fd);
826 fd = -1;
827 use_mmap = 1;
830 assert (MAP_FAILED == (void *) -1);
831 #endif
833 /* If the data is not yet available (i.e. mmap'ed) we try to load
834 it manually. */
835 if (data == (struct mo_file_header *) -1)
837 size_t to_read;
838 char *read_ptr;
840 data = (struct mo_file_header *) malloc (size);
841 if (data == NULL)
842 goto out;
844 to_read = size;
845 read_ptr = (char *) data;
848 long int nb = (long int) read (fd, read_ptr, to_read);
849 if (nb <= 0)
851 #ifdef EINTR
852 if (nb == -1 && errno == EINTR)
853 continue;
854 #endif
855 goto out;
857 read_ptr += nb;
858 to_read -= nb;
860 while (to_read > 0);
862 close (fd);
863 fd = -1;
866 /* Using the magic number we can test whether it really is a message
867 catalog file. */
868 if (__builtin_expect (data->magic != _MAGIC && data->magic != _MAGIC_SWAPPED,
871 /* The magic number is wrong: not a message catalog file. */
872 #ifdef HAVE_MMAP
873 if (use_mmap)
874 munmap ((caddr_t) data, size);
875 else
876 #endif
877 free (data);
878 goto out;
881 domain = (struct loaded_domain *) malloc (sizeof (struct loaded_domain));
882 if (domain == NULL)
883 goto out;
884 domain_file->data = domain;
886 domain->data = (char *) data;
887 domain->use_mmap = use_mmap;
888 domain->mmap_size = size;
889 domain->must_swap = data->magic != _MAGIC;
890 domain->malloced = NULL;
892 /* Fill in the information about the available tables. */
893 revision = W (domain->must_swap, data->revision);
894 /* We support only the major revisions 0 and 1. */
895 switch (revision >> 16)
897 case 0:
898 case 1:
899 domain->nstrings = W (domain->must_swap, data->nstrings);
900 domain->orig_tab = (const struct string_desc *)
901 ((char *) data + W (domain->must_swap, data->orig_tab_offset));
902 domain->trans_tab = (const struct string_desc *)
903 ((char *) data + W (domain->must_swap, data->trans_tab_offset));
904 domain->hash_size = W (domain->must_swap, data->hash_tab_size);
905 domain->hash_tab =
906 (domain->hash_size > 2
907 ? (const nls_uint32 *)
908 ((char *) data + W (domain->must_swap, data->hash_tab_offset))
909 : NULL);
910 domain->must_swap_hash_tab = domain->must_swap;
912 /* Now dispatch on the minor revision. */
913 switch (revision & 0xffff)
915 case 0:
916 domain->n_sysdep_strings = 0;
917 domain->orig_sysdep_tab = NULL;
918 domain->trans_sysdep_tab = NULL;
919 break;
920 case 1:
921 default:
923 nls_uint32 n_sysdep_strings;
925 if (domain->hash_tab == NULL)
926 /* This is invalid. These minor revisions need a hash table. */
927 goto invalid;
929 n_sysdep_strings =
930 W (domain->must_swap, data->n_sysdep_strings);
931 if (n_sysdep_strings > 0)
933 nls_uint32 n_sysdep_segments;
934 const struct sysdep_segment *sysdep_segments;
935 const char **sysdep_segment_values;
936 const nls_uint32 *orig_sysdep_tab;
937 const nls_uint32 *trans_sysdep_tab;
938 nls_uint32 n_inmem_sysdep_strings;
939 size_t memneed;
940 char *mem;
941 struct sysdep_string_desc *inmem_orig_sysdep_tab;
942 struct sysdep_string_desc *inmem_trans_sysdep_tab;
943 nls_uint32 *inmem_hash_tab;
944 unsigned int i, j;
946 /* Get the values of the system dependent segments. */
947 n_sysdep_segments =
948 W (domain->must_swap, data->n_sysdep_segments);
949 sysdep_segments = (const struct sysdep_segment *)
950 ((char *) data
951 + W (domain->must_swap, data->sysdep_segments_offset));
952 sysdep_segment_values = calloc
953 (n_sysdep_segments, sizeof (const char *));
954 if (sysdep_segment_values == NULL)
955 goto invalid;
956 for (i = 0; i < n_sysdep_segments; i++)
958 const char *name =
959 (char *) data
960 + W (domain->must_swap, sysdep_segments[i].offset);
961 nls_uint32 namelen =
962 W (domain->must_swap, sysdep_segments[i].length);
964 if (!(namelen > 0 && name[namelen - 1] == '\0'))
966 free (sysdep_segment_values);
967 goto invalid;
970 sysdep_segment_values[i] = get_sysdep_segment_value (name);
973 orig_sysdep_tab = (const nls_uint32 *)
974 ((char *) data
975 + W (domain->must_swap, data->orig_sysdep_tab_offset));
976 trans_sysdep_tab = (const nls_uint32 *)
977 ((char *) data
978 + W (domain->must_swap, data->trans_sysdep_tab_offset));
980 /* Compute the amount of additional memory needed for the
981 system dependent strings and the augmented hash table.
982 At the same time, also drop string pairs which refer to
983 an undefined system dependent segment. */
984 n_inmem_sysdep_strings = 0;
985 memneed = domain->hash_size * sizeof (nls_uint32);
986 for (i = 0; i < n_sysdep_strings; i++)
988 int valid = 1;
989 size_t needs[2];
991 for (j = 0; j < 2; j++)
993 const struct sysdep_string *sysdep_string =
994 (const struct sysdep_string *)
995 ((char *) data
996 + W (domain->must_swap,
997 j == 0
998 ? orig_sysdep_tab[i]
999 : trans_sysdep_tab[i]));
1000 size_t need = 0;
1001 const struct segment_pair *p = sysdep_string->segments;
1003 if (W (domain->must_swap, p->sysdepref) != SEGMENTS_END)
1004 for (p = sysdep_string->segments;; p++)
1006 nls_uint32 sysdepref;
1008 need += W (domain->must_swap, p->segsize);
1010 sysdepref = W (domain->must_swap, p->sysdepref);
1011 if (sysdepref == SEGMENTS_END)
1012 break;
1014 if (sysdepref >= n_sysdep_segments)
1016 /* Invalid. */
1017 free (sysdep_segment_values);
1018 goto invalid;
1021 if (sysdep_segment_values[sysdepref] == NULL)
1023 /* This particular string pair is invalid. */
1024 valid = 0;
1025 break;
1028 need += strlen (sysdep_segment_values[sysdepref]);
1031 needs[j] = need;
1032 if (!valid)
1033 break;
1036 if (valid)
1038 n_inmem_sysdep_strings++;
1039 memneed += needs[0] + needs[1];
1042 memneed += 2 * n_inmem_sysdep_strings
1043 * sizeof (struct sysdep_string_desc);
1045 if (n_inmem_sysdep_strings > 0)
1047 unsigned int k;
1049 /* Allocate additional memory. */
1050 mem = (char *) malloc (memneed);
1051 if (mem == NULL)
1052 goto invalid;
1054 domain->malloced = mem;
1055 inmem_orig_sysdep_tab = (struct sysdep_string_desc *) mem;
1056 mem += n_inmem_sysdep_strings
1057 * sizeof (struct sysdep_string_desc);
1058 inmem_trans_sysdep_tab = (struct sysdep_string_desc *) mem;
1059 mem += n_inmem_sysdep_strings
1060 * sizeof (struct sysdep_string_desc);
1061 inmem_hash_tab = (nls_uint32 *) mem;
1062 mem += domain->hash_size * sizeof (nls_uint32);
1064 /* Compute the system dependent strings. */
1065 k = 0;
1066 for (i = 0; i < n_sysdep_strings; i++)
1068 int valid = 1;
1070 for (j = 0; j < 2; j++)
1072 const struct sysdep_string *sysdep_string =
1073 (const struct sysdep_string *)
1074 ((char *) data
1075 + W (domain->must_swap,
1076 j == 0
1077 ? orig_sysdep_tab[i]
1078 : trans_sysdep_tab[i]));
1079 const struct segment_pair *p =
1080 sysdep_string->segments;
1082 if (W (domain->must_swap, p->sysdepref)
1083 != SEGMENTS_END)
1084 for (p = sysdep_string->segments;; p++)
1086 nls_uint32 sysdepref;
1088 sysdepref =
1089 W (domain->must_swap, p->sysdepref);
1090 if (sysdepref == SEGMENTS_END)
1091 break;
1093 if (sysdep_segment_values[sysdepref] == NULL)
1095 /* This particular string pair is
1096 invalid. */
1097 valid = 0;
1098 break;
1102 if (!valid)
1103 break;
1106 if (valid)
1108 for (j = 0; j < 2; j++)
1110 const struct sysdep_string *sysdep_string =
1111 (const struct sysdep_string *)
1112 ((char *) data
1113 + W (domain->must_swap,
1114 j == 0
1115 ? orig_sysdep_tab[i]
1116 : trans_sysdep_tab[i]));
1117 const char *static_segments =
1118 (char *) data
1119 + W (domain->must_swap, sysdep_string->offset);
1120 const struct segment_pair *p =
1121 sysdep_string->segments;
1123 /* Concatenate the segments, and fill
1124 inmem_orig_sysdep_tab[k] (for j == 0) and
1125 inmem_trans_sysdep_tab[k] (for j == 1). */
1127 struct sysdep_string_desc *inmem_tab_entry =
1128 (j == 0
1129 ? inmem_orig_sysdep_tab
1130 : inmem_trans_sysdep_tab)
1131 + k;
1133 if (W (domain->must_swap, p->sysdepref)
1134 == SEGMENTS_END)
1136 /* Only one static segment. */
1137 inmem_tab_entry->length =
1138 W (domain->must_swap, p->segsize);
1139 inmem_tab_entry->pointer = static_segments;
1141 else
1143 inmem_tab_entry->pointer = mem;
1145 for (p = sysdep_string->segments;; p++)
1147 nls_uint32 segsize =
1148 W (domain->must_swap, p->segsize);
1149 nls_uint32 sysdepref =
1150 W (domain->must_swap, p->sysdepref);
1151 size_t n;
1153 if (segsize > 0)
1155 memcpy (mem, static_segments, segsize);
1156 mem += segsize;
1157 static_segments += segsize;
1160 if (sysdepref == SEGMENTS_END)
1161 break;
1163 n = strlen (sysdep_segment_values[sysdepref]);
1164 memcpy (mem, sysdep_segment_values[sysdepref], n);
1165 mem += n;
1168 inmem_tab_entry->length =
1169 mem - inmem_tab_entry->pointer;
1173 k++;
1176 if (k != n_inmem_sysdep_strings)
1177 abort ();
1179 /* Compute the augmented hash table. */
1180 for (i = 0; i < domain->hash_size; i++)
1181 inmem_hash_tab[i] =
1182 W (domain->must_swap_hash_tab, domain->hash_tab[i]);
1183 for (i = 0; i < n_inmem_sysdep_strings; i++)
1185 const char *msgid = inmem_orig_sysdep_tab[i].pointer;
1186 nls_uint32 hash_val = __hash_string (msgid);
1187 nls_uint32 idx = hash_val % domain->hash_size;
1188 nls_uint32 incr =
1189 1 + (hash_val % (domain->hash_size - 2));
1191 for (;;)
1193 if (inmem_hash_tab[idx] == 0)
1195 /* Hash table entry is empty. Use it. */
1196 inmem_hash_tab[idx] = 1 + domain->nstrings + i;
1197 break;
1200 if (idx >= domain->hash_size - incr)
1201 idx -= domain->hash_size - incr;
1202 else
1203 idx += incr;
1207 domain->n_sysdep_strings = n_inmem_sysdep_strings;
1208 domain->orig_sysdep_tab = inmem_orig_sysdep_tab;
1209 domain->trans_sysdep_tab = inmem_trans_sysdep_tab;
1211 domain->hash_tab = inmem_hash_tab;
1212 domain->must_swap_hash_tab = 0;
1214 else
1216 domain->n_sysdep_strings = 0;
1217 domain->orig_sysdep_tab = NULL;
1218 domain->trans_sysdep_tab = NULL;
1221 free (sysdep_segment_values);
1223 else
1225 domain->n_sysdep_strings = 0;
1226 domain->orig_sysdep_tab = NULL;
1227 domain->trans_sysdep_tab = NULL;
1230 break;
1232 break;
1233 default:
1234 /* This is an invalid revision. */
1235 invalid:
1236 /* This is an invalid .mo file or we ran out of resources. */
1237 free (domain->malloced);
1238 #ifdef HAVE_MMAP
1239 if (use_mmap)
1240 munmap ((caddr_t) data, size);
1241 else
1242 #endif
1243 free (data);
1244 free (domain);
1245 domain_file->data = NULL;
1246 goto out;
1249 /* No caches of converted translations so far. */
1250 domain->conversions = NULL;
1251 domain->nconversions = 0;
1252 #ifdef _LIBC
1253 __libc_rwlock_init (domain->conversions_lock);
1254 #else
1255 gl_rwlock_init (domain->conversions_lock);
1256 #endif
1258 /* Get the header entry and look for a plural specification. */
1259 #ifdef IN_LIBGLOCALE
1260 nullentry =
1261 _nl_find_msg (domain_file, domainbinding, NULL, "", &nullentrylen);
1262 #else
1263 nullentry = _nl_find_msg (domain_file, domainbinding, "", 0, &nullentrylen);
1264 #endif
1265 if (__builtin_expect (nullentry == (char *) -1, 0))
1267 #ifdef _LIBC
1268 __libc_rwlock_fini (domain->conversions_lock);
1269 #endif
1270 goto invalid;
1272 EXTRACT_PLURAL_EXPRESSION (nullentry, &domain->plural, &domain->nplurals);
1274 out:
1275 if (fd != -1)
1276 close (fd);
1278 domain_file->decided = 1;
1280 done:
1281 __libc_lock_unlock_recursive (lock);
1285 #ifdef _LIBC
1286 void
1287 __libc_freeres_fn_section
1288 _nl_unload_domain (struct loaded_domain *domain)
1290 size_t i;
1292 if (domain->plural != &__gettext_germanic_plural)
1293 __gettext_free_exp ((struct expression *) domain->plural);
1295 for (i = 0; i < domain->nconversions; i++)
1297 struct converted_domain *convd = &domain->conversions[i];
1299 free ((char *) convd->encoding);
1300 if (convd->conv_tab != NULL && convd->conv_tab != (char **) -1)
1301 free (convd->conv_tab);
1302 if (convd->conv != (__gconv_t) -1)
1303 __gconv_close (convd->conv);
1305 free (domain->conversions);
1306 __libc_rwlock_fini (domain->conversions_lock);
1308 free (domain->malloced);
1310 # ifdef _POSIX_MAPPED_FILES
1311 if (domain->use_mmap)
1312 munmap ((caddr_t) domain->data, domain->mmap_size);
1313 else
1314 # endif /* _POSIX_MAPPED_FILES */
1315 free ((void *) domain->data);
1317 free (domain);
1319 #endif