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