1/* loadmsgcat.c - Load needed message catalogs. */
2
3/* Copyright (C) 1995-1999, 2000-2003, 2005-2009 Free Software Foundation, Inc.
4
5   This file is part of GNU Bash.
6
7   Bash is free software: you can redistribute it and/or modify
8   it under the terms of the GNU General Public License as published by
9   the Free Software Foundation, either version 3 of the License, or
10   (at your option) any later version.
11
12   Bash is distributed in the hope that it will be useful,
13   but WITHOUT ANY WARRANTY; without even the implied warranty of
14   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15   GNU General Public License for more details.
16
17   You should have received a copy of the GNU General Public License
18   along with Bash.  If not, see <http://www.gnu.org/licenses/>.
19*/
20
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
27
28#ifdef HAVE_CONFIG_H
29# include <config.h>
30#endif
31
32#include <ctype.h>
33#include <errno.h>
34#include <fcntl.h>
35#include <sys/types.h>
36#include <sys/stat.h>
37
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
54char *alloca ();
55#    endif
56#   endif
57#  endif
58# endif
59#endif
60
61#include <stdlib.h>
62#include <string.h>
63
64#if defined HAVE_UNISTD_H || defined _LIBC
65# include <unistd.h>
66#endif
67
68#ifdef _LIBC
69# include <langinfo.h>
70# include <locale.h>
71#endif
72
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
81
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
88
89#include "gmo.h"
90#include "gettextP.h"
91#include "hash-string.h"
92#include "plural-exp.h"
93
94#ifdef _LIBC
95# include "../locale/localeinfo.h"
96#endif
97
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
455
456/* @@ end of prolog @@ */
457
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
468
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
477
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
494
495
496/* Prototypes for local functions.  Needed to ensure compiler checking of
497   function argument counts despite of K&R C function definition syntax.  */
498static const char *get_sysdep_segment_value PARAMS ((const char *name));
499
500
501/* We need a sign, whether a new catalog was loaded, which can be associated
502   with all translations.  This is important if the translations are
503   cached by one of GCC's features.  */
504int _nl_msg_cat_cntr;
505
506
507/* Expand a system dependent string segment.  Return NULL if unsupported.  */
508static const char *
509get_sysdep_segment_value (name)
510     const char *name;
511{
512  /* Test for an ISO C 99 section 7.8.1 format string directive.
513     Syntax:
514     P R I { d | i | o | u | x | X }
515     { { | LEAST | FAST } { 8 | 16 | 32 | 64 } | MAX | PTR }  */
516  /* We don't use a table of 14 times 6 'const char *' strings here, because
517     data relocations cost startup time.  */
518  if (name[0] == 'P' && name[1] == 'R' && name[2] == 'I')
519    {
520      if (name[3] == 'd' || name[3] == 'i' || name[3] == 'o' || name[3] == 'u'
521	  || name[3] == 'x' || name[3] == 'X')
522	{
523	  if (name[4] == '8' && name[5] == '\0')
524	    {
525	      if (name[3] == 'd')
526		return PRId8;
527	      if (name[3] == 'i')
528		return PRIi8;
529	      if (name[3] == 'o')
530		return PRIo8;
531	      if (name[3] == 'u')
532		return PRIu8;
533	      if (name[3] == 'x')
534		return PRIx8;
535	      if (name[3] == 'X')
536		return PRIX8;
537	      abort ();
538	    }
539	  if (name[4] == '1' && name[5] == '6' && name[6] == '\0')
540	    {
541	      if (name[3] == 'd')
542		return PRId16;
543	      if (name[3] == 'i')
544		return PRIi16;
545	      if (name[3] == 'o')
546		return PRIo16;
547	      if (name[3] == 'u')
548		return PRIu16;
549	      if (name[3] == 'x')
550		return PRIx16;
551	      if (name[3] == 'X')
552		return PRIX16;
553	      abort ();
554	    }
555	  if (name[4] == '3' && name[5] == '2' && name[6] == '\0')
556	    {
557	      if (name[3] == 'd')
558		return PRId32;
559	      if (name[3] == 'i')
560		return PRIi32;
561	      if (name[3] == 'o')
562		return PRIo32;
563	      if (name[3] == 'u')
564		return PRIu32;
565	      if (name[3] == 'x')
566		return PRIx32;
567	      if (name[3] == 'X')
568		return PRIX32;
569	      abort ();
570	    }
571	  if (name[4] == '6' && name[5] == '4' && name[6] == '\0')
572	    {
573	      if (name[3] == 'd')
574		return PRId64;
575	      if (name[3] == 'i')
576		return PRIi64;
577	      if (name[3] == 'o')
578		return PRIo64;
579	      if (name[3] == 'u')
580		return PRIu64;
581	      if (name[3] == 'x')
582		return PRIx64;
583	      if (name[3] == 'X')
584		return PRIX64;
585	      abort ();
586	    }
587	  if (name[4] == 'L' && name[5] == 'E' && name[6] == 'A'
588	      && name[7] == 'S' && name[8] == 'T')
589	    {
590	      if (name[9] == '8' && name[10] == '\0')
591		{
592		  if (name[3] == 'd')
593		    return PRIdLEAST8;
594		  if (name[3] == 'i')
595		    return PRIiLEAST8;
596		  if (name[3] == 'o')
597		    return PRIoLEAST8;
598		  if (name[3] == 'u')
599		    return PRIuLEAST8;
600		  if (name[3] == 'x')
601		    return PRIxLEAST8;
602		  if (name[3] == 'X')
603		    return PRIXLEAST8;
604		  abort ();
605		}
606	      if (name[9] == '1' && name[10] == '6' && name[11] == '\0')
607		{
608		  if (name[3] == 'd')
609		    return PRIdLEAST16;
610		  if (name[3] == 'i')
611		    return PRIiLEAST16;
612		  if (name[3] == 'o')
613		    return PRIoLEAST16;
614		  if (name[3] == 'u')
615		    return PRIuLEAST16;
616		  if (name[3] == 'x')
617		    return PRIxLEAST16;
618		  if (name[3] == 'X')
619		    return PRIXLEAST16;
620		  abort ();
621		}
622	      if (name[9] == '3' && name[10] == '2' && name[11] == '\0')
623		{
624		  if (name[3] == 'd')
625		    return PRIdLEAST32;
626		  if (name[3] == 'i')
627		    return PRIiLEAST32;
628		  if (name[3] == 'o')
629		    return PRIoLEAST32;
630		  if (name[3] == 'u')
631		    return PRIuLEAST32;
632		  if (name[3] == 'x')
633		    return PRIxLEAST32;
634		  if (name[3] == 'X')
635		    return PRIXLEAST32;
636		  abort ();
637		}
638	      if (name[9] == '6' && name[10] == '4' && name[11] == '\0')
639		{
640		  if (name[3] == 'd')
641		    return PRIdLEAST64;
642		  if (name[3] == 'i')
643		    return PRIiLEAST64;
644		  if (name[3] == 'o')
645		    return PRIoLEAST64;
646		  if (name[3] == 'u')
647		    return PRIuLEAST64;
648		  if (name[3] == 'x')
649		    return PRIxLEAST64;
650		  if (name[3] == 'X')
651		    return PRIXLEAST64;
652		  abort ();
653		}
654	    }
655	  if (name[4] == 'F' && name[5] == 'A' && name[6] == 'S'
656	      && name[7] == 'T')
657	    {
658	      if (name[8] == '8' && name[9] == '\0')
659		{
660		  if (name[3] == 'd')
661		    return PRIdFAST8;
662		  if (name[3] == 'i')
663		    return PRIiFAST8;
664		  if (name[3] == 'o')
665		    return PRIoFAST8;
666		  if (name[3] == 'u')
667		    return PRIuFAST8;
668		  if (name[3] == 'x')
669		    return PRIxFAST8;
670		  if (name[3] == 'X')
671		    return PRIXFAST8;
672		  abort ();
673		}
674	      if (name[8] == '1' && name[9] == '6' && name[10] == '\0')
675		{
676		  if (name[3] == 'd')
677		    return PRIdFAST16;
678		  if (name[3] == 'i')
679		    return PRIiFAST16;
680		  if (name[3] == 'o')
681		    return PRIoFAST16;
682		  if (name[3] == 'u')
683		    return PRIuFAST16;
684		  if (name[3] == 'x')
685		    return PRIxFAST16;
686		  if (name[3] == 'X')
687		    return PRIXFAST16;
688		  abort ();
689		}
690	      if (name[8] == '3' && name[9] == '2' && name[10] == '\0')
691		{
692		  if (name[3] == 'd')
693		    return PRIdFAST32;
694		  if (name[3] == 'i')
695		    return PRIiFAST32;
696		  if (name[3] == 'o')
697		    return PRIoFAST32;
698		  if (name[3] == 'u')
699		    return PRIuFAST32;
700		  if (name[3] == 'x')
701		    return PRIxFAST32;
702		  if (name[3] == 'X')
703		    return PRIXFAST32;
704		  abort ();
705		}
706	      if (name[8] == '6' && name[9] == '4' && name[10] == '\0')
707		{
708		  if (name[3] == 'd')
709		    return PRIdFAST64;
710		  if (name[3] == 'i')
711		    return PRIiFAST64;
712		  if (name[3] == 'o')
713		    return PRIoFAST64;
714		  if (name[3] == 'u')
715		    return PRIuFAST64;
716		  if (name[3] == 'x')
717		    return PRIxFAST64;
718		  if (name[3] == 'X')
719		    return PRIXFAST64;
720		  abort ();
721		}
722	    }
723	  if (name[4] == 'M' && name[5] == 'A' && name[6] == 'X'
724	      && name[7] == '\0')
725	    {
726	      if (name[3] == 'd')
727		return PRIdMAX;
728	      if (name[3] == 'i')
729		return PRIiMAX;
730	      if (name[3] == 'o')
731		return PRIoMAX;
732	      if (name[3] == 'u')
733		return PRIuMAX;
734	      if (name[3] == 'x')
735		return PRIxMAX;
736	      if (name[3] == 'X')
737		return PRIXMAX;
738	      abort ();
739	    }
740	  if (name[4] == 'P' && name[5] == 'T' && name[6] == 'R'
741	      && name[7] == '\0')
742	    {
743	      if (name[3] == 'd')
744		return PRIdPTR;
745	      if (name[3] == 'i')
746		return PRIiPTR;
747	      if (name[3] == 'o')
748		return PRIoPTR;
749	      if (name[3] == 'u')
750		return PRIuPTR;
751	      if (name[3] == 'x')
752		return PRIxPTR;
753	      if (name[3] == 'X')
754		return PRIXPTR;
755	      abort ();
756	    }
757	}
758    }
759  /* Other system dependent strings are not valid.  */
760  return NULL;
761}
762
763/* Initialize the codeset dependent parts of an opened message catalog.
764   Return the header entry.  */
765const char *
766internal_function
767_nl_init_domain_conv (domain_file, domain, domainbinding)
768     struct loaded_l10nfile *domain_file;
769     struct loaded_domain *domain;
770     struct binding *domainbinding;
771{
772  /* Find out about the character set the file is encoded with.
773     This can be found (in textual form) in the entry "".  If this
774     entry does not exist or if this does not contain the `charset='
775     information, we will assume the charset matches the one the
776     current locale and we don't have to perform any conversion.  */
777  char *nullentry;
778  size_t nullentrylen;
779
780  /* Preinitialize fields, to avoid recursion during _nl_find_msg.  */
781  domain->codeset_cntr =
782    (domainbinding != NULL ? domainbinding->codeset_cntr : 0);
783#ifdef _LIBC
784  domain->conv = (__gconv_t) -1;
785#else
786# if HAVE_ICONV
787  domain->conv = (iconv_t) -1;
788# endif
789#endif
790  domain->conv_tab = NULL;
791
792  /* Get the header entry.  */
793  nullentry = _nl_find_msg (domain_file, domainbinding, "", &nullentrylen);
794
795  if (nullentry != NULL)
796    {
797#if defined _LIBC || HAVE_ICONV
798      const char *charsetstr;
799
800      charsetstr = strstr (nullentry, "charset=");
801      if (charsetstr != NULL)
802	{
803	  size_t len;
804	  char *charset;
805	  const char *outcharset;
806
807	  charsetstr += strlen ("charset=");
808	  len = strcspn (charsetstr, " \t\n");
809
810	  charset = (char *) alloca (len + 1);
811# if defined _LIBC || HAVE_MEMPCPY
812	  *((char *) mempcpy (charset, charsetstr, len)) = '\0';
813# else
814	  memcpy (charset, charsetstr, len);
815	  charset[len] = '\0';
816# endif
817
818	  /* The output charset should normally be determined by the
819	     locale.  But sometimes the locale is not used or not correctly
820	     set up, so we provide a possibility for the user to override
821	     this.  Moreover, the value specified through
822	     bind_textdomain_codeset overrides both.  */
823	  if (domainbinding != NULL && domainbinding->codeset != NULL)
824	    outcharset = domainbinding->codeset;
825	  else
826	    {
827	      outcharset = getenv ("OUTPUT_CHARSET");
828	      if (outcharset == NULL || outcharset[0] == '\0')
829		{
830# ifdef _LIBC
831		  outcharset = _NL_CURRENT (LC_CTYPE, CODESET);
832# else
833#  if HAVE_ICONV
834		  extern const char *locale_charset PARAMS ((void));
835		  outcharset = locale_charset ();
836#  endif
837# endif
838		}
839	    }
840
841# ifdef _LIBC
842	  /* We always want to use transliteration.  */
843	  outcharset = norm_add_slashes (outcharset, "TRANSLIT");
844	  charset = norm_add_slashes (charset, NULL);
845	  if (__gconv_open (outcharset, charset, &domain->conv,
846			    GCONV_AVOID_NOCONV)
847	      != __GCONV_OK)
848	    domain->conv = (__gconv_t) -1;
849# else
850#  if HAVE_ICONV
851	  /* When using GNU libc >= 2.2 or GNU libiconv >= 1.5,
852	     we want to use transliteration.  */
853#   if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2) || __GLIBC__ > 2 \
854       || _LIBICONV_VERSION >= 0x0105
855	  if (strchr (outcharset, '/') == NULL)
856	    {
857	      char *tmp;
858
859	      len = strlen (outcharset);
860	      tmp = (char *) alloca (len + 10 + 1);
861	      memcpy (tmp, outcharset, len);
862	      memcpy (tmp + len, "//TRANSLIT", 10 + 1);
863	      outcharset = tmp;
864
865	      domain->conv = iconv_open (outcharset, charset);
866
867	      freea (outcharset);
868	    }
869	  else
870#   endif
871	    domain->conv = iconv_open (outcharset, charset);
872#  endif
873# endif
874
875	  freea (charset);
876	}
877#endif /* _LIBC || HAVE_ICONV */
878    }
879
880  return nullentry;
881}
882
883/* Frees the codeset dependent parts of an opened message catalog.  */
884void
885internal_function
886_nl_free_domain_conv (domain)
887     struct loaded_domain *domain;
888{
889  if (domain->conv_tab != NULL && domain->conv_tab != (char **) -1)
890    free (domain->conv_tab);
891
892#ifdef _LIBC
893  if (domain->conv != (__gconv_t) -1)
894    __gconv_close (domain->conv);
895#else
896# if HAVE_ICONV
897  if (domain->conv != (iconv_t) -1)
898    iconv_close (domain->conv);
899# endif
900#endif
901}
902
903/* Load the message catalogs specified by FILENAME.  If it is no valid
904   message catalog do nothing.  */
905void
906internal_function
907_nl_load_domain (domain_file, domainbinding)
908     struct loaded_l10nfile *domain_file;
909     struct binding *domainbinding;
910{
911  int fd;
912  size_t size;
913#ifdef _LIBC
914  struct stat64 st;
915#else
916  struct stat st;
917#endif
918  struct mo_file_header *data = (struct mo_file_header *) -1;
919  int use_mmap = 0;
920  struct loaded_domain *domain;
921  int revision;
922  const char *nullentry;
923
924  domain_file->decided = 1;
925  domain_file->data = NULL;
926
927  /* Note that it would be useless to store domainbinding in domain_file
928     because domainbinding might be == NULL now but != NULL later (after
929     a call to bind_textdomain_codeset).  */
930
931  /* If the record does not represent a valid locale the FILENAME
932     might be NULL.  This can happen when according to the given
933     specification the locale file name is different for XPG and CEN
934     syntax.  */
935  if (domain_file->filename == NULL)
936    return;
937
938  /* Try to open the addressed file.  */
939  fd = open (domain_file->filename, O_RDONLY | O_BINARY);
940  if (fd == -1)
941    return;
942
943  /* We must know about the size of the file.  */
944  if (
945#ifdef _LIBC
946      __builtin_expect (fstat64 (fd, &st) != 0, 0)
947#else
948      __builtin_expect (fstat (fd, &st) != 0, 0)
949#endif
950      || __builtin_expect ((size = (size_t) st.st_size) != st.st_size, 0)
951      || __builtin_expect (size < sizeof (struct mo_file_header), 0))
952    {
953      /* Something went wrong.  */
954      close (fd);
955      return;
956    }
957
958#ifdef HAVE_MMAP
959  /* Now we are ready to load the file.  If mmap() is available we try
960     this first.  If not available or it failed we try to load it.  */
961  data = (struct mo_file_header *) mmap (NULL, size, PROT_READ,
962					 MAP_PRIVATE, fd, 0);
963
964  if (__builtin_expect (data != (struct mo_file_header *) -1, 1))
965    {
966      /* mmap() call was successful.  */
967      close (fd);
968      use_mmap = 1;
969    }
970#endif
971
972  /* If the data is not yet available (i.e. mmap'ed) we try to load
973     it manually.  */
974  if (data == (struct mo_file_header *) -1)
975    {
976      size_t to_read;
977      char *read_ptr;
978
979      data = (struct mo_file_header *) malloc (size);
980      if (data == NULL)
981	return;
982
983      to_read = size;
984      read_ptr = (char *) data;
985      do
986	{
987	  long int nb = (long int) read (fd, read_ptr, to_read);
988	  if (nb <= 0)
989	    {
990#ifdef EINTR
991	      if (nb == -1 && errno == EINTR)
992		continue;
993#endif
994	      close (fd);
995	      return;
996	    }
997	  read_ptr += nb;
998	  to_read -= nb;
999	}
1000      while (to_read > 0);
1001
1002      close (fd);
1003    }
1004
1005  /* Using the magic number we can test whether it really is a message
1006     catalog file.  */
1007  if (__builtin_expect (data->magic != _MAGIC && data->magic != _MAGIC_SWAPPED,
1008			0))
1009    {
1010      /* The magic number is wrong: not a message catalog file.  */
1011#ifdef HAVE_MMAP
1012      if (use_mmap)
1013	munmap ((caddr_t) data, size);
1014      else
1015#endif
1016	free (data);
1017      return;
1018    }
1019
1020  domain = (struct loaded_domain *) malloc (sizeof (struct loaded_domain));
1021  if (domain == NULL)
1022    return;
1023  domain_file->data = domain;
1024
1025  domain->data = (char *) data;
1026  domain->use_mmap = use_mmap;
1027  domain->mmap_size = size;
1028  domain->must_swap = data->magic != _MAGIC;
1029  domain->malloced = NULL;
1030
1031  /* Fill in the information about the available tables.  */
1032  revision = W (domain->must_swap, data->revision);
1033  /* We support only the major revision 0.  */
1034  switch (revision >> 16)
1035    {
1036    case 0:
1037      domain->nstrings = W (domain->must_swap, data->nstrings);
1038      domain->orig_tab = (const struct string_desc *)
1039	((char *) data + W (domain->must_swap, data->orig_tab_offset));
1040      domain->trans_tab = (const struct string_desc *)
1041	((char *) data + W (domain->must_swap, data->trans_tab_offset));
1042      domain->hash_size = W (domain->must_swap, data->hash_tab_size);
1043      domain->hash_tab =
1044	(domain->hash_size > 2
1045	 ? (const nls_uint32 *)
1046	   ((char *) data + W (domain->must_swap, data->hash_tab_offset))
1047	 : NULL);
1048      domain->must_swap_hash_tab = domain->must_swap;
1049
1050      /* Now dispatch on the minor revision.  */
1051      switch (revision & 0xffff)
1052	{
1053	case 0:
1054	  domain->n_sysdep_strings = 0;
1055	  domain->orig_sysdep_tab = NULL;
1056	  domain->trans_sysdep_tab = NULL;
1057	  break;
1058	case 1:
1059	default:
1060	  {
1061	    nls_uint32 n_sysdep_strings;
1062
1063	    if (domain->hash_tab == NULL)
1064	      /* This is invalid.  These minor revisions need a hash table.  */
1065	      goto invalid;
1066
1067	    n_sysdep_strings =
1068	      W (domain->must_swap, data->n_sysdep_strings);
1069	    if (n_sysdep_strings > 0)
1070	      {
1071		nls_uint32 n_sysdep_segments;
1072		const struct sysdep_segment *sysdep_segments;
1073		const char **sysdep_segment_values;
1074		const nls_uint32 *orig_sysdep_tab;
1075		const nls_uint32 *trans_sysdep_tab;
1076		size_t memneed;
1077		char *mem;
1078		struct sysdep_string_desc *inmem_orig_sysdep_tab;
1079		struct sysdep_string_desc *inmem_trans_sysdep_tab;
1080		nls_uint32 *inmem_hash_tab;
1081		unsigned int i;
1082
1083		/* Get the values of the system dependent segments.  */
1084		n_sysdep_segments =
1085		  W (domain->must_swap, data->n_sysdep_segments);
1086		sysdep_segments = (const struct sysdep_segment *)
1087		  ((char *) data
1088		   + W (domain->must_swap, data->sysdep_segments_offset));
1089		sysdep_segment_values =
1090		  alloca (n_sysdep_segments * sizeof (const char *));
1091		for (i = 0; i < n_sysdep_segments; i++)
1092		  {
1093		    const char *name =
1094		      (char *) data
1095		      + W (domain->must_swap, sysdep_segments[i].offset);
1096		    nls_uint32 namelen =
1097		      W (domain->must_swap, sysdep_segments[i].length);
1098
1099		    if (!(namelen > 0 && name[namelen - 1] == '\0'))
1100		      {
1101			freea (sysdep_segment_values);
1102			goto invalid;
1103		      }
1104
1105		    sysdep_segment_values[i] = get_sysdep_segment_value (name);
1106		  }
1107
1108		orig_sysdep_tab = (const nls_uint32 *)
1109		  ((char *) data
1110		   + W (domain->must_swap, data->orig_sysdep_tab_offset));
1111		trans_sysdep_tab = (const nls_uint32 *)
1112		  ((char *) data
1113		   + W (domain->must_swap, data->trans_sysdep_tab_offset));
1114
1115		/* Compute the amount of additional memory needed for the
1116		   system dependent strings and the augmented hash table.  */
1117		memneed = 2 * n_sysdep_strings
1118			  * sizeof (struct sysdep_string_desc)
1119			  + domain->hash_size * sizeof (nls_uint32);
1120		for (i = 0; i < 2 * n_sysdep_strings; i++)
1121		  {
1122		    const struct sysdep_string *sysdep_string =
1123		      (const struct sysdep_string *)
1124		      ((char *) data
1125		       + W (domain->must_swap,
1126			    i < n_sysdep_strings
1127			    ? orig_sysdep_tab[i]
1128			    : trans_sysdep_tab[i - n_sysdep_strings]));
1129		    size_t need = 0;
1130		    const struct segment_pair *p = sysdep_string->segments;
1131
1132		    if (W (domain->must_swap, p->sysdepref) != SEGMENTS_END)
1133		      for (p = sysdep_string->segments;; p++)
1134			{
1135			  nls_uint32 sysdepref;
1136
1137			  need += W (domain->must_swap, p->segsize);
1138
1139			  sysdepref = W (domain->must_swap, p->sysdepref);
1140			  if (sysdepref == SEGMENTS_END)
1141			    break;
1142
1143			  if (sysdepref >= n_sysdep_segments)
1144			    {
1145			      /* Invalid.  */
1146			      freea (sysdep_segment_values);
1147			      goto invalid;
1148			    }
1149
1150			  need += strlen (sysdep_segment_values[sysdepref]);
1151			}
1152
1153		    memneed += need;
1154		  }
1155
1156		/* Allocate additional memory.  */
1157		mem = (char *) malloc (memneed);
1158		if (mem == NULL)
1159		  goto invalid;
1160
1161		domain->malloced = mem;
1162		inmem_orig_sysdep_tab = (struct sysdep_string_desc *) mem;
1163		mem += n_sysdep_strings * sizeof (struct sysdep_string_desc);
1164		inmem_trans_sysdep_tab = (struct sysdep_string_desc *) mem;
1165		mem += n_sysdep_strings * sizeof (struct sysdep_string_desc);
1166		inmem_hash_tab = (nls_uint32 *) mem;
1167		mem += domain->hash_size * sizeof (nls_uint32);
1168
1169		/* Compute the system dependent strings.  */
1170		for (i = 0; i < 2 * n_sysdep_strings; i++)
1171		  {
1172		    const struct sysdep_string *sysdep_string =
1173		      (const struct sysdep_string *)
1174		      ((char *) data
1175		       + W (domain->must_swap,
1176			    i < n_sysdep_strings
1177			    ? orig_sysdep_tab[i]
1178			    : trans_sysdep_tab[i - n_sysdep_strings]));
1179		    const char *static_segments =
1180		      (char *) data
1181		      + W (domain->must_swap, sysdep_string->offset);
1182		    const struct segment_pair *p = sysdep_string->segments;
1183
1184		    /* Concatenate the segments, and fill
1185		       inmem_orig_sysdep_tab[i] (for i < n_sysdep_strings) and
1186		       inmem_trans_sysdep_tab[i-n_sysdep_strings] (for
1187		       i >= n_sysdep_strings).  */
1188
1189		    if (W (domain->must_swap, p->sysdepref) == SEGMENTS_END)
1190		      {
1191			/* Only one static segment.  */
1192			inmem_orig_sysdep_tab[i].length =
1193			  W (domain->must_swap, p->segsize);
1194			inmem_orig_sysdep_tab[i].pointer = static_segments;
1195		      }
1196		    else
1197		      {
1198			inmem_orig_sysdep_tab[i].pointer = mem;
1199
1200			for (p = sysdep_string->segments;; p++)
1201			  {
1202			    nls_uint32 segsize =
1203			      W (domain->must_swap, p->segsize);
1204			    nls_uint32 sysdepref =
1205			      W (domain->must_swap, p->sysdepref);
1206			    size_t n;
1207
1208			    if (segsize > 0)
1209			      {
1210				memcpy (mem, static_segments, segsize);
1211				mem += segsize;
1212				static_segments += segsize;
1213			      }
1214
1215			    if (sysdepref == SEGMENTS_END)
1216			      break;
1217
1218			    n = strlen (sysdep_segment_values[sysdepref]);
1219			    memcpy (mem, sysdep_segment_values[sysdepref], n);
1220			    mem += n;
1221			  }
1222
1223			inmem_orig_sysdep_tab[i].length =
1224			  mem - inmem_orig_sysdep_tab[i].pointer;
1225		      }
1226		  }
1227
1228		/* Compute the augmented hash table.  */
1229		for (i = 0; i < domain->hash_size; i++)
1230		  inmem_hash_tab[i] =
1231		    W (domain->must_swap_hash_tab, domain->hash_tab[i]);
1232		for (i = 0; i < n_sysdep_strings; i++)
1233		  {
1234		    const char *msgid = inmem_orig_sysdep_tab[i].pointer;
1235		    nls_uint32 hash_val = hash_string (msgid);
1236		    nls_uint32 idx = hash_val % domain->hash_size;
1237		    nls_uint32 incr = 1 + (hash_val % (domain->hash_size - 2));
1238
1239		    for (;;)
1240		      {
1241			if (inmem_hash_tab[idx] == 0)
1242			  {
1243			    /* Hash table entry is empty.  Use it.  */
1244			    inmem_hash_tab[idx] = 1 + domain->nstrings + i;
1245			    break;
1246			  }
1247
1248			if (idx >= domain->hash_size - incr)
1249			  idx -= domain->hash_size - incr;
1250			else
1251			  idx += incr;
1252		      }
1253		  }
1254
1255		freea (sysdep_segment_values);
1256
1257		domain->n_sysdep_strings = n_sysdep_strings;
1258		domain->orig_sysdep_tab = inmem_orig_sysdep_tab;
1259		domain->trans_sysdep_tab = inmem_trans_sysdep_tab;
1260
1261		domain->hash_tab = inmem_hash_tab;
1262		domain->must_swap_hash_tab = 0;
1263	      }
1264	    else
1265	      {
1266		domain->n_sysdep_strings = 0;
1267		domain->orig_sysdep_tab = NULL;
1268		domain->trans_sysdep_tab = NULL;
1269	      }
1270	  }
1271	  break;
1272	}
1273      break;
1274    default:
1275      /* This is an invalid revision.  */
1276    invalid:
1277      /* This is an invalid .mo file.  */
1278      if (domain->malloced)
1279	free (domain->malloced);
1280#ifdef HAVE_MMAP
1281      if (use_mmap)
1282	munmap ((caddr_t) data, size);
1283      else
1284#endif
1285	free (data);
1286      free (domain);
1287      domain_file->data = NULL;
1288      return;
1289    }
1290
1291  /* Now initialize the character set converter from the character set
1292     the file is encoded with (found in the header entry) to the domain's
1293     specified character set or the locale's character set.  */
1294  nullentry = _nl_init_domain_conv (domain_file, domain, domainbinding);
1295
1296  /* Also look for a plural specification.  */
1297  EXTRACT_PLURAL_EXPRESSION (nullentry, &domain->plural, &domain->nplurals);
1298}
1299
1300
1301#ifdef _LIBC
1302void
1303internal_function
1304_nl_unload_domain (domain)
1305     struct loaded_domain *domain;
1306{
1307  if (domain->plural != &__gettext_germanic_plural)
1308    __gettext_free_exp (domain->plural);
1309
1310  _nl_free_domain_conv (domain);
1311
1312  if (domain->malloced)
1313    free (domain->malloced);
1314
1315# ifdef _POSIX_MAPPED_FILES
1316  if (domain->use_mmap)
1317    munmap ((caddr_t) domain->data, domain->mmap_size);
1318  else
1319# endif	/* _POSIX_MAPPED_FILES */
1320    free ((void *) domain->data);
1321
1322  free (domain);
1323}
1324#endif
1325