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