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