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