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