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