1 /* Load needed message catalogs.
2 Copyright (C) 1995-2005, 2007 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
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.
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.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, see
17 <http://www.gnu.org/licenses/>. */
19 /* Tell glibc's <string.h> to provide a prototype for mempcpy().
20 This must come before <config.h> because <config.h> may include
21 <features.h>, and once <features.h> has been included, it's too late. */
23 # define _GNU_SOURCE 1
33 #include <sys/types.h>
38 # define alloca __builtin_alloca
39 # define HAVE_ALLOCA 1
41 # if defined HAVE_ALLOCA_H || defined _LIBC
57 #if defined HAVE_UNISTD_H || defined _LIBC
62 # include <langinfo.h>
66 #if (defined HAVE_MMAP && defined HAVE_MUNMAP && !defined DISALLOW_MMAP) \
67 || (defined _LIBC && defined _POSIX_MAPPED_FILES)
68 # include <sys/mman.h>
75 #if defined HAVE_STDINT_H_WITH_UINTMAX || defined _LIBC
78 #if defined HAVE_INTTYPES_H || defined _LIBC
79 # include <inttypes.h>
84 #include "hash-string.h"
85 #include "plural-exp.h"
88 # include "../locale/localeinfo.h"
89 # include <not-cancel.h>
90 # include <bits/libc-lock.h>
93 /* Provide fallback values for macros that ought to be defined in <inttypes.h>.
94 Note that our fallback values need not be literal strings, because we don't
95 use them with preprocessor string concatenation. */
96 #if !defined PRId8 || PRI_MACROS_BROKEN
100 #if !defined PRIi8 || PRI_MACROS_BROKEN
104 #if !defined PRIo8 || PRI_MACROS_BROKEN
108 #if !defined PRIu8 || PRI_MACROS_BROKEN
112 #if !defined PRIx8 || PRI_MACROS_BROKEN
116 #if !defined PRIX8 || PRI_MACROS_BROKEN
120 #if !defined PRId16 || PRI_MACROS_BROKEN
124 #if !defined PRIi16 || PRI_MACROS_BROKEN
128 #if !defined PRIo16 || PRI_MACROS_BROKEN
132 #if !defined PRIu16 || PRI_MACROS_BROKEN
136 #if !defined PRIx16 || PRI_MACROS_BROKEN
140 #if !defined PRIX16 || PRI_MACROS_BROKEN
144 #if !defined PRId32 || PRI_MACROS_BROKEN
148 #if !defined PRIi32 || PRI_MACROS_BROKEN
152 #if !defined PRIo32 || PRI_MACROS_BROKEN
156 #if !defined PRIu32 || PRI_MACROS_BROKEN
160 #if !defined PRIx32 || PRI_MACROS_BROKEN
164 #if !defined PRIX32 || PRI_MACROS_BROKEN
168 #if !defined PRId64 || PRI_MACROS_BROKEN
170 # define PRId64 (sizeof (long) == 8 ? "ld" : "lld")
172 #if !defined PRIi64 || PRI_MACROS_BROKEN
174 # define PRIi64 (sizeof (long) == 8 ? "li" : "lli")
176 #if !defined PRIo64 || PRI_MACROS_BROKEN
178 # define PRIo64 (sizeof (long) == 8 ? "lo" : "llo")
180 #if !defined PRIu64 || PRI_MACROS_BROKEN
182 # define PRIu64 (sizeof (long) == 8 ? "lu" : "llu")
184 #if !defined PRIx64 || PRI_MACROS_BROKEN
186 # define PRIx64 (sizeof (long) == 8 ? "lx" : "llx")
188 #if !defined PRIX64 || PRI_MACROS_BROKEN
190 # define PRIX64 (sizeof (long) == 8 ? "lX" : "llX")
192 #if !defined PRIdLEAST8 || PRI_MACROS_BROKEN
194 # define PRIdLEAST8 "d"
196 #if !defined PRIiLEAST8 || PRI_MACROS_BROKEN
198 # define PRIiLEAST8 "i"
200 #if !defined PRIoLEAST8 || PRI_MACROS_BROKEN
202 # define PRIoLEAST8 "o"
204 #if !defined PRIuLEAST8 || PRI_MACROS_BROKEN
206 # define PRIuLEAST8 "u"
208 #if !defined PRIxLEAST8 || PRI_MACROS_BROKEN
210 # define PRIxLEAST8 "x"
212 #if !defined PRIXLEAST8 || PRI_MACROS_BROKEN
214 # define PRIXLEAST8 "X"
216 #if !defined PRIdLEAST16 || PRI_MACROS_BROKEN
218 # define PRIdLEAST16 "d"
220 #if !defined PRIiLEAST16 || PRI_MACROS_BROKEN
222 # define PRIiLEAST16 "i"
224 #if !defined PRIoLEAST16 || PRI_MACROS_BROKEN
226 # define PRIoLEAST16 "o"
228 #if !defined PRIuLEAST16 || PRI_MACROS_BROKEN
230 # define PRIuLEAST16 "u"
232 #if !defined PRIxLEAST16 || PRI_MACROS_BROKEN
234 # define PRIxLEAST16 "x"
236 #if !defined PRIXLEAST16 || PRI_MACROS_BROKEN
238 # define PRIXLEAST16 "X"
240 #if !defined PRIdLEAST32 || PRI_MACROS_BROKEN
242 # define PRIdLEAST32 "d"
244 #if !defined PRIiLEAST32 || PRI_MACROS_BROKEN
246 # define PRIiLEAST32 "i"
248 #if !defined PRIoLEAST32 || PRI_MACROS_BROKEN
250 # define PRIoLEAST32 "o"
252 #if !defined PRIuLEAST32 || PRI_MACROS_BROKEN
254 # define PRIuLEAST32 "u"
256 #if !defined PRIxLEAST32 || PRI_MACROS_BROKEN
258 # define PRIxLEAST32 "x"
260 #if !defined PRIXLEAST32 || PRI_MACROS_BROKEN
262 # define PRIXLEAST32 "X"
264 #if !defined PRIdLEAST64 || PRI_MACROS_BROKEN
266 # define PRIdLEAST64 PRId64
268 #if !defined PRIiLEAST64 || PRI_MACROS_BROKEN
270 # define PRIiLEAST64 PRIi64
272 #if !defined PRIoLEAST64 || PRI_MACROS_BROKEN
274 # define PRIoLEAST64 PRIo64
276 #if !defined PRIuLEAST64 || PRI_MACROS_BROKEN
278 # define PRIuLEAST64 PRIu64
280 #if !defined PRIxLEAST64 || PRI_MACROS_BROKEN
282 # define PRIxLEAST64 PRIx64
284 #if !defined PRIXLEAST64 || PRI_MACROS_BROKEN
286 # define PRIXLEAST64 PRIX64
288 #if !defined PRIdFAST8 || PRI_MACROS_BROKEN
290 # define PRIdFAST8 "d"
292 #if !defined PRIiFAST8 || PRI_MACROS_BROKEN
294 # define PRIiFAST8 "i"
296 #if !defined PRIoFAST8 || PRI_MACROS_BROKEN
298 # define PRIoFAST8 "o"
300 #if !defined PRIuFAST8 || PRI_MACROS_BROKEN
302 # define PRIuFAST8 "u"
304 #if !defined PRIxFAST8 || PRI_MACROS_BROKEN
306 # define PRIxFAST8 "x"
308 #if !defined PRIXFAST8 || PRI_MACROS_BROKEN
310 # define PRIXFAST8 "X"
312 #if !defined PRIdFAST16 || PRI_MACROS_BROKEN
314 # define PRIdFAST16 "d"
316 #if !defined PRIiFAST16 || PRI_MACROS_BROKEN
318 # define PRIiFAST16 "i"
320 #if !defined PRIoFAST16 || PRI_MACROS_BROKEN
322 # define PRIoFAST16 "o"
324 #if !defined PRIuFAST16 || PRI_MACROS_BROKEN
326 # define PRIuFAST16 "u"
328 #if !defined PRIxFAST16 || PRI_MACROS_BROKEN
330 # define PRIxFAST16 "x"
332 #if !defined PRIXFAST16 || PRI_MACROS_BROKEN
334 # define PRIXFAST16 "X"
336 #if !defined PRIdFAST32 || PRI_MACROS_BROKEN
338 # define PRIdFAST32 "d"
340 #if !defined PRIiFAST32 || PRI_MACROS_BROKEN
342 # define PRIiFAST32 "i"
344 #if !defined PRIoFAST32 || PRI_MACROS_BROKEN
346 # define PRIoFAST32 "o"
348 #if !defined PRIuFAST32 || PRI_MACROS_BROKEN
350 # define PRIuFAST32 "u"
352 #if !defined PRIxFAST32 || PRI_MACROS_BROKEN
354 # define PRIxFAST32 "x"
356 #if !defined PRIXFAST32 || PRI_MACROS_BROKEN
358 # define PRIXFAST32 "X"
360 #if !defined PRIdFAST64 || PRI_MACROS_BROKEN
362 # define PRIdFAST64 PRId64
364 #if !defined PRIiFAST64 || PRI_MACROS_BROKEN
366 # define PRIiFAST64 PRIi64
368 #if !defined PRIoFAST64 || PRI_MACROS_BROKEN
370 # define PRIoFAST64 PRIo64
372 #if !defined PRIuFAST64 || PRI_MACROS_BROKEN
374 # define PRIuFAST64 PRIu64
376 #if !defined PRIxFAST64 || PRI_MACROS_BROKEN
378 # define PRIxFAST64 PRIx64
380 #if !defined PRIXFAST64 || PRI_MACROS_BROKEN
382 # define PRIXFAST64 PRIX64
384 #if !defined PRIdMAX || PRI_MACROS_BROKEN
386 # define PRIdMAX (sizeof (uintmax_t) == sizeof (long) ? "ld" : "lld")
388 #if !defined PRIiMAX || PRI_MACROS_BROKEN
390 # define PRIiMAX (sizeof (uintmax_t) == sizeof (long) ? "li" : "lli")
392 #if !defined PRIoMAX || PRI_MACROS_BROKEN
394 # define PRIoMAX (sizeof (uintmax_t) == sizeof (long) ? "lo" : "llo")
396 #if !defined PRIuMAX || PRI_MACROS_BROKEN
398 # define PRIuMAX (sizeof (uintmax_t) == sizeof (long) ? "lu" : "llu")
400 #if !defined PRIxMAX || PRI_MACROS_BROKEN
402 # define PRIxMAX (sizeof (uintmax_t) == sizeof (long) ? "lx" : "llx")
404 #if !defined PRIXMAX || PRI_MACROS_BROKEN
406 # define PRIXMAX (sizeof (uintmax_t) == sizeof (long) ? "lX" : "llX")
408 #if !defined PRIdPTR || PRI_MACROS_BROKEN
411 (sizeof (void *) == sizeof (long) ? "ld" : \
412 sizeof (void *) == sizeof (int) ? "d" : \
415 #if !defined PRIiPTR || PRI_MACROS_BROKEN
418 (sizeof (void *) == sizeof (long) ? "li" : \
419 sizeof (void *) == sizeof (int) ? "i" : \
422 #if !defined PRIoPTR || PRI_MACROS_BROKEN
425 (sizeof (void *) == sizeof (long) ? "lo" : \
426 sizeof (void *) == sizeof (int) ? "o" : \
429 #if !defined PRIuPTR || PRI_MACROS_BROKEN
432 (sizeof (void *) == sizeof (long) ? "lu" : \
433 sizeof (void *) == sizeof (int) ? "u" : \
436 #if !defined PRIxPTR || PRI_MACROS_BROKEN
439 (sizeof (void *) == sizeof (long) ? "lx" : \
440 sizeof (void *) == sizeof (int) ? "x" : \
443 #if !defined PRIXPTR || PRI_MACROS_BROKEN
446 (sizeof (void *) == sizeof (long) ? "lX" : \
447 sizeof (void *) == sizeof (int) ? "X" : \
451 /* @@ end of prolog @@ */
454 /* Rename the non ISO C functions. This is required by the standard
455 because some ISO C functions will require linking with this object
456 file and the name space must not be polluted. */
457 # define open(name, flags) open_not_cancel_2 (name, flags)
458 # define close(fd) close_not_cancel_no_status (fd)
459 # define read(fd, buf, n) read_not_cancel (fd, buf, n)
460 # define mmap(addr, len, prot, flags, fd, offset) \
461 __mmap (addr, len, prot, flags, fd, offset)
462 # define munmap(addr, len) __munmap (addr, len)
465 /* For those losing systems which don't have `alloca' we have to add
466 some additional code emulating it. */
468 # define freea(p) /* nothing */
470 # define alloca(n) malloc (n)
471 # define freea(p) free (p)
475 /* Prototypes for local functions. Needed to ensure compiler checking of
476 function argument counts despite of K&R C function definition syntax. */
477 static const char *get_sysdep_segment_value
PARAMS ((const char *name
));
480 /* We need a sign, whether a new catalog was loaded, which can be associated
481 with all translations. This is important if the translations are
482 cached by one of GCC's features. */
483 int _nl_msg_cat_cntr
;
486 /* Expand a system dependent string segment. Return NULL if unsupported. */
488 get_sysdep_segment_value (name
)
491 /* Test for an ISO C 99 section 7.8.1 format string directive.
493 P R I { d | i | o | u | x | X }
494 { { | LEAST | FAST } { 8 | 16 | 32 | 64 } | MAX | PTR } */
495 /* We don't use a table of 14 times 6 'const char *' strings here, because
496 data relocations cost startup time. */
497 if (name
[0] == 'P' && name
[1] == 'R' && name
[2] == 'I')
499 if (name
[3] == 'd' || name
[3] == 'i' || name
[3] == 'o' || name
[3] == 'u'
500 || name
[3] == 'x' || name
[3] == 'X')
502 if (name
[4] == '8' && name
[5] == '\0')
518 if (name
[4] == '1' && name
[5] == '6' && name
[6] == '\0')
534 if (name
[4] == '3' && name
[5] == '2' && name
[6] == '\0')
550 if (name
[4] == '6' && name
[5] == '4' && name
[6] == '\0')
566 if (name
[4] == 'L' && name
[5] == 'E' && name
[6] == 'A'
567 && name
[7] == 'S' && name
[8] == 'T')
569 if (name
[9] == '8' && name
[10] == '\0')
585 if (name
[9] == '1' && name
[10] == '6' && name
[11] == '\0')
601 if (name
[9] == '3' && name
[10] == '2' && name
[11] == '\0')
617 if (name
[9] == '6' && name
[10] == '4' && name
[11] == '\0')
634 if (name
[4] == 'F' && name
[5] == 'A' && name
[6] == 'S'
637 if (name
[8] == '8' && name
[9] == '\0')
653 if (name
[8] == '1' && name
[9] == '6' && name
[10] == '\0')
669 if (name
[8] == '3' && name
[9] == '2' && name
[10] == '\0')
685 if (name
[8] == '6' && name
[9] == '4' && name
[10] == '\0')
702 if (name
[4] == 'M' && name
[5] == 'A' && name
[6] == 'X'
719 if (name
[4] == 'P' && name
[5] == 'T' && name
[6] == 'R'
738 /* Test for a glibc specific printf() format directive flag. */
739 if (name
[0] == 'I' && name
[1] == '\0')
741 #if defined _LIBC || __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2)
742 /* The 'I' flag, in numeric format directives, replaces ASCII digits
743 with the 'outdigits' defined in the LC_CTYPE locale facet. This is
744 used for Farsi (Persian) and maybe Arabic. */
750 /* Other system dependent strings are not valid. */
754 /* Load the message catalogs specified by FILENAME. If it is no valid
755 message catalog do nothing. */
758 _nl_load_domain (domain_file
, domainbinding
)
759 struct loaded_l10nfile
*domain_file
;
760 struct binding
*domainbinding
;
762 __libc_lock_define_initialized_recursive (static, lock
);
770 struct mo_file_header
*data
= (struct mo_file_header
*) -1;
772 struct loaded_domain
*domain
;
774 const char *nullentry
;
777 __libc_lock_lock_recursive (lock
);
778 if (domain_file
->decided
!= 0)
780 /* There are two possibilities:
782 + is is the same thread calling again during this
783 initialization via _nl_find_msg. We have initialized
784 everything this call needs.
786 + this is another thread which tried to initialize this object.
787 Not necessary anymore since if the lock is available this
790 __libc_lock_unlock_recursive (lock
);
794 domain_file
->decided
= -1;
795 domain_file
->data
= NULL
;
797 /* Note that it would be useless to store domainbinding in domain_file
798 because domainbinding might be == NULL now but != NULL later (after
799 a call to bind_textdomain_codeset). */
801 /* If the record does not represent a valid locale the FILENAME
802 might be NULL. This can happen when according to the given
803 specification the locale file name is different for XPG and CEN
805 if (domain_file
->filename
== NULL
)
808 /* Try to open the addressed file. */
809 fd
= open (domain_file
->filename
, O_RDONLY
);
813 /* We must know about the size of the file. */
816 __builtin_expect (fstat64 (fd
, &st
) != 0, 0)
818 __builtin_expect (fstat (fd
, &st
) != 0, 0)
820 || __builtin_expect ((size
= (size_t) st
.st_size
) != st
.st_size
, 0)
821 || __builtin_expect (size
< sizeof (struct mo_file_header
), 0))
822 /* Something went wrong. */
826 /* Now we are ready to load the file. If mmap() is available we try
827 this first. If not available or it failed we try to load it. */
828 data
= (struct mo_file_header
*) mmap (NULL
, size
, PROT_READ
,
831 if (__builtin_expect (data
!= MAP_FAILED
, 1))
833 /* mmap() call was successful. */
840 /* If the data is not yet available (i.e. mmap'ed) we try to load
842 if (data
== MAP_FAILED
)
847 data
= (struct mo_file_header
*) malloc (size
);
852 read_ptr
= (char *) data
;
855 long int nb
= (long int) TEMP_FAILURE_RETRY (read (fd
, read_ptr
,
869 /* Using the magic number we can test whether it really is a message
871 if (__builtin_expect (data
->magic
!= _MAGIC
&& data
->magic
!= _MAGIC_SWAPPED
,
874 /* The magic number is wrong: not a message catalog file. */
877 munmap ((caddr_t
) data
, size
);
884 domain
= (struct loaded_domain
*) malloc (sizeof (struct loaded_domain
));
887 domain_file
->data
= domain
;
889 domain
->data
= (char *) data
;
890 domain
->use_mmap
= use_mmap
;
891 domain
->mmap_size
= size
;
892 domain
->must_swap
= data
->magic
!= _MAGIC
;
893 domain
->malloced
= NULL
;
895 /* Fill in the information about the available tables. */
896 revision
= W (domain
->must_swap
, data
->revision
);
897 /* We support only the major revisions 0 and 1. */
898 switch (revision
>> 16)
902 domain
->nstrings
= W (domain
->must_swap
, data
->nstrings
);
903 domain
->orig_tab
= (const struct string_desc
*)
904 ((char *) data
+ W (domain
->must_swap
, data
->orig_tab_offset
));
905 domain
->trans_tab
= (const struct string_desc
*)
906 ((char *) data
+ W (domain
->must_swap
, data
->trans_tab_offset
));
907 domain
->hash_size
= W (domain
->must_swap
, data
->hash_tab_size
);
909 (domain
->hash_size
> 2
910 ? (const nls_uint32
*)
911 ((char *) data
+ W (domain
->must_swap
, data
->hash_tab_offset
))
913 domain
->must_swap_hash_tab
= domain
->must_swap
;
915 /* Now dispatch on the minor revision. */
916 switch (revision
& 0xffff)
919 domain
->n_sysdep_strings
= 0;
920 domain
->orig_sysdep_tab
= NULL
;
921 domain
->trans_sysdep_tab
= NULL
;
926 nls_uint32 n_sysdep_strings
;
928 if (domain
->hash_tab
== NULL
)
929 /* This is invalid. These minor revisions need a hash table. */
933 W (domain
->must_swap
, data
->n_sysdep_strings
);
934 if (n_sysdep_strings
> 0)
936 nls_uint32 n_sysdep_segments
;
937 const struct sysdep_segment
*sysdep_segments
;
938 const char **sysdep_segment_values
;
939 const nls_uint32
*orig_sysdep_tab
;
940 const nls_uint32
*trans_sysdep_tab
;
941 nls_uint32 n_inmem_sysdep_strings
;
944 struct sysdep_string_desc
*inmem_orig_sysdep_tab
;
945 struct sysdep_string_desc
*inmem_trans_sysdep_tab
;
946 nls_uint32
*inmem_hash_tab
;
949 /* Get the values of the system dependent segments. */
951 W (domain
->must_swap
, data
->n_sysdep_segments
);
952 sysdep_segments
= (const struct sysdep_segment
*)
954 + W (domain
->must_swap
, data
->sysdep_segments_offset
));
955 sysdep_segment_values
=
956 alloca (n_sysdep_segments
* sizeof (const char *));
957 for (i
= 0; i
< n_sysdep_segments
; i
++)
961 + W (domain
->must_swap
, sysdep_segments
[i
].offset
);
963 W (domain
->must_swap
, sysdep_segments
[i
].length
);
965 if (!(namelen
> 0 && name
[namelen
- 1] == '\0'))
967 freea (sysdep_segment_values
);
971 sysdep_segment_values
[i
] = get_sysdep_segment_value (name
);
974 orig_sysdep_tab
= (const nls_uint32
*)
976 + W (domain
->must_swap
, data
->orig_sysdep_tab_offset
));
977 trans_sysdep_tab
= (const nls_uint32
*)
979 + W (domain
->must_swap
, data
->trans_sysdep_tab_offset
));
981 /* Compute the amount of additional memory needed for the
982 system dependent strings and the augmented hash table.
983 At the same time, also drop string pairs which refer to
984 an undefined system dependent segment. */
985 n_inmem_sysdep_strings
= 0;
986 memneed
= domain
->hash_size
* sizeof (nls_uint32
);
987 for (i
= 0; i
< n_sysdep_strings
; i
++)
992 for (j
= 0; j
< 2; j
++)
994 const struct sysdep_string
*sysdep_string
=
995 (const struct sysdep_string
*)
997 + W (domain
->must_swap
,
1000 : trans_sysdep_tab
[i
]));
1002 const struct segment_pair
*p
= sysdep_string
->segments
;
1004 if (W (domain
->must_swap
, p
->sysdepref
) != SEGMENTS_END
)
1005 for (p
= sysdep_string
->segments
;; p
++)
1007 nls_uint32 sysdepref
;
1009 need
+= W (domain
->must_swap
, p
->segsize
);
1011 sysdepref
= W (domain
->must_swap
, p
->sysdepref
);
1012 if (sysdepref
== SEGMENTS_END
)
1015 if (sysdepref
>= n_sysdep_segments
)
1018 freea (sysdep_segment_values
);
1022 if (sysdep_segment_values
[sysdepref
] == NULL
)
1024 /* This particular string pair is invalid. */
1029 need
+= strlen (sysdep_segment_values
[sysdepref
]);
1039 n_inmem_sysdep_strings
++;
1040 memneed
+= needs
[0] + needs
[1];
1043 memneed
+= 2 * n_inmem_sysdep_strings
1044 * sizeof (struct sysdep_string_desc
);
1046 if (n_inmem_sysdep_strings
> 0)
1050 /* Allocate additional memory. */
1051 mem
= (char *) malloc (memneed
);
1055 domain
->malloced
= mem
;
1056 inmem_orig_sysdep_tab
= (struct sysdep_string_desc
*) mem
;
1057 mem
+= n_inmem_sysdep_strings
1058 * sizeof (struct sysdep_string_desc
);
1059 inmem_trans_sysdep_tab
= (struct sysdep_string_desc
*) mem
;
1060 mem
+= n_inmem_sysdep_strings
1061 * sizeof (struct sysdep_string_desc
);
1062 inmem_hash_tab
= (nls_uint32
*) mem
;
1063 mem
+= domain
->hash_size
* sizeof (nls_uint32
);
1065 /* Compute the system dependent strings. */
1067 for (i
= 0; i
< n_sysdep_strings
; i
++)
1071 for (j
= 0; j
< 2; j
++)
1073 const struct sysdep_string
*sysdep_string
=
1074 (const struct sysdep_string
*)
1076 + W (domain
->must_swap
,
1078 ? orig_sysdep_tab
[i
]
1079 : trans_sysdep_tab
[i
]));
1080 const struct segment_pair
*p
=
1081 sysdep_string
->segments
;
1083 if (W (domain
->must_swap
, p
->sysdepref
)
1085 for (p
= sysdep_string
->segments
;; p
++)
1087 nls_uint32 sysdepref
;
1090 W (domain
->must_swap
, p
->sysdepref
);
1091 if (sysdepref
== SEGMENTS_END
)
1094 if (sysdep_segment_values
[sysdepref
] == NULL
)
1096 /* This particular string pair is
1109 for (j
= 0; j
< 2; j
++)
1111 const struct sysdep_string
*sysdep_string
=
1112 (const struct sysdep_string
*)
1114 + W (domain
->must_swap
,
1116 ? orig_sysdep_tab
[i
]
1117 : trans_sysdep_tab
[i
]));
1118 const char *static_segments
=
1120 + W (domain
->must_swap
, sysdep_string
->offset
);
1121 const struct segment_pair
*p
=
1122 sysdep_string
->segments
;
1124 /* Concatenate the segments, and fill
1125 inmem_orig_sysdep_tab[k] (for j == 0) and
1126 inmem_trans_sysdep_tab[k] (for j == 1). */
1128 struct sysdep_string_desc
*inmem_tab_entry
=
1130 ? inmem_orig_sysdep_tab
1131 : inmem_trans_sysdep_tab
)
1134 if (W (domain
->must_swap
, p
->sysdepref
)
1137 /* Only one static segment. */
1138 inmem_tab_entry
->length
=
1139 W (domain
->must_swap
, p
->segsize
);
1140 inmem_tab_entry
->pointer
= static_segments
;
1144 inmem_tab_entry
->pointer
= mem
;
1146 for (p
= sysdep_string
->segments
;; p
++)
1148 nls_uint32 segsize
=
1149 W (domain
->must_swap
, p
->segsize
);
1150 nls_uint32 sysdepref
=
1151 W (domain
->must_swap
, p
->sysdepref
);
1156 memcpy (mem
, static_segments
, segsize
);
1158 static_segments
+= segsize
;
1161 if (sysdepref
== SEGMENTS_END
)
1164 n
= strlen (sysdep_segment_values
[sysdepref
]);
1165 memcpy (mem
, sysdep_segment_values
[sysdepref
], n
);
1169 inmem_tab_entry
->length
=
1170 mem
- inmem_tab_entry
->pointer
;
1177 if (k
!= n_inmem_sysdep_strings
)
1180 /* Compute the augmented hash table. */
1181 for (i
= 0; i
< domain
->hash_size
; i
++)
1183 W (domain
->must_swap_hash_tab
, domain
->hash_tab
[i
]);
1184 for (i
= 0; i
< n_inmem_sysdep_strings
; i
++)
1186 const char *msgid
= inmem_orig_sysdep_tab
[i
].pointer
;
1187 nls_uint32 hash_val
= __hash_string (msgid
);
1188 nls_uint32 idx
= hash_val
% domain
->hash_size
;
1190 1 + (hash_val
% (domain
->hash_size
- 2));
1194 if (inmem_hash_tab
[idx
] == 0)
1196 /* Hash table entry is empty. Use it. */
1197 inmem_hash_tab
[idx
] = 1 + domain
->nstrings
+ i
;
1201 if (idx
>= domain
->hash_size
- incr
)
1202 idx
-= domain
->hash_size
- incr
;
1208 domain
->n_sysdep_strings
= n_inmem_sysdep_strings
;
1209 domain
->orig_sysdep_tab
= inmem_orig_sysdep_tab
;
1210 domain
->trans_sysdep_tab
= inmem_trans_sysdep_tab
;
1212 domain
->hash_tab
= inmem_hash_tab
;
1213 domain
->must_swap_hash_tab
= 0;
1217 domain
->n_sysdep_strings
= 0;
1218 domain
->orig_sysdep_tab
= NULL
;
1219 domain
->trans_sysdep_tab
= NULL
;
1222 freea (sysdep_segment_values
);
1226 domain
->n_sysdep_strings
= 0;
1227 domain
->orig_sysdep_tab
= NULL
;
1228 domain
->trans_sysdep_tab
= NULL
;
1235 /* This is an invalid revision. */
1237 /* This is an invalid .mo file. */
1238 free (domain
->malloced
);
1241 munmap ((caddr_t
) data
, size
);
1246 domain_file
->data
= NULL
;
1250 /* No caches of converted translations so far. */
1251 domain
->conversions
= NULL
;
1252 domain
->nconversions
= 0;
1253 __libc_rwlock_init (domain
->conversions_lock
);
1255 /* Get the header entry and look for a plural specification. */
1256 nullentry
= _nl_find_msg (domain_file
, domainbinding
, "", 0, &nullentrylen
);
1257 EXTRACT_PLURAL_EXPRESSION (nullentry
, &domain
->plural
, &domain
->nplurals
);
1263 domain_file
->decided
= 1;
1265 __libc_lock_unlock_recursive (lock
);
1271 internal_function __libc_freeres_fn_section
1272 _nl_unload_domain (domain
)
1273 struct loaded_domain
*domain
;
1277 if (domain
->plural
!= &__gettext_germanic_plural
)
1278 __gettext_free_exp ((struct expression
*) domain
->plural
);
1280 for (i
= 0; i
< domain
->nconversions
; i
++)
1282 struct converted_domain
*convd
= &domain
->conversions
[i
];
1284 free ((char *) convd
->encoding
);
1285 if (convd
->conv_tab
!= NULL
&& convd
->conv_tab
!= (char **) -1)
1286 free (convd
->conv_tab
);
1287 if (convd
->conv
!= (__gconv_t
) -1)
1288 __gconv_close (convd
->conv
);
1290 free (domain
->conversions
);
1291 __libc_rwlock_fini (domain
->conversions_lock
);
1293 free (domain
->malloced
);
1295 # ifdef _POSIX_MAPPED_FILES
1296 if (domain
->use_mmap
)
1297 munmap ((caddr_t
) domain
->data
, domain
->mmap_size
);
1299 # endif /* _POSIX_MAPPED_FILES */
1300 free ((void *) domain
->data
);