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