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