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