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