hurd: fix pathconf visibility
[glibc.git] / intl / loadmsgcat.c
blob7ccb4ffa6807b6578c49541408a71127ddc45e0e
1 /* Load needed message catalogs.
2 Copyright (C) 1995-2016 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 <http://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 #ifdef __GNUC__
36 # undef alloca
37 # define alloca __builtin_alloca
38 # define HAVE_ALLOCA 1
39 #else
40 # ifdef _MSC_VER
41 # include <malloc.h>
42 # define alloca _alloca
43 # else
44 # if defined HAVE_ALLOCA_H || defined _LIBC
45 # include <alloca.h>
46 # else
47 # ifdef _AIX
48 #pragma alloca
49 # else
50 # ifndef alloca
51 char *alloca ();
52 # endif
53 # endif
54 # endif
55 # endif
56 #endif
58 #include <stdlib.h>
59 #include <string.h>
61 #if defined HAVE_UNISTD_H || defined _LIBC
62 # include <unistd.h>
63 #endif
65 #ifdef _LIBC
66 # include <langinfo.h>
67 # include <locale.h>
68 #endif
70 #if (defined HAVE_MMAP && defined HAVE_MUNMAP && !defined DISALLOW_MMAP) \
71 || (defined _LIBC && defined _POSIX_MAPPED_FILES)
72 # include <sys/mman.h>
73 # undef HAVE_MMAP
74 # define HAVE_MMAP 1
75 #else
76 # undef HAVE_MMAP
77 #endif
79 #if defined HAVE_STDINT_H_WITH_UINTMAX || defined _LIBC
80 # include <stdint.h>
81 #endif
82 #if defined HAVE_INTTYPES_H || defined _LIBC
83 # include <inttypes.h>
84 #endif
86 #include "gmo.h"
87 #include "gettextP.h"
88 #include "hash-string.h"
89 #include "plural-exp.h"
91 #ifdef _LIBC
92 # include "../locale/localeinfo.h"
93 # include <not-cancel.h>
94 #endif
96 /* Handle multi-threaded applications. */
97 #ifdef _LIBC
98 # include <libc-lock.h>
99 #else
100 # include "lock.h"
101 #endif
103 #ifdef _LIBC
104 # define PRI_MACROS_BROKEN 0
105 #endif
107 /* Provide fallback values for macros that ought to be defined in <inttypes.h>.
108 Note that our fallback values need not be literal strings, because we don't
109 use them with preprocessor string concatenation. */
110 #if !defined PRId8 || PRI_MACROS_BROKEN
111 # undef PRId8
112 # define PRId8 "d"
113 #endif
114 #if !defined PRIi8 || PRI_MACROS_BROKEN
115 # undef PRIi8
116 # define PRIi8 "i"
117 #endif
118 #if !defined PRIo8 || PRI_MACROS_BROKEN
119 # undef PRIo8
120 # define PRIo8 "o"
121 #endif
122 #if !defined PRIu8 || PRI_MACROS_BROKEN
123 # undef PRIu8
124 # define PRIu8 "u"
125 #endif
126 #if !defined PRIx8 || PRI_MACROS_BROKEN
127 # undef PRIx8
128 # define PRIx8 "x"
129 #endif
130 #if !defined PRIX8 || PRI_MACROS_BROKEN
131 # undef PRIX8
132 # define PRIX8 "X"
133 #endif
134 #if !defined PRId16 || PRI_MACROS_BROKEN
135 # undef PRId16
136 # define PRId16 "d"
137 #endif
138 #if !defined PRIi16 || PRI_MACROS_BROKEN
139 # undef PRIi16
140 # define PRIi16 "i"
141 #endif
142 #if !defined PRIo16 || PRI_MACROS_BROKEN
143 # undef PRIo16
144 # define PRIo16 "o"
145 #endif
146 #if !defined PRIu16 || PRI_MACROS_BROKEN
147 # undef PRIu16
148 # define PRIu16 "u"
149 #endif
150 #if !defined PRIx16 || PRI_MACROS_BROKEN
151 # undef PRIx16
152 # define PRIx16 "x"
153 #endif
154 #if !defined PRIX16 || PRI_MACROS_BROKEN
155 # undef PRIX16
156 # define PRIX16 "X"
157 #endif
158 #if !defined PRId32 || PRI_MACROS_BROKEN
159 # undef PRId32
160 # define PRId32 "d"
161 #endif
162 #if !defined PRIi32 || PRI_MACROS_BROKEN
163 # undef PRIi32
164 # define PRIi32 "i"
165 #endif
166 #if !defined PRIo32 || PRI_MACROS_BROKEN
167 # undef PRIo32
168 # define PRIo32 "o"
169 #endif
170 #if !defined PRIu32 || PRI_MACROS_BROKEN
171 # undef PRIu32
172 # define PRIu32 "u"
173 #endif
174 #if !defined PRIx32 || PRI_MACROS_BROKEN
175 # undef PRIx32
176 # define PRIx32 "x"
177 #endif
178 #if !defined PRIX32 || PRI_MACROS_BROKEN
179 # undef PRIX32
180 # define PRIX32 "X"
181 #endif
182 #if !defined PRId64 || PRI_MACROS_BROKEN
183 # undef PRId64
184 # define PRId64 (sizeof (long) == 8 ? "ld" : "lld")
185 #endif
186 #if !defined PRIi64 || PRI_MACROS_BROKEN
187 # undef PRIi64
188 # define PRIi64 (sizeof (long) == 8 ? "li" : "lli")
189 #endif
190 #if !defined PRIo64 || PRI_MACROS_BROKEN
191 # undef PRIo64
192 # define PRIo64 (sizeof (long) == 8 ? "lo" : "llo")
193 #endif
194 #if !defined PRIu64 || PRI_MACROS_BROKEN
195 # undef PRIu64
196 # define PRIu64 (sizeof (long) == 8 ? "lu" : "llu")
197 #endif
198 #if !defined PRIx64 || PRI_MACROS_BROKEN
199 # undef PRIx64
200 # define PRIx64 (sizeof (long) == 8 ? "lx" : "llx")
201 #endif
202 #if !defined PRIX64 || PRI_MACROS_BROKEN
203 # undef PRIX64
204 # define PRIX64 (sizeof (long) == 8 ? "lX" : "llX")
205 #endif
206 #if !defined PRIdLEAST8 || PRI_MACROS_BROKEN
207 # undef PRIdLEAST8
208 # define PRIdLEAST8 "d"
209 #endif
210 #if !defined PRIiLEAST8 || PRI_MACROS_BROKEN
211 # undef PRIiLEAST8
212 # define PRIiLEAST8 "i"
213 #endif
214 #if !defined PRIoLEAST8 || PRI_MACROS_BROKEN
215 # undef PRIoLEAST8
216 # define PRIoLEAST8 "o"
217 #endif
218 #if !defined PRIuLEAST8 || PRI_MACROS_BROKEN
219 # undef PRIuLEAST8
220 # define PRIuLEAST8 "u"
221 #endif
222 #if !defined PRIxLEAST8 || PRI_MACROS_BROKEN
223 # undef PRIxLEAST8
224 # define PRIxLEAST8 "x"
225 #endif
226 #if !defined PRIXLEAST8 || PRI_MACROS_BROKEN
227 # undef PRIXLEAST8
228 # define PRIXLEAST8 "X"
229 #endif
230 #if !defined PRIdLEAST16 || PRI_MACROS_BROKEN
231 # undef PRIdLEAST16
232 # define PRIdLEAST16 "d"
233 #endif
234 #if !defined PRIiLEAST16 || PRI_MACROS_BROKEN
235 # undef PRIiLEAST16
236 # define PRIiLEAST16 "i"
237 #endif
238 #if !defined PRIoLEAST16 || PRI_MACROS_BROKEN
239 # undef PRIoLEAST16
240 # define PRIoLEAST16 "o"
241 #endif
242 #if !defined PRIuLEAST16 || PRI_MACROS_BROKEN
243 # undef PRIuLEAST16
244 # define PRIuLEAST16 "u"
245 #endif
246 #if !defined PRIxLEAST16 || PRI_MACROS_BROKEN
247 # undef PRIxLEAST16
248 # define PRIxLEAST16 "x"
249 #endif
250 #if !defined PRIXLEAST16 || PRI_MACROS_BROKEN
251 # undef PRIXLEAST16
252 # define PRIXLEAST16 "X"
253 #endif
254 #if !defined PRIdLEAST32 || PRI_MACROS_BROKEN
255 # undef PRIdLEAST32
256 # define PRIdLEAST32 "d"
257 #endif
258 #if !defined PRIiLEAST32 || PRI_MACROS_BROKEN
259 # undef PRIiLEAST32
260 # define PRIiLEAST32 "i"
261 #endif
262 #if !defined PRIoLEAST32 || PRI_MACROS_BROKEN
263 # undef PRIoLEAST32
264 # define PRIoLEAST32 "o"
265 #endif
266 #if !defined PRIuLEAST32 || PRI_MACROS_BROKEN
267 # undef PRIuLEAST32
268 # define PRIuLEAST32 "u"
269 #endif
270 #if !defined PRIxLEAST32 || PRI_MACROS_BROKEN
271 # undef PRIxLEAST32
272 # define PRIxLEAST32 "x"
273 #endif
274 #if !defined PRIXLEAST32 || PRI_MACROS_BROKEN
275 # undef PRIXLEAST32
276 # define PRIXLEAST32 "X"
277 #endif
278 #if !defined PRIdLEAST64 || PRI_MACROS_BROKEN
279 # undef PRIdLEAST64
280 # define PRIdLEAST64 PRId64
281 #endif
282 #if !defined PRIiLEAST64 || PRI_MACROS_BROKEN
283 # undef PRIiLEAST64
284 # define PRIiLEAST64 PRIi64
285 #endif
286 #if !defined PRIoLEAST64 || PRI_MACROS_BROKEN
287 # undef PRIoLEAST64
288 # define PRIoLEAST64 PRIo64
289 #endif
290 #if !defined PRIuLEAST64 || PRI_MACROS_BROKEN
291 # undef PRIuLEAST64
292 # define PRIuLEAST64 PRIu64
293 #endif
294 #if !defined PRIxLEAST64 || PRI_MACROS_BROKEN
295 # undef PRIxLEAST64
296 # define PRIxLEAST64 PRIx64
297 #endif
298 #if !defined PRIXLEAST64 || PRI_MACROS_BROKEN
299 # undef PRIXLEAST64
300 # define PRIXLEAST64 PRIX64
301 #endif
302 #if !defined PRIdFAST8 || PRI_MACROS_BROKEN
303 # undef PRIdFAST8
304 # define PRIdFAST8 "d"
305 #endif
306 #if !defined PRIiFAST8 || PRI_MACROS_BROKEN
307 # undef PRIiFAST8
308 # define PRIiFAST8 "i"
309 #endif
310 #if !defined PRIoFAST8 || PRI_MACROS_BROKEN
311 # undef PRIoFAST8
312 # define PRIoFAST8 "o"
313 #endif
314 #if !defined PRIuFAST8 || PRI_MACROS_BROKEN
315 # undef PRIuFAST8
316 # define PRIuFAST8 "u"
317 #endif
318 #if !defined PRIxFAST8 || PRI_MACROS_BROKEN
319 # undef PRIxFAST8
320 # define PRIxFAST8 "x"
321 #endif
322 #if !defined PRIXFAST8 || PRI_MACROS_BROKEN
323 # undef PRIXFAST8
324 # define PRIXFAST8 "X"
325 #endif
326 #if !defined PRIdFAST16 || PRI_MACROS_BROKEN
327 # undef PRIdFAST16
328 # define PRIdFAST16 "d"
329 #endif
330 #if !defined PRIiFAST16 || PRI_MACROS_BROKEN
331 # undef PRIiFAST16
332 # define PRIiFAST16 "i"
333 #endif
334 #if !defined PRIoFAST16 || PRI_MACROS_BROKEN
335 # undef PRIoFAST16
336 # define PRIoFAST16 "o"
337 #endif
338 #if !defined PRIuFAST16 || PRI_MACROS_BROKEN
339 # undef PRIuFAST16
340 # define PRIuFAST16 "u"
341 #endif
342 #if !defined PRIxFAST16 || PRI_MACROS_BROKEN
343 # undef PRIxFAST16
344 # define PRIxFAST16 "x"
345 #endif
346 #if !defined PRIXFAST16 || PRI_MACROS_BROKEN
347 # undef PRIXFAST16
348 # define PRIXFAST16 "X"
349 #endif
350 #if !defined PRIdFAST32 || PRI_MACROS_BROKEN
351 # undef PRIdFAST32
352 # define PRIdFAST32 "d"
353 #endif
354 #if !defined PRIiFAST32 || PRI_MACROS_BROKEN
355 # undef PRIiFAST32
356 # define PRIiFAST32 "i"
357 #endif
358 #if !defined PRIoFAST32 || PRI_MACROS_BROKEN
359 # undef PRIoFAST32
360 # define PRIoFAST32 "o"
361 #endif
362 #if !defined PRIuFAST32 || PRI_MACROS_BROKEN
363 # undef PRIuFAST32
364 # define PRIuFAST32 "u"
365 #endif
366 #if !defined PRIxFAST32 || PRI_MACROS_BROKEN
367 # undef PRIxFAST32
368 # define PRIxFAST32 "x"
369 #endif
370 #if !defined PRIXFAST32 || PRI_MACROS_BROKEN
371 # undef PRIXFAST32
372 # define PRIXFAST32 "X"
373 #endif
374 #if !defined PRIdFAST64 || PRI_MACROS_BROKEN
375 # undef PRIdFAST64
376 # define PRIdFAST64 PRId64
377 #endif
378 #if !defined PRIiFAST64 || PRI_MACROS_BROKEN
379 # undef PRIiFAST64
380 # define PRIiFAST64 PRIi64
381 #endif
382 #if !defined PRIoFAST64 || PRI_MACROS_BROKEN
383 # undef PRIoFAST64
384 # define PRIoFAST64 PRIo64
385 #endif
386 #if !defined PRIuFAST64 || PRI_MACROS_BROKEN
387 # undef PRIuFAST64
388 # define PRIuFAST64 PRIu64
389 #endif
390 #if !defined PRIxFAST64 || PRI_MACROS_BROKEN
391 # undef PRIxFAST64
392 # define PRIxFAST64 PRIx64
393 #endif
394 #if !defined PRIXFAST64 || PRI_MACROS_BROKEN
395 # undef PRIXFAST64
396 # define PRIXFAST64 PRIX64
397 #endif
398 #if !defined PRIdMAX || PRI_MACROS_BROKEN
399 # undef PRIdMAX
400 # define PRIdMAX (sizeof (uintmax_t) == sizeof (long) ? "ld" : "lld")
401 #endif
402 #if !defined PRIiMAX || PRI_MACROS_BROKEN
403 # undef PRIiMAX
404 # define PRIiMAX (sizeof (uintmax_t) == sizeof (long) ? "li" : "lli")
405 #endif
406 #if !defined PRIoMAX || PRI_MACROS_BROKEN
407 # undef PRIoMAX
408 # define PRIoMAX (sizeof (uintmax_t) == sizeof (long) ? "lo" : "llo")
409 #endif
410 #if !defined PRIuMAX || PRI_MACROS_BROKEN
411 # undef PRIuMAX
412 # define PRIuMAX (sizeof (uintmax_t) == sizeof (long) ? "lu" : "llu")
413 #endif
414 #if !defined PRIxMAX || PRI_MACROS_BROKEN
415 # undef PRIxMAX
416 # define PRIxMAX (sizeof (uintmax_t) == sizeof (long) ? "lx" : "llx")
417 #endif
418 #if !defined PRIXMAX || PRI_MACROS_BROKEN
419 # undef PRIXMAX
420 # define PRIXMAX (sizeof (uintmax_t) == sizeof (long) ? "lX" : "llX")
421 #endif
422 #if !defined PRIdPTR || PRI_MACROS_BROKEN
423 # undef PRIdPTR
424 # define PRIdPTR \
425 (sizeof (void *) == sizeof (long) ? "ld" : \
426 sizeof (void *) == sizeof (int) ? "d" : \
427 "lld")
428 #endif
429 #if !defined PRIiPTR || PRI_MACROS_BROKEN
430 # undef PRIiPTR
431 # define PRIiPTR \
432 (sizeof (void *) == sizeof (long) ? "li" : \
433 sizeof (void *) == sizeof (int) ? "i" : \
434 "lli")
435 #endif
436 #if !defined PRIoPTR || PRI_MACROS_BROKEN
437 # undef PRIoPTR
438 # define PRIoPTR \
439 (sizeof (void *) == sizeof (long) ? "lo" : \
440 sizeof (void *) == sizeof (int) ? "o" : \
441 "llo")
442 #endif
443 #if !defined PRIuPTR || PRI_MACROS_BROKEN
444 # undef PRIuPTR
445 # define PRIuPTR \
446 (sizeof (void *) == sizeof (long) ? "lu" : \
447 sizeof (void *) == sizeof (int) ? "u" : \
448 "llu")
449 #endif
450 #if !defined PRIxPTR || PRI_MACROS_BROKEN
451 # undef PRIxPTR
452 # define PRIxPTR \
453 (sizeof (void *) == sizeof (long) ? "lx" : \
454 sizeof (void *) == sizeof (int) ? "x" : \
455 "llx")
456 #endif
457 #if !defined PRIXPTR || PRI_MACROS_BROKEN
458 # undef PRIXPTR
459 # define PRIXPTR \
460 (sizeof (void *) == sizeof (long) ? "lX" : \
461 sizeof (void *) == sizeof (int) ? "X" : \
462 "llX")
463 #endif
465 /* @@ end of prolog @@ */
467 #ifdef _LIBC
468 /* Rename the non ISO C functions. This is required by the standard
469 because some ISO C functions will require linking with this object
470 file and the name space must not be polluted. */
471 # define open(name, flags) open_not_cancel_2 (name, flags)
472 # define close(fd) close_not_cancel_no_status (fd)
473 # define read(fd, buf, n) read_not_cancel (fd, buf, n)
474 # define mmap(addr, len, prot, flags, fd, offset) \
475 __mmap (addr, len, prot, flags, fd, offset)
476 # define munmap(addr, len) __munmap (addr, len)
477 #endif
479 /* For those losing systems which don't have `alloca' we have to add
480 some additional code emulating it. */
481 #ifdef HAVE_ALLOCA
482 # define freea(p) /* nothing */
483 #else
484 # define alloca(n) malloc (n)
485 # define freea(p) free (p)
486 #endif
488 /* For systems that distinguish between text and binary I/O.
489 O_BINARY is usually declared in <fcntl.h>. */
490 #if !defined O_BINARY && defined _O_BINARY
491 /* For MSC-compatible compilers. */
492 # define O_BINARY _O_BINARY
493 # define O_TEXT _O_TEXT
494 #endif
495 #ifdef __BEOS__
496 /* BeOS 5 has O_BINARY and O_TEXT, but they have no effect. */
497 # undef O_BINARY
498 # undef O_TEXT
499 #endif
500 /* On reasonable systems, binary I/O is the default. */
501 #ifndef O_BINARY
502 # define O_BINARY 0
503 #endif
506 /* We need a sign, whether a new catalog was loaded, which can be associated
507 with all translations. This is important if the translations are
508 cached by one of GCC's features. */
509 int _nl_msg_cat_cntr;
512 /* Expand a system dependent string segment. Return NULL if unsupported. */
513 static const char *
514 get_sysdep_segment_value (const char *name)
516 /* Test for an ISO C 99 section 7.8.1 format string directive.
517 Syntax:
518 P R I { d | i | o | u | x | X }
519 { { | LEAST | FAST } { 8 | 16 | 32 | 64 } | MAX | PTR } */
520 /* We don't use a table of 14 times 6 'const char *' strings here, because
521 data relocations cost startup time. */
522 if (name[0] == 'P' && name[1] == 'R' && name[2] == 'I')
524 if (name[3] == 'd' || name[3] == 'i' || name[3] == 'o' || name[3] == 'u'
525 || name[3] == 'x' || name[3] == 'X')
527 if (name[4] == '8' && name[5] == '\0')
529 if (name[3] == 'd')
530 return PRId8;
531 if (name[3] == 'i')
532 return PRIi8;
533 if (name[3] == 'o')
534 return PRIo8;
535 if (name[3] == 'u')
536 return PRIu8;
537 if (name[3] == 'x')
538 return PRIx8;
539 if (name[3] == 'X')
540 return PRIX8;
541 abort ();
543 if (name[4] == '1' && name[5] == '6' && name[6] == '\0')
545 if (name[3] == 'd')
546 return PRId16;
547 if (name[3] == 'i')
548 return PRIi16;
549 if (name[3] == 'o')
550 return PRIo16;
551 if (name[3] == 'u')
552 return PRIu16;
553 if (name[3] == 'x')
554 return PRIx16;
555 if (name[3] == 'X')
556 return PRIX16;
557 abort ();
559 if (name[4] == '3' && name[5] == '2' && name[6] == '\0')
561 if (name[3] == 'd')
562 return PRId32;
563 if (name[3] == 'i')
564 return PRIi32;
565 if (name[3] == 'o')
566 return PRIo32;
567 if (name[3] == 'u')
568 return PRIu32;
569 if (name[3] == 'x')
570 return PRIx32;
571 if (name[3] == 'X')
572 return PRIX32;
573 abort ();
575 if (name[4] == '6' && name[5] == '4' && name[6] == '\0')
577 if (name[3] == 'd')
578 return PRId64;
579 if (name[3] == 'i')
580 return PRIi64;
581 if (name[3] == 'o')
582 return PRIo64;
583 if (name[3] == 'u')
584 return PRIu64;
585 if (name[3] == 'x')
586 return PRIx64;
587 if (name[3] == 'X')
588 return PRIX64;
589 abort ();
591 if (name[4] == 'L' && name[5] == 'E' && name[6] == 'A'
592 && name[7] == 'S' && name[8] == 'T')
594 if (name[9] == '8' && name[10] == '\0')
596 if (name[3] == 'd')
597 return PRIdLEAST8;
598 if (name[3] == 'i')
599 return PRIiLEAST8;
600 if (name[3] == 'o')
601 return PRIoLEAST8;
602 if (name[3] == 'u')
603 return PRIuLEAST8;
604 if (name[3] == 'x')
605 return PRIxLEAST8;
606 if (name[3] == 'X')
607 return PRIXLEAST8;
608 abort ();
610 if (name[9] == '1' && name[10] == '6' && name[11] == '\0')
612 if (name[3] == 'd')
613 return PRIdLEAST16;
614 if (name[3] == 'i')
615 return PRIiLEAST16;
616 if (name[3] == 'o')
617 return PRIoLEAST16;
618 if (name[3] == 'u')
619 return PRIuLEAST16;
620 if (name[3] == 'x')
621 return PRIxLEAST16;
622 if (name[3] == 'X')
623 return PRIXLEAST16;
624 abort ();
626 if (name[9] == '3' && name[10] == '2' && name[11] == '\0')
628 if (name[3] == 'd')
629 return PRIdLEAST32;
630 if (name[3] == 'i')
631 return PRIiLEAST32;
632 if (name[3] == 'o')
633 return PRIoLEAST32;
634 if (name[3] == 'u')
635 return PRIuLEAST32;
636 if (name[3] == 'x')
637 return PRIxLEAST32;
638 if (name[3] == 'X')
639 return PRIXLEAST32;
640 abort ();
642 if (name[9] == '6' && name[10] == '4' && name[11] == '\0')
644 if (name[3] == 'd')
645 return PRIdLEAST64;
646 if (name[3] == 'i')
647 return PRIiLEAST64;
648 if (name[3] == 'o')
649 return PRIoLEAST64;
650 if (name[3] == 'u')
651 return PRIuLEAST64;
652 if (name[3] == 'x')
653 return PRIxLEAST64;
654 if (name[3] == 'X')
655 return PRIXLEAST64;
656 abort ();
659 if (name[4] == 'F' && name[5] == 'A' && name[6] == 'S'
660 && name[7] == 'T')
662 if (name[8] == '8' && name[9] == '\0')
664 if (name[3] == 'd')
665 return PRIdFAST8;
666 if (name[3] == 'i')
667 return PRIiFAST8;
668 if (name[3] == 'o')
669 return PRIoFAST8;
670 if (name[3] == 'u')
671 return PRIuFAST8;
672 if (name[3] == 'x')
673 return PRIxFAST8;
674 if (name[3] == 'X')
675 return PRIXFAST8;
676 abort ();
678 if (name[8] == '1' && name[9] == '6' && name[10] == '\0')
680 if (name[3] == 'd')
681 return PRIdFAST16;
682 if (name[3] == 'i')
683 return PRIiFAST16;
684 if (name[3] == 'o')
685 return PRIoFAST16;
686 if (name[3] == 'u')
687 return PRIuFAST16;
688 if (name[3] == 'x')
689 return PRIxFAST16;
690 if (name[3] == 'X')
691 return PRIXFAST16;
692 abort ();
694 if (name[8] == '3' && name[9] == '2' && name[10] == '\0')
696 if (name[3] == 'd')
697 return PRIdFAST32;
698 if (name[3] == 'i')
699 return PRIiFAST32;
700 if (name[3] == 'o')
701 return PRIoFAST32;
702 if (name[3] == 'u')
703 return PRIuFAST32;
704 if (name[3] == 'x')
705 return PRIxFAST32;
706 if (name[3] == 'X')
707 return PRIXFAST32;
708 abort ();
710 if (name[8] == '6' && name[9] == '4' && name[10] == '\0')
712 if (name[3] == 'd')
713 return PRIdFAST64;
714 if (name[3] == 'i')
715 return PRIiFAST64;
716 if (name[3] == 'o')
717 return PRIoFAST64;
718 if (name[3] == 'u')
719 return PRIuFAST64;
720 if (name[3] == 'x')
721 return PRIxFAST64;
722 if (name[3] == 'X')
723 return PRIXFAST64;
724 abort ();
727 if (name[4] == 'M' && name[5] == 'A' && name[6] == 'X'
728 && name[7] == '\0')
730 if (name[3] == 'd')
731 return PRIdMAX;
732 if (name[3] == 'i')
733 return PRIiMAX;
734 if (name[3] == 'o')
735 return PRIoMAX;
736 if (name[3] == 'u')
737 return PRIuMAX;
738 if (name[3] == 'x')
739 return PRIxMAX;
740 if (name[3] == 'X')
741 return PRIXMAX;
742 abort ();
744 if (name[4] == 'P' && name[5] == 'T' && name[6] == 'R'
745 && name[7] == '\0')
747 if (name[3] == 'd')
748 return PRIdPTR;
749 if (name[3] == 'i')
750 return PRIiPTR;
751 if (name[3] == 'o')
752 return PRIoPTR;
753 if (name[3] == 'u')
754 return PRIuPTR;
755 if (name[3] == 'x')
756 return PRIxPTR;
757 if (name[3] == 'X')
758 return PRIXPTR;
759 abort ();
763 /* Test for a glibc specific printf() format directive flag. */
764 if (name[0] == 'I' && name[1] == '\0')
766 #if defined _LIBC \
767 || ((__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2)) \
768 && !defined __UCLIBC__)
769 /* The 'I' flag, in numeric format directives, replaces ASCII digits
770 with the 'outdigits' defined in the LC_CTYPE locale facet. This is
771 used for Farsi (Persian), some Indic languages, and maybe Arabic. */
772 return "I";
773 #else
774 return "";
775 #endif
777 /* Other system dependent strings are not valid. */
778 return NULL;
781 /* Load the message catalogs specified by FILENAME. If it is no valid
782 message catalog do nothing. */
783 void
784 internal_function
785 _nl_load_domain (struct loaded_l10nfile *domain_file,
786 struct binding *domainbinding)
788 __libc_lock_define_initialized_recursive (static, lock);
789 int fd = -1;
790 size_t size;
791 #ifdef _LIBC
792 struct stat64 st;
793 #else
794 struct stat st;
795 #endif
796 struct mo_file_header *data = (struct mo_file_header *) -1;
797 int use_mmap = 0;
798 struct loaded_domain *domain;
799 int revision;
800 const char *nullentry;
801 size_t nullentrylen;
803 __libc_lock_lock_recursive (lock);
804 if (domain_file->decided != 0)
806 /* There are two possibilities:
808 + this is the same thread calling again during this initialization
809 via _nl_find_msg. We have initialized everything this call needs.
811 + this is another thread which tried to initialize this object.
812 Not necessary anymore since if the lock is available this
813 is finished.
815 goto done;
818 domain_file->decided = -1;
819 domain_file->data = NULL;
821 /* Note that it would be useless to store domainbinding in domain_file
822 because domainbinding might be == NULL now but != NULL later (after
823 a call to bind_textdomain_codeset). */
825 /* If the record does not represent a valid locale the FILENAME
826 might be NULL. This can happen when according to the given
827 specification the locale file name is different for XPG and CEN
828 syntax. */
829 if (domain_file->filename == NULL)
830 goto out;
832 /* Try to open the addressed file. */
833 fd = open (domain_file->filename, O_RDONLY | O_BINARY);
834 if (fd == -1)
835 goto out;
837 /* We must know about the size of the file. */
838 if (
839 #ifdef _LIBC
840 __builtin_expect (fstat64 (fd, &st) != 0, 0)
841 #else
842 __builtin_expect (fstat (fd, &st) != 0, 0)
843 #endif
844 || __builtin_expect ((size = (size_t) st.st_size) != st.st_size, 0)
845 || __builtin_expect (size < sizeof (struct mo_file_header), 0))
846 /* Something went wrong. */
847 goto out;
849 #ifdef HAVE_MMAP
850 /* Now we are ready to load the file. If mmap() is available we try
851 this first. If not available or it failed we try to load it. */
852 data = (struct mo_file_header *) mmap (NULL, size, PROT_READ,
853 MAP_PRIVATE, fd, 0);
855 if (__builtin_expect (data != MAP_FAILED, 1))
857 /* mmap() call was successful. */
858 close (fd);
859 fd = -1;
860 use_mmap = 1;
863 assert (MAP_FAILED == (void *) -1);
864 #endif
866 /* If the data is not yet available (i.e. mmap'ed) we try to load
867 it manually. */
868 if (data == (struct mo_file_header *) -1)
870 size_t to_read;
871 char *read_ptr;
873 data = (struct mo_file_header *) malloc (size);
874 if (data == NULL)
875 goto out;
877 to_read = size;
878 read_ptr = (char *) data;
881 long int nb = (long int) read (fd, read_ptr, to_read);
882 if (nb <= 0)
884 #ifdef EINTR
885 if (nb == -1 && errno == EINTR)
886 continue;
887 #endif
888 goto out;
890 read_ptr += nb;
891 to_read -= nb;
893 while (to_read > 0);
895 close (fd);
896 fd = -1;
899 /* Using the magic number we can test whether it really is a message
900 catalog file. */
901 if (__builtin_expect (data->magic != _MAGIC && data->magic != _MAGIC_SWAPPED,
904 /* The magic number is wrong: not a message catalog file. */
905 #ifdef HAVE_MMAP
906 if (use_mmap)
907 munmap ((caddr_t) data, size);
908 else
909 #endif
910 free (data);
911 goto out;
914 domain = (struct loaded_domain *) malloc (sizeof (struct loaded_domain));
915 if (domain == NULL)
916 goto out;
917 domain_file->data = domain;
919 domain->data = (char *) data;
920 domain->use_mmap = use_mmap;
921 domain->mmap_size = size;
922 domain->must_swap = data->magic != _MAGIC;
923 domain->malloced = NULL;
925 /* Fill in the information about the available tables. */
926 revision = W (domain->must_swap, data->revision);
927 /* We support only the major revisions 0 and 1. */
928 switch (revision >> 16)
930 case 0:
931 case 1:
932 domain->nstrings = W (domain->must_swap, data->nstrings);
933 domain->orig_tab = (const struct string_desc *)
934 ((char *) data + W (domain->must_swap, data->orig_tab_offset));
935 domain->trans_tab = (const struct string_desc *)
936 ((char *) data + W (domain->must_swap, data->trans_tab_offset));
937 domain->hash_size = W (domain->must_swap, data->hash_tab_size);
938 domain->hash_tab =
939 (domain->hash_size > 2
940 ? (const nls_uint32 *)
941 ((char *) data + W (domain->must_swap, data->hash_tab_offset))
942 : NULL);
943 domain->must_swap_hash_tab = domain->must_swap;
945 /* Now dispatch on the minor revision. */
946 switch (revision & 0xffff)
948 case 0:
949 domain->n_sysdep_strings = 0;
950 domain->orig_sysdep_tab = NULL;
951 domain->trans_sysdep_tab = NULL;
952 break;
953 case 1:
954 default:
956 nls_uint32 n_sysdep_strings;
958 if (domain->hash_tab == NULL)
959 /* This is invalid. These minor revisions need a hash table. */
960 goto invalid;
962 n_sysdep_strings =
963 W (domain->must_swap, data->n_sysdep_strings);
964 if (n_sysdep_strings > 0)
966 nls_uint32 n_sysdep_segments;
967 const struct sysdep_segment *sysdep_segments;
968 const char **sysdep_segment_values;
969 const nls_uint32 *orig_sysdep_tab;
970 const nls_uint32 *trans_sysdep_tab;
971 nls_uint32 n_inmem_sysdep_strings;
972 size_t memneed;
973 char *mem;
974 struct sysdep_string_desc *inmem_orig_sysdep_tab;
975 struct sysdep_string_desc *inmem_trans_sysdep_tab;
976 nls_uint32 *inmem_hash_tab;
977 unsigned int i, j;
979 /* Get the values of the system dependent segments. */
980 n_sysdep_segments =
981 W (domain->must_swap, data->n_sysdep_segments);
982 sysdep_segments = (const struct sysdep_segment *)
983 ((char *) data
984 + W (domain->must_swap, data->sysdep_segments_offset));
985 sysdep_segment_values =
986 (const char **)
987 alloca (n_sysdep_segments * sizeof (const char *));
988 for (i = 0; i < n_sysdep_segments; i++)
990 const char *name =
991 (char *) data
992 + W (domain->must_swap, sysdep_segments[i].offset);
993 nls_uint32 namelen =
994 W (domain->must_swap, sysdep_segments[i].length);
996 if (!(namelen > 0 && name[namelen - 1] == '\0'))
998 freea (sysdep_segment_values);
999 goto invalid;
1002 sysdep_segment_values[i] = get_sysdep_segment_value (name);
1005 orig_sysdep_tab = (const nls_uint32 *)
1006 ((char *) data
1007 + W (domain->must_swap, data->orig_sysdep_tab_offset));
1008 trans_sysdep_tab = (const nls_uint32 *)
1009 ((char *) data
1010 + W (domain->must_swap, data->trans_sysdep_tab_offset));
1012 /* Compute the amount of additional memory needed for the
1013 system dependent strings and the augmented hash table.
1014 At the same time, also drop string pairs which refer to
1015 an undefined system dependent segment. */
1016 n_inmem_sysdep_strings = 0;
1017 memneed = domain->hash_size * sizeof (nls_uint32);
1018 for (i = 0; i < n_sysdep_strings; i++)
1020 int valid = 1;
1021 size_t needs[2];
1023 for (j = 0; j < 2; j++)
1025 const struct sysdep_string *sysdep_string =
1026 (const struct sysdep_string *)
1027 ((char *) data
1028 + W (domain->must_swap,
1029 j == 0
1030 ? orig_sysdep_tab[i]
1031 : trans_sysdep_tab[i]));
1032 size_t need = 0;
1033 const struct segment_pair *p = sysdep_string->segments;
1035 if (W (domain->must_swap, p->sysdepref) != SEGMENTS_END)
1036 for (p = sysdep_string->segments;; p++)
1038 nls_uint32 sysdepref;
1040 need += W (domain->must_swap, p->segsize);
1042 sysdepref = W (domain->must_swap, p->sysdepref);
1043 if (sysdepref == SEGMENTS_END)
1044 break;
1046 if (sysdepref >= n_sysdep_segments)
1048 /* Invalid. */
1049 freea (sysdep_segment_values);
1050 goto invalid;
1053 if (sysdep_segment_values[sysdepref] == NULL)
1055 /* This particular string pair is invalid. */
1056 valid = 0;
1057 break;
1060 need += strlen (sysdep_segment_values[sysdepref]);
1063 needs[j] = need;
1064 if (!valid)
1065 break;
1068 if (valid)
1070 n_inmem_sysdep_strings++;
1071 memneed += needs[0] + needs[1];
1074 memneed += 2 * n_inmem_sysdep_strings
1075 * sizeof (struct sysdep_string_desc);
1077 if (n_inmem_sysdep_strings > 0)
1079 unsigned int k;
1081 /* Allocate additional memory. */
1082 mem = (char *) malloc (memneed);
1083 if (mem == NULL)
1084 goto invalid;
1086 domain->malloced = mem;
1087 inmem_orig_sysdep_tab = (struct sysdep_string_desc *) mem;
1088 mem += n_inmem_sysdep_strings
1089 * sizeof (struct sysdep_string_desc);
1090 inmem_trans_sysdep_tab = (struct sysdep_string_desc *) mem;
1091 mem += n_inmem_sysdep_strings
1092 * sizeof (struct sysdep_string_desc);
1093 inmem_hash_tab = (nls_uint32 *) mem;
1094 mem += domain->hash_size * sizeof (nls_uint32);
1096 /* Compute the system dependent strings. */
1097 k = 0;
1098 for (i = 0; i < n_sysdep_strings; i++)
1100 int valid = 1;
1102 for (j = 0; j < 2; j++)
1104 const struct sysdep_string *sysdep_string =
1105 (const struct sysdep_string *)
1106 ((char *) data
1107 + W (domain->must_swap,
1108 j == 0
1109 ? orig_sysdep_tab[i]
1110 : trans_sysdep_tab[i]));
1111 const struct segment_pair *p =
1112 sysdep_string->segments;
1114 if (W (domain->must_swap, p->sysdepref)
1115 != SEGMENTS_END)
1116 for (p = sysdep_string->segments;; p++)
1118 nls_uint32 sysdepref;
1120 sysdepref =
1121 W (domain->must_swap, p->sysdepref);
1122 if (sysdepref == SEGMENTS_END)
1123 break;
1125 if (sysdep_segment_values[sysdepref] == NULL)
1127 /* This particular string pair is
1128 invalid. */
1129 valid = 0;
1130 break;
1134 if (!valid)
1135 break;
1138 if (valid)
1140 for (j = 0; j < 2; j++)
1142 const struct sysdep_string *sysdep_string =
1143 (const struct sysdep_string *)
1144 ((char *) data
1145 + W (domain->must_swap,
1146 j == 0
1147 ? orig_sysdep_tab[i]
1148 : trans_sysdep_tab[i]));
1149 const char *static_segments =
1150 (char *) data
1151 + W (domain->must_swap, sysdep_string->offset);
1152 const struct segment_pair *p =
1153 sysdep_string->segments;
1155 /* Concatenate the segments, and fill
1156 inmem_orig_sysdep_tab[k] (for j == 0) and
1157 inmem_trans_sysdep_tab[k] (for j == 1). */
1159 struct sysdep_string_desc *inmem_tab_entry =
1160 (j == 0
1161 ? inmem_orig_sysdep_tab
1162 : inmem_trans_sysdep_tab)
1163 + k;
1165 if (W (domain->must_swap, p->sysdepref)
1166 == SEGMENTS_END)
1168 /* Only one static segment. */
1169 inmem_tab_entry->length =
1170 W (domain->must_swap, p->segsize);
1171 inmem_tab_entry->pointer = static_segments;
1173 else
1175 inmem_tab_entry->pointer = mem;
1177 for (p = sysdep_string->segments;; p++)
1179 nls_uint32 segsize =
1180 W (domain->must_swap, p->segsize);
1181 nls_uint32 sysdepref =
1182 W (domain->must_swap, p->sysdepref);
1183 size_t n;
1185 if (segsize > 0)
1187 memcpy (mem, static_segments, segsize);
1188 mem += segsize;
1189 static_segments += segsize;
1192 if (sysdepref == SEGMENTS_END)
1193 break;
1195 n = strlen (sysdep_segment_values[sysdepref]);
1196 memcpy (mem, sysdep_segment_values[sysdepref], n);
1197 mem += n;
1200 inmem_tab_entry->length =
1201 mem - inmem_tab_entry->pointer;
1205 k++;
1208 if (k != n_inmem_sysdep_strings)
1209 abort ();
1211 /* Compute the augmented hash table. */
1212 for (i = 0; i < domain->hash_size; i++)
1213 inmem_hash_tab[i] =
1214 W (domain->must_swap_hash_tab, domain->hash_tab[i]);
1215 for (i = 0; i < n_inmem_sysdep_strings; i++)
1217 const char *msgid = inmem_orig_sysdep_tab[i].pointer;
1218 nls_uint32 hash_val = __hash_string (msgid);
1219 nls_uint32 idx = hash_val % domain->hash_size;
1220 nls_uint32 incr =
1221 1 + (hash_val % (domain->hash_size - 2));
1223 for (;;)
1225 if (inmem_hash_tab[idx] == 0)
1227 /* Hash table entry is empty. Use it. */
1228 inmem_hash_tab[idx] = 1 + domain->nstrings + i;
1229 break;
1232 if (idx >= domain->hash_size - incr)
1233 idx -= domain->hash_size - incr;
1234 else
1235 idx += incr;
1239 domain->n_sysdep_strings = n_inmem_sysdep_strings;
1240 domain->orig_sysdep_tab = inmem_orig_sysdep_tab;
1241 domain->trans_sysdep_tab = inmem_trans_sysdep_tab;
1243 domain->hash_tab = inmem_hash_tab;
1244 domain->must_swap_hash_tab = 0;
1246 else
1248 domain->n_sysdep_strings = 0;
1249 domain->orig_sysdep_tab = NULL;
1250 domain->trans_sysdep_tab = NULL;
1253 freea (sysdep_segment_values);
1255 else
1257 domain->n_sysdep_strings = 0;
1258 domain->orig_sysdep_tab = NULL;
1259 domain->trans_sysdep_tab = NULL;
1262 break;
1264 break;
1265 default:
1266 /* This is an invalid revision. */
1267 invalid:
1268 /* This is an invalid .mo file or we ran out of resources. */
1269 free (domain->malloced);
1270 #ifdef HAVE_MMAP
1271 if (use_mmap)
1272 munmap ((caddr_t) data, size);
1273 else
1274 #endif
1275 free (data);
1276 free (domain);
1277 domain_file->data = NULL;
1278 goto out;
1281 /* No caches of converted translations so far. */
1282 domain->conversions = NULL;
1283 domain->nconversions = 0;
1284 #ifdef _LIBC
1285 __libc_rwlock_init (domain->conversions_lock);
1286 #else
1287 gl_rwlock_init (domain->conversions_lock);
1288 #endif
1290 /* Get the header entry and look for a plural specification. */
1291 #ifdef IN_LIBGLOCALE
1292 nullentry =
1293 _nl_find_msg (domain_file, domainbinding, NULL, "", &nullentrylen);
1294 #else
1295 nullentry = _nl_find_msg (domain_file, domainbinding, "", 0, &nullentrylen);
1296 #endif
1297 if (__builtin_expect (nullentry == (char *) -1, 0))
1299 #ifdef _LIBC
1300 __libc_rwlock_fini (domain->conversions_lock);
1301 #endif
1302 goto invalid;
1304 EXTRACT_PLURAL_EXPRESSION (nullentry, &domain->plural, &domain->nplurals);
1306 out:
1307 if (fd != -1)
1308 close (fd);
1310 domain_file->decided = 1;
1312 done:
1313 __libc_lock_unlock_recursive (lock);
1317 #ifdef _LIBC
1318 void
1319 internal_function __libc_freeres_fn_section
1320 _nl_unload_domain (struct loaded_domain *domain)
1322 size_t i;
1324 if (domain->plural != &__gettext_germanic_plural)
1325 __gettext_free_exp ((struct expression *) domain->plural);
1327 for (i = 0; i < domain->nconversions; i++)
1329 struct converted_domain *convd = &domain->conversions[i];
1331 free ((char *) convd->encoding);
1332 if (convd->conv_tab != NULL && convd->conv_tab != (char **) -1)
1333 free (convd->conv_tab);
1334 if (convd->conv != (__gconv_t) -1)
1335 __gconv_close (convd->conv);
1337 free (domain->conversions);
1338 __libc_rwlock_fini (domain->conversions_lock);
1340 free (domain->malloced);
1342 # ifdef _POSIX_MAPPED_FILES
1343 if (domain->use_mmap)
1344 munmap ((caddr_t) domain->data, domain->mmap_size);
1345 else
1346 # endif /* _POSIX_MAPPED_FILES */
1347 free ((void *) domain->data);
1349 free (domain);
1351 #endif