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