Imported Upstream version 0.19.7
[platform/upstream/gettext.git] / gettext-runtime / intl / loadmsgcat.c
1 /* Load needed message catalogs.
2    Copyright (C) 1995-2015 Free Software Foundation, Inc.
3
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.
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
12    GNU Lesser General Public License for more details.
13
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/>.  */
16
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
23
24 #ifdef HAVE_CONFIG_H
25 # include <config.h>
26 #endif
27
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>
34
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
57
58 #include <stdlib.h>
59 #include <string.h>
60
61 #if defined HAVE_UNISTD_H || defined _LIBC
62 # include <unistd.h>
63 #endif
64
65 #ifdef _LIBC
66 # include <langinfo.h>
67 # include <locale.h>
68 #endif
69
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
78
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
85
86 #include "gmo.h"
87 #include "gettextP.h"
88 #include "hash-string.h"
89 #include "plural-exp.h"
90
91 #ifdef _LIBC
92 # include "../locale/localeinfo.h"
93 # include <not-cancel.h>
94 #endif
95
96 /* Handle multi-threaded applications.  */
97 #ifdef _LIBC
98 # include <bits/libc-lock.h>
99 #else
100 # include "lock.h"
101 #endif
102
103 #ifdef _LIBC
104 # define PRI_MACROS_BROKEN 0
105 #endif
106
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
464
465 /* @@ end of prolog @@ */
466
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
478
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
487
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
504
505
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;
510
511
512 /* Expand a system dependent string segment.  Return NULL if unsupported.  */
513 static const char *
514 get_sysdep_segment_value (const char *name)
515 {
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')
523     {
524       if (name[3] == 'd' || name[3] == 'i' || name[3] == 'o' || name[3] == 'u'
525           || name[3] == 'x' || name[3] == 'X')
526         {
527           if (name[4] == '8' && name[5] == '\0')
528             {
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 ();
542             }
543           if (name[4] == '1' && name[5] == '6' && name[6] == '\0')
544             {
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 ();
558             }
559           if (name[4] == '3' && name[5] == '2' && name[6] == '\0')
560             {
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 ();
574             }
575           if (name[4] == '6' && name[5] == '4' && name[6] == '\0')
576             {
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 ();
590             }
591           if (name[4] == 'L' && name[5] == 'E' && name[6] == 'A'
592               && name[7] == 'S' && name[8] == 'T')
593             {
594               if (name[9] == '8' && name[10] == '\0')
595                 {
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 ();
609                 }
610               if (name[9] == '1' && name[10] == '6' && name[11] == '\0')
611                 {
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 ();
625                 }
626               if (name[9] == '3' && name[10] == '2' && name[11] == '\0')
627                 {
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 ();
641                 }
642               if (name[9] == '6' && name[10] == '4' && name[11] == '\0')
643                 {
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 ();
657                 }
658             }
659           if (name[4] == 'F' && name[5] == 'A' && name[6] == 'S'
660               && name[7] == 'T')
661             {
662               if (name[8] == '8' && name[9] == '\0')
663                 {
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 ();
677                 }
678               if (name[8] == '1' && name[9] == '6' && name[10] == '\0')
679                 {
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 ();
693                 }
694               if (name[8] == '3' && name[9] == '2' && name[10] == '\0')
695                 {
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 ();
709                 }
710               if (name[8] == '6' && name[9] == '4' && name[10] == '\0')
711                 {
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 ();
725                 }
726             }
727           if (name[4] == 'M' && name[5] == 'A' && name[6] == 'X'
728               && name[7] == '\0')
729             {
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 ();
743             }
744           if (name[4] == 'P' && name[5] == 'T' && name[6] == 'R'
745               && name[7] == '\0')
746             {
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 ();
760             }
761         }
762     }
763   /* Test for a glibc specific printf() format directive flag.  */
764   if (name[0] == 'I' && name[1] == '\0')
765     {
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
776     }
777   /* Other system dependent strings are not valid.  */
778   return NULL;
779 }
780
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)
787 {
788   int fd = -1;
789   size_t size;
790 #ifdef _LIBC
791   struct stat64 st;
792 #else
793   struct stat st;
794 #endif
795   struct mo_file_header *data = (struct mo_file_header *) -1;
796   int use_mmap = 0;
797   struct loaded_domain *domain;
798   int revision;
799   const char *nullentry;
800   size_t nullentrylen;
801   __libc_lock_define_initialized_recursive (static, lock);
802
803   __libc_lock_lock_recursive (lock);
804   if (domain_file->decided != 0)
805     {
806       /* There are two possibilities:
807
808          + this is the same thread calling again during this initialization
809            via _nl_find_msg.  We have initialized everything this call needs.
810
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.
814       */
815       goto done;
816     }
817
818   domain_file->decided = -1;
819   domain_file->data = NULL;
820
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).  */
824
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;
831
832   /* Try to open the addressed file.  */
833   fd = open (domain_file->filename, O_RDONLY | O_BINARY);
834   if (fd == -1)
835     goto out;
836
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;
848
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);
854
855   if (__builtin_expect (data != MAP_FAILED, 1))
856     {
857       /* mmap() call was successful.  */
858       close (fd);
859       fd = -1;
860       use_mmap = 1;
861     }
862
863   assert (MAP_FAILED == (void *) -1);
864 #endif
865
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)
869     {
870       size_t to_read;
871       char *read_ptr;
872
873       data = (struct mo_file_header *) malloc (size);
874       if (data == NULL)
875         goto out;
876
877       to_read = size;
878       read_ptr = (char *) data;
879       do
880         {
881           long int nb = (long int) read (fd, read_ptr, to_read);
882           if (nb <= 0)
883             {
884 #ifdef EINTR
885               if (nb == -1 && errno == EINTR)
886                 continue;
887 #endif
888               free (data);
889               goto out;
890             }
891           read_ptr += nb;
892           to_read -= nb;
893         }
894       while (to_read > 0);
895
896       close (fd);
897       fd = -1;
898     }
899
900   /* Using the magic number we can test whether it really is a message
901      catalog file.  */
902   if (__builtin_expect (data->magic != _MAGIC && data->magic != _MAGIC_SWAPPED,
903                         0))
904     {
905       /* The magic number is wrong: not a message catalog file.  */
906 #ifdef HAVE_MMAP
907       if (use_mmap)
908         munmap ((caddr_t) data, size);
909       else
910 #endif
911         free (data);
912       goto out;
913     }
914
915   domain = (struct loaded_domain *) malloc (sizeof (struct loaded_domain));
916   if (domain == NULL)
917     goto out;
918   domain_file->data = domain;
919
920   domain->data = (char *) data;
921   domain->use_mmap = use_mmap;
922   domain->mmap_size = size;
923   domain->must_swap = data->magic != _MAGIC;
924   domain->malloced = NULL;
925
926   /* Fill in the information about the available tables.  */
927   revision = W (domain->must_swap, data->revision);
928   /* We support only the major revisions 0 and 1.  */
929   switch (revision >> 16)
930     {
931     case 0:
932     case 1:
933       domain->nstrings = W (domain->must_swap, data->nstrings);
934       domain->orig_tab = (const struct string_desc *)
935         ((char *) data + W (domain->must_swap, data->orig_tab_offset));
936       domain->trans_tab = (const struct string_desc *)
937         ((char *) data + W (domain->must_swap, data->trans_tab_offset));
938       domain->hash_size = W (domain->must_swap, data->hash_tab_size);
939       domain->hash_tab =
940         (domain->hash_size > 2
941          ? (const nls_uint32 *)
942            ((char *) data + W (domain->must_swap, data->hash_tab_offset))
943          : NULL);
944       domain->must_swap_hash_tab = domain->must_swap;
945
946       /* Now dispatch on the minor revision.  */
947       switch (revision & 0xffff)
948         {
949         case 0:
950           domain->n_sysdep_strings = 0;
951           domain->orig_sysdep_tab = NULL;
952           domain->trans_sysdep_tab = NULL;
953           break;
954         case 1:
955         default:
956           {
957             nls_uint32 n_sysdep_strings;
958
959             if (domain->hash_tab == NULL)
960               /* This is invalid.  These minor revisions need a hash table.  */
961               goto invalid;
962
963             n_sysdep_strings =
964               W (domain->must_swap, data->n_sysdep_strings);
965             if (n_sysdep_strings > 0)
966               {
967                 nls_uint32 n_sysdep_segments;
968                 const struct sysdep_segment *sysdep_segments;
969                 const char **sysdep_segment_values;
970                 const nls_uint32 *orig_sysdep_tab;
971                 const nls_uint32 *trans_sysdep_tab;
972                 nls_uint32 n_inmem_sysdep_strings;
973                 size_t memneed;
974                 char *mem;
975                 struct sysdep_string_desc *inmem_orig_sysdep_tab;
976                 struct sysdep_string_desc *inmem_trans_sysdep_tab;
977                 nls_uint32 *inmem_hash_tab;
978                 unsigned int i, j;
979
980                 /* Get the values of the system dependent segments.  */
981                 n_sysdep_segments =
982                   W (domain->must_swap, data->n_sysdep_segments);
983                 sysdep_segments = (const struct sysdep_segment *)
984                   ((char *) data
985                    + W (domain->must_swap, data->sysdep_segments_offset));
986                 sysdep_segment_values =
987                   (const char **)
988                   alloca (n_sysdep_segments * sizeof (const char *));
989                 for (i = 0; i < n_sysdep_segments; i++)
990                   {
991                     const char *name =
992                       (char *) data
993                       + W (domain->must_swap, sysdep_segments[i].offset);
994                     nls_uint32 namelen =
995                       W (domain->must_swap, sysdep_segments[i].length);
996
997                     if (!(namelen > 0 && name[namelen - 1] == '\0'))
998                       {
999                         freea (sysdep_segment_values);
1000                         goto invalid;
1001                       }
1002
1003                     sysdep_segment_values[i] = get_sysdep_segment_value (name);
1004                   }
1005
1006                 orig_sysdep_tab = (const nls_uint32 *)
1007                   ((char *) data
1008                    + W (domain->must_swap, data->orig_sysdep_tab_offset));
1009                 trans_sysdep_tab = (const nls_uint32 *)
1010                   ((char *) data
1011                    + W (domain->must_swap, data->trans_sysdep_tab_offset));
1012
1013                 /* Compute the amount of additional memory needed for the
1014                    system dependent strings and the augmented hash table.
1015                    At the same time, also drop string pairs which refer to
1016                    an undefined system dependent segment.  */
1017                 n_inmem_sysdep_strings = 0;
1018                 memneed = domain->hash_size * sizeof (nls_uint32);
1019                 for (i = 0; i < n_sysdep_strings; i++)
1020                   {
1021                     int valid = 1;
1022                     size_t needs[2];
1023
1024                     for (j = 0; j < 2; j++)
1025                       {
1026                         const struct sysdep_string *sysdep_string =
1027                           (const struct sysdep_string *)
1028                           ((char *) data
1029                            + W (domain->must_swap,
1030                                 j == 0
1031                                 ? orig_sysdep_tab[i]
1032                                 : trans_sysdep_tab[i]));
1033                         size_t need = 0;
1034                         const struct segment_pair *p = sysdep_string->segments;
1035
1036                         if (W (domain->must_swap, p->sysdepref) != SEGMENTS_END)
1037                           for (p = sysdep_string->segments;; p++)
1038                             {
1039                               nls_uint32 sysdepref;
1040
1041                               need += W (domain->must_swap, p->segsize);
1042
1043                               sysdepref = W (domain->must_swap, p->sysdepref);
1044                               if (sysdepref == SEGMENTS_END)
1045                                 break;
1046
1047                               if (sysdepref >= n_sysdep_segments)
1048                                 {
1049                                   /* Invalid.  */
1050                                   freea (sysdep_segment_values);
1051                                   goto invalid;
1052                                 }
1053
1054                               if (sysdep_segment_values[sysdepref] == NULL)
1055                                 {
1056                                   /* This particular string pair is invalid.  */
1057                                   valid = 0;
1058                                   break;
1059                                 }
1060
1061                               need += strlen (sysdep_segment_values[sysdepref]);
1062                             }
1063
1064                         needs[j] = need;
1065                         if (!valid)
1066                           break;
1067                       }
1068
1069                     if (valid)
1070                       {
1071                         n_inmem_sysdep_strings++;
1072                         memneed += needs[0] + needs[1];
1073                       }
1074                   }
1075                 memneed += 2 * n_inmem_sysdep_strings
1076                            * sizeof (struct sysdep_string_desc);
1077
1078                 if (n_inmem_sysdep_strings > 0)
1079                   {
1080                     unsigned int k;
1081
1082                     /* Allocate additional memory.  */
1083                     mem = (char *) malloc (memneed);
1084                     if (mem == NULL)
1085                       goto invalid;
1086
1087                     domain->malloced = mem;
1088                     inmem_orig_sysdep_tab = (struct sysdep_string_desc *) mem;
1089                     mem += n_inmem_sysdep_strings
1090                            * sizeof (struct sysdep_string_desc);
1091                     inmem_trans_sysdep_tab = (struct sysdep_string_desc *) mem;
1092                     mem += n_inmem_sysdep_strings
1093                            * sizeof (struct sysdep_string_desc);
1094                     inmem_hash_tab = (nls_uint32 *) mem;
1095                     mem += domain->hash_size * sizeof (nls_uint32);
1096
1097                     /* Compute the system dependent strings.  */
1098                     k = 0;
1099                     for (i = 0; i < n_sysdep_strings; i++)
1100                       {
1101                         int valid = 1;
1102
1103                         for (j = 0; j < 2; j++)
1104                           {
1105                             const struct sysdep_string *sysdep_string =
1106                               (const struct sysdep_string *)
1107                               ((char *) data
1108                                + W (domain->must_swap,
1109                                     j == 0
1110                                     ? orig_sysdep_tab[i]
1111                                     : trans_sysdep_tab[i]));
1112                             const struct segment_pair *p =
1113                               sysdep_string->segments;
1114
1115                             if (W (domain->must_swap, p->sysdepref)
1116                                 != SEGMENTS_END)
1117                               for (p = sysdep_string->segments;; p++)
1118                                 {
1119                                   nls_uint32 sysdepref;
1120
1121                                   sysdepref =
1122                                     W (domain->must_swap, p->sysdepref);
1123                                   if (sysdepref == SEGMENTS_END)
1124                                     break;
1125
1126                                   if (sysdep_segment_values[sysdepref] == NULL)
1127                                     {
1128                                       /* This particular string pair is
1129                                          invalid.  */
1130                                       valid = 0;
1131                                       break;
1132                                     }
1133                                 }
1134
1135                             if (!valid)
1136                               break;
1137                           }
1138
1139                         if (valid)
1140                           {
1141                             for (j = 0; j < 2; j++)
1142                               {
1143                                 const struct sysdep_string *sysdep_string =
1144                                   (const struct sysdep_string *)
1145                                   ((char *) data
1146                                    + W (domain->must_swap,
1147                                         j == 0
1148                                         ? orig_sysdep_tab[i]
1149                                         : trans_sysdep_tab[i]));
1150                                 const char *static_segments =
1151                                   (char *) data
1152                                   + W (domain->must_swap, sysdep_string->offset);
1153                                 const struct segment_pair *p =
1154                                   sysdep_string->segments;
1155
1156                                 /* Concatenate the segments, and fill
1157                                    inmem_orig_sysdep_tab[k] (for j == 0) and
1158                                    inmem_trans_sysdep_tab[k] (for j == 1).  */
1159
1160                                 struct sysdep_string_desc *inmem_tab_entry =
1161                                   (j == 0
1162                                    ? inmem_orig_sysdep_tab
1163                                    : inmem_trans_sysdep_tab)
1164                                   + k;
1165
1166                                 if (W (domain->must_swap, p->sysdepref)
1167                                     == SEGMENTS_END)
1168                                   {
1169                                     /* Only one static segment.  */
1170                                     inmem_tab_entry->length =
1171                                       W (domain->must_swap, p->segsize);
1172                                     inmem_tab_entry->pointer = static_segments;
1173                                   }
1174                                 else
1175                                   {
1176                                     inmem_tab_entry->pointer = mem;
1177
1178                                     for (p = sysdep_string->segments;; p++)
1179                                       {
1180                                         nls_uint32 segsize =
1181                                           W (domain->must_swap, p->segsize);
1182                                         nls_uint32 sysdepref =
1183                                           W (domain->must_swap, p->sysdepref);
1184                                         size_t n;
1185
1186                                         if (segsize > 0)
1187                                           {
1188                                             memcpy (mem, static_segments, segsize);
1189                                             mem += segsize;
1190                                             static_segments += segsize;
1191                                           }
1192
1193                                         if (sysdepref == SEGMENTS_END)
1194                                           break;
1195
1196                                         n = strlen (sysdep_segment_values[sysdepref]);
1197                                         memcpy (mem, sysdep_segment_values[sysdepref], n);
1198                                         mem += n;
1199                                       }
1200
1201                                     inmem_tab_entry->length =
1202                                       mem - inmem_tab_entry->pointer;
1203                                   }
1204                               }
1205
1206                             k++;
1207                           }
1208                       }
1209                     if (k != n_inmem_sysdep_strings)
1210                       abort ();
1211
1212                     /* Compute the augmented hash table.  */
1213                     for (i = 0; i < domain->hash_size; i++)
1214                       inmem_hash_tab[i] =
1215                         W (domain->must_swap_hash_tab, domain->hash_tab[i]);
1216                     for (i = 0; i < n_inmem_sysdep_strings; i++)
1217                       {
1218                         const char *msgid = inmem_orig_sysdep_tab[i].pointer;
1219                         nls_uint32 hash_val = __hash_string (msgid);
1220                         nls_uint32 idx = hash_val % domain->hash_size;
1221                         nls_uint32 incr =
1222                           1 + (hash_val % (domain->hash_size - 2));
1223
1224                         for (;;)
1225                           {
1226                             if (inmem_hash_tab[idx] == 0)
1227                               {
1228                                 /* Hash table entry is empty.  Use it.  */
1229                                 inmem_hash_tab[idx] = 1 + domain->nstrings + i;
1230                                 break;
1231                               }
1232
1233                             if (idx >= domain->hash_size - incr)
1234                               idx -= domain->hash_size - incr;
1235                             else
1236                               idx += incr;
1237                           }
1238                       }
1239
1240                     domain->n_sysdep_strings = n_inmem_sysdep_strings;
1241                     domain->orig_sysdep_tab = inmem_orig_sysdep_tab;
1242                     domain->trans_sysdep_tab = inmem_trans_sysdep_tab;
1243
1244                     domain->hash_tab = inmem_hash_tab;
1245                     domain->must_swap_hash_tab = 0;
1246                   }
1247                 else
1248                   {
1249                     domain->n_sysdep_strings = 0;
1250                     domain->orig_sysdep_tab = NULL;
1251                     domain->trans_sysdep_tab = NULL;
1252                   }
1253
1254                 freea (sysdep_segment_values);
1255               }
1256             else
1257               {
1258                 domain->n_sysdep_strings = 0;
1259                 domain->orig_sysdep_tab = NULL;
1260                 domain->trans_sysdep_tab = NULL;
1261               }
1262           }
1263           break;
1264         }
1265       break;
1266     default:
1267       /* This is an invalid revision.  */
1268     invalid:
1269       /* This is an invalid .mo file or we ran out of resources.  */
1270       free (domain->malloced);
1271 #ifdef HAVE_MMAP
1272       if (use_mmap)
1273         munmap ((caddr_t) data, size);
1274       else
1275 #endif
1276         free (data);
1277       free (domain);
1278       domain_file->data = NULL;
1279       goto out;
1280     }
1281
1282   /* No caches of converted translations so far.  */
1283   domain->conversions = NULL;
1284   domain->nconversions = 0;
1285 #ifdef _LIBC
1286   __libc_rwlock_init (domain->conversions_lock);
1287 #else
1288   gl_rwlock_init (domain->conversions_lock);
1289 #endif
1290
1291   /* Get the header entry and look for a plural specification.  */
1292 #ifdef IN_LIBGLOCALE
1293   nullentry =
1294     _nl_find_msg (domain_file, domainbinding, NULL, "", &nullentrylen);
1295 #else
1296   nullentry = _nl_find_msg (domain_file, domainbinding, "", 0, &nullentrylen);
1297 #endif
1298   if (__builtin_expect (nullentry == (char *) -1, 0))
1299     {
1300 #ifdef _LIBC
1301       __libc_rwlock_fini (domain->conversions_lock);
1302 #endif
1303       goto invalid;
1304     }
1305   EXTRACT_PLURAL_EXPRESSION (nullentry, &domain->plural, &domain->nplurals);
1306
1307  out:
1308   if (fd != -1)
1309     close (fd);
1310
1311   domain_file->decided = 1;
1312
1313  done:
1314   __libc_lock_unlock_recursive (lock);
1315 }
1316
1317
1318 #ifdef _LIBC
1319 void
1320 internal_function __libc_freeres_fn_section
1321 _nl_unload_domain (struct loaded_domain *domain)
1322 {
1323   size_t i;
1324
1325   if (domain->plural != &__gettext_germanic_plural)
1326     __gettext_free_exp ((struct expression *) domain->plural);
1327
1328   for (i = 0; i < domain->nconversions; i++)
1329     {
1330       struct converted_domain *convd = &domain->conversions[i];
1331
1332       free ((char *) convd->encoding);
1333       if (convd->conv_tab != NULL && convd->conv_tab != (char **) -1)
1334         free (convd->conv_tab);
1335       if (convd->conv != (__gconv_t) -1)
1336         __gconv_close (convd->conv);
1337     }
1338   free (domain->conversions);
1339   __libc_rwlock_fini (domain->conversions_lock);
1340
1341   free (domain->malloced);
1342
1343 # ifdef _POSIX_MAPPED_FILES
1344   if (domain->use_mmap)
1345     munmap ((caddr_t) domain->data, domain->mmap_size);
1346   else
1347 # endif /* _POSIX_MAPPED_FILES */
1348     free ((void *) domain->data);
1349
1350   free (domain);
1351 }
1352 #endif