1 /* Load needed message catalogs.
2 Copyright (C) 1995-2015 Free Software Foundation, Inc.
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.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU Lesser General Public License for more details.
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/>. */
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. */
21 # define _GNU_SOURCE 1
32 #include <sys/types.h>
37 # define alloca __builtin_alloca
38 # define HAVE_ALLOCA 1
42 # define alloca _alloca
44 # if defined HAVE_ALLOCA_H || defined _LIBC
61 #if defined HAVE_UNISTD_H || defined _LIBC
66 # include <langinfo.h>
70 #if (defined HAVE_MMAP && defined HAVE_MUNMAP && !defined DISALLOW_MMAP) \
71 || (defined _LIBC && defined _POSIX_MAPPED_FILES)
72 # include <sys/mman.h>
79 #if defined HAVE_STDINT_H_WITH_UINTMAX || defined _LIBC
82 #if defined HAVE_INTTYPES_H || defined _LIBC
83 # include <inttypes.h>
88 #include "hash-string.h"
89 #include "plural-exp.h"
92 # include "../locale/localeinfo.h"
93 # include <not-cancel.h>
96 /* Handle multi-threaded applications. */
98 # include <bits/libc-lock.h>
104 # define PRI_MACROS_BROKEN 0
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
114 #if !defined PRIi8 || PRI_MACROS_BROKEN
118 #if !defined PRIo8 || PRI_MACROS_BROKEN
122 #if !defined PRIu8 || PRI_MACROS_BROKEN
126 #if !defined PRIx8 || PRI_MACROS_BROKEN
130 #if !defined PRIX8 || PRI_MACROS_BROKEN
134 #if !defined PRId16 || PRI_MACROS_BROKEN
138 #if !defined PRIi16 || PRI_MACROS_BROKEN
142 #if !defined PRIo16 || PRI_MACROS_BROKEN
146 #if !defined PRIu16 || PRI_MACROS_BROKEN
150 #if !defined PRIx16 || PRI_MACROS_BROKEN
154 #if !defined PRIX16 || PRI_MACROS_BROKEN
158 #if !defined PRId32 || PRI_MACROS_BROKEN
162 #if !defined PRIi32 || PRI_MACROS_BROKEN
166 #if !defined PRIo32 || PRI_MACROS_BROKEN
170 #if !defined PRIu32 || PRI_MACROS_BROKEN
174 #if !defined PRIx32 || PRI_MACROS_BROKEN
178 #if !defined PRIX32 || PRI_MACROS_BROKEN
182 #if !defined PRId64 || PRI_MACROS_BROKEN
184 # define PRId64 (sizeof (long) == 8 ? "ld" : "lld")
186 #if !defined PRIi64 || PRI_MACROS_BROKEN
188 # define PRIi64 (sizeof (long) == 8 ? "li" : "lli")
190 #if !defined PRIo64 || PRI_MACROS_BROKEN
192 # define PRIo64 (sizeof (long) == 8 ? "lo" : "llo")
194 #if !defined PRIu64 || PRI_MACROS_BROKEN
196 # define PRIu64 (sizeof (long) == 8 ? "lu" : "llu")
198 #if !defined PRIx64 || PRI_MACROS_BROKEN
200 # define PRIx64 (sizeof (long) == 8 ? "lx" : "llx")
202 #if !defined PRIX64 || PRI_MACROS_BROKEN
204 # define PRIX64 (sizeof (long) == 8 ? "lX" : "llX")
206 #if !defined PRIdLEAST8 || PRI_MACROS_BROKEN
208 # define PRIdLEAST8 "d"
210 #if !defined PRIiLEAST8 || PRI_MACROS_BROKEN
212 # define PRIiLEAST8 "i"
214 #if !defined PRIoLEAST8 || PRI_MACROS_BROKEN
216 # define PRIoLEAST8 "o"
218 #if !defined PRIuLEAST8 || PRI_MACROS_BROKEN
220 # define PRIuLEAST8 "u"
222 #if !defined PRIxLEAST8 || PRI_MACROS_BROKEN
224 # define PRIxLEAST8 "x"
226 #if !defined PRIXLEAST8 || PRI_MACROS_BROKEN
228 # define PRIXLEAST8 "X"
230 #if !defined PRIdLEAST16 || PRI_MACROS_BROKEN
232 # define PRIdLEAST16 "d"
234 #if !defined PRIiLEAST16 || PRI_MACROS_BROKEN
236 # define PRIiLEAST16 "i"
238 #if !defined PRIoLEAST16 || PRI_MACROS_BROKEN
240 # define PRIoLEAST16 "o"
242 #if !defined PRIuLEAST16 || PRI_MACROS_BROKEN
244 # define PRIuLEAST16 "u"
246 #if !defined PRIxLEAST16 || PRI_MACROS_BROKEN
248 # define PRIxLEAST16 "x"
250 #if !defined PRIXLEAST16 || PRI_MACROS_BROKEN
252 # define PRIXLEAST16 "X"
254 #if !defined PRIdLEAST32 || PRI_MACROS_BROKEN
256 # define PRIdLEAST32 "d"
258 #if !defined PRIiLEAST32 || PRI_MACROS_BROKEN
260 # define PRIiLEAST32 "i"
262 #if !defined PRIoLEAST32 || PRI_MACROS_BROKEN
264 # define PRIoLEAST32 "o"
266 #if !defined PRIuLEAST32 || PRI_MACROS_BROKEN
268 # define PRIuLEAST32 "u"
270 #if !defined PRIxLEAST32 || PRI_MACROS_BROKEN
272 # define PRIxLEAST32 "x"
274 #if !defined PRIXLEAST32 || PRI_MACROS_BROKEN
276 # define PRIXLEAST32 "X"
278 #if !defined PRIdLEAST64 || PRI_MACROS_BROKEN
280 # define PRIdLEAST64 PRId64
282 #if !defined PRIiLEAST64 || PRI_MACROS_BROKEN
284 # define PRIiLEAST64 PRIi64
286 #if !defined PRIoLEAST64 || PRI_MACROS_BROKEN
288 # define PRIoLEAST64 PRIo64
290 #if !defined PRIuLEAST64 || PRI_MACROS_BROKEN
292 # define PRIuLEAST64 PRIu64
294 #if !defined PRIxLEAST64 || PRI_MACROS_BROKEN
296 # define PRIxLEAST64 PRIx64
298 #if !defined PRIXLEAST64 || PRI_MACROS_BROKEN
300 # define PRIXLEAST64 PRIX64
302 #if !defined PRIdFAST8 || PRI_MACROS_BROKEN
304 # define PRIdFAST8 "d"
306 #if !defined PRIiFAST8 || PRI_MACROS_BROKEN
308 # define PRIiFAST8 "i"
310 #if !defined PRIoFAST8 || PRI_MACROS_BROKEN
312 # define PRIoFAST8 "o"
314 #if !defined PRIuFAST8 || PRI_MACROS_BROKEN
316 # define PRIuFAST8 "u"
318 #if !defined PRIxFAST8 || PRI_MACROS_BROKEN
320 # define PRIxFAST8 "x"
322 #if !defined PRIXFAST8 || PRI_MACROS_BROKEN
324 # define PRIXFAST8 "X"
326 #if !defined PRIdFAST16 || PRI_MACROS_BROKEN
328 # define PRIdFAST16 "d"
330 #if !defined PRIiFAST16 || PRI_MACROS_BROKEN
332 # define PRIiFAST16 "i"
334 #if !defined PRIoFAST16 || PRI_MACROS_BROKEN
336 # define PRIoFAST16 "o"
338 #if !defined PRIuFAST16 || PRI_MACROS_BROKEN
340 # define PRIuFAST16 "u"
342 #if !defined PRIxFAST16 || PRI_MACROS_BROKEN
344 # define PRIxFAST16 "x"
346 #if !defined PRIXFAST16 || PRI_MACROS_BROKEN
348 # define PRIXFAST16 "X"
350 #if !defined PRIdFAST32 || PRI_MACROS_BROKEN
352 # define PRIdFAST32 "d"
354 #if !defined PRIiFAST32 || PRI_MACROS_BROKEN
356 # define PRIiFAST32 "i"
358 #if !defined PRIoFAST32 || PRI_MACROS_BROKEN
360 # define PRIoFAST32 "o"
362 #if !defined PRIuFAST32 || PRI_MACROS_BROKEN
364 # define PRIuFAST32 "u"
366 #if !defined PRIxFAST32 || PRI_MACROS_BROKEN
368 # define PRIxFAST32 "x"
370 #if !defined PRIXFAST32 || PRI_MACROS_BROKEN
372 # define PRIXFAST32 "X"
374 #if !defined PRIdFAST64 || PRI_MACROS_BROKEN
376 # define PRIdFAST64 PRId64
378 #if !defined PRIiFAST64 || PRI_MACROS_BROKEN
380 # define PRIiFAST64 PRIi64
382 #if !defined PRIoFAST64 || PRI_MACROS_BROKEN
384 # define PRIoFAST64 PRIo64
386 #if !defined PRIuFAST64 || PRI_MACROS_BROKEN
388 # define PRIuFAST64 PRIu64
390 #if !defined PRIxFAST64 || PRI_MACROS_BROKEN
392 # define PRIxFAST64 PRIx64
394 #if !defined PRIXFAST64 || PRI_MACROS_BROKEN
396 # define PRIXFAST64 PRIX64
398 #if !defined PRIdMAX || PRI_MACROS_BROKEN
400 # define PRIdMAX (sizeof (uintmax_t) == sizeof (long) ? "ld" : "lld")
402 #if !defined PRIiMAX || PRI_MACROS_BROKEN
404 # define PRIiMAX (sizeof (uintmax_t) == sizeof (long) ? "li" : "lli")
406 #if !defined PRIoMAX || PRI_MACROS_BROKEN
408 # define PRIoMAX (sizeof (uintmax_t) == sizeof (long) ? "lo" : "llo")
410 #if !defined PRIuMAX || PRI_MACROS_BROKEN
412 # define PRIuMAX (sizeof (uintmax_t) == sizeof (long) ? "lu" : "llu")
414 #if !defined PRIxMAX || PRI_MACROS_BROKEN
416 # define PRIxMAX (sizeof (uintmax_t) == sizeof (long) ? "lx" : "llx")
418 #if !defined PRIXMAX || PRI_MACROS_BROKEN
420 # define PRIXMAX (sizeof (uintmax_t) == sizeof (long) ? "lX" : "llX")
422 #if !defined PRIdPTR || PRI_MACROS_BROKEN
425 (sizeof (void *) == sizeof (long) ? "ld" : \
426 sizeof (void *) == sizeof (int) ? "d" : \
429 #if !defined PRIiPTR || PRI_MACROS_BROKEN
432 (sizeof (void *) == sizeof (long) ? "li" : \
433 sizeof (void *) == sizeof (int) ? "i" : \
436 #if !defined PRIoPTR || PRI_MACROS_BROKEN
439 (sizeof (void *) == sizeof (long) ? "lo" : \
440 sizeof (void *) == sizeof (int) ? "o" : \
443 #if !defined PRIuPTR || PRI_MACROS_BROKEN
446 (sizeof (void *) == sizeof (long) ? "lu" : \
447 sizeof (void *) == sizeof (int) ? "u" : \
450 #if !defined PRIxPTR || PRI_MACROS_BROKEN
453 (sizeof (void *) == sizeof (long) ? "lx" : \
454 sizeof (void *) == sizeof (int) ? "x" : \
457 #if !defined PRIXPTR || PRI_MACROS_BROKEN
460 (sizeof (void *) == sizeof (long) ? "lX" : \
461 sizeof (void *) == sizeof (int) ? "X" : \
465 /* @@ end of prolog @@ */
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
470 file and the name space must not be polluted. */
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)
479 /* For those losing systems which don't have `alloca' we have to add
480 some additional code emulating it. */
482 # define freea(p) /* nothing */
484 # define alloca(n) malloc (n)
485 # define freea(p) free (p)
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
496 /* BeOS 5 has O_BINARY and O_TEXT, but they have no effect. */
500 /* On reasonable systems, binary I/O is the default. */
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. */
509 int _nl_msg_cat_cntr;
512 /* Expand a system dependent string segment. Return NULL if unsupported. */
514 get_sysdep_segment_value (const char *name)
516 /* Test for an ISO C 99 section 7.8.1 format string directive.
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')
524 if (name[3] == 'd' || name[3] == 'i' || name[3] == 'o' || name[3] == 'u'
525 || name[3] == 'x' || name[3] == 'X')
527 if (name[4] == '8' && name[5] == '\0')
543 if (name[4] == '1' && name[5] == '6' && name[6] == '\0')
559 if (name[4] == '3' && name[5] == '2' && name[6] == '\0')
575 if (name[4] == '6' && name[5] == '4' && name[6] == '\0')
591 if (name[4] == 'L' && name[5] == 'E' && name[6] == 'A'
592 && name[7] == 'S' && name[8] == 'T')
594 if (name[9] == '8' && name[10] == '\0')
610 if (name[9] == '1' && name[10] == '6' && name[11] == '\0')
626 if (name[9] == '3' && name[10] == '2' && name[11] == '\0')
642 if (name[9] == '6' && name[10] == '4' && name[11] == '\0')
659 if (name[4] == 'F' && name[5] == 'A' && name[6] == 'S'
662 if (name[8] == '8' && name[9] == '\0')
678 if (name[8] == '1' && name[9] == '6' && name[10] == '\0')
694 if (name[8] == '3' && name[9] == '2' && name[10] == '\0')
710 if (name[8] == '6' && name[9] == '4' && name[10] == '\0')
727 if (name[4] == 'M' && name[5] == 'A' && name[6] == 'X'
744 if (name[4] == 'P' && name[5] == 'T' && name[6] == 'R'
763 /* Test for a glibc specific printf() format directive flag. */
764 if (name[0] == 'I' && name[1] == '\0')
767 || ((__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2)) \
768 && !defined __UCLIBC__)
769 /* The 'I' flag, in numeric format directives, replaces ASCII digits
770 with the 'outdigits' defined in the LC_CTYPE locale facet. This is
771 used for Farsi (Persian), some Indic languages, and maybe Arabic. */
777 /* Other system dependent strings are not valid. */
781 /* Load the message catalogs specified by FILENAME. If it is no valid
782 message catalog do nothing. */
785 _nl_load_domain (struct loaded_l10nfile *domain_file,
786 struct binding *domainbinding)
795 struct mo_file_header *data = (struct mo_file_header *) -1;
797 struct loaded_domain *domain;
799 const char *nullentry;
801 __libc_lock_define_initialized_recursive (static, lock);
803 __libc_lock_lock_recursive (lock);
804 if (domain_file->decided != 0)
806 /* There are two possibilities:
808 + this is the same thread calling again during this initialization
809 via _nl_find_msg. We have initialized everything this call needs.
811 + this is another thread which tried to initialize this object.
812 Not necessary anymore since if the lock is available this
818 domain_file->decided = -1;
819 domain_file->data = NULL;
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). */
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
829 if (domain_file->filename == NULL)
832 /* Try to open the addressed file. */
833 fd = open (domain_file->filename, O_RDONLY | O_BINARY);
837 /* We must know about the size of the file. */
840 __builtin_expect (fstat64 (fd, &st) != 0, 0)
842 __builtin_expect (fstat (fd, &st) != 0, 0)
844 || __builtin_expect ((size = (size_t) st.st_size) != st.st_size, 0)
845 || __builtin_expect (size < sizeof (struct mo_file_header), 0))
846 /* Something went wrong. */
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. */
852 data = (struct mo_file_header *) mmap (NULL, size, PROT_READ,
855 if (__builtin_expect (data != MAP_FAILED, 1))
857 /* mmap() call was successful. */
863 assert (MAP_FAILED == (void *) -1);
866 /* If the data is not yet available (i.e. mmap'ed) we try to load
868 if (data == (struct mo_file_header *) -1)
873 data = (struct mo_file_header *) malloc (size);
878 read_ptr = (char *) data;
881 long int nb = (long int) read (fd, read_ptr, to_read);
885 if (nb == -1 && errno == EINTR)
900 /* Using the magic number we can test whether it really is a message
902 if (__builtin_expect (data->magic != _MAGIC && data->magic != _MAGIC_SWAPPED,
905 /* The magic number is wrong: not a message catalog file. */
908 munmap ((caddr_t) data, size);
915 domain = (struct loaded_domain *) malloc (sizeof (struct loaded_domain));
918 domain_file->data = domain;
920 domain->data = (char *) data;
921 domain->use_mmap = use_mmap;
922 domain->mmap_size = size;
923 domain->must_swap = data->magic != _MAGIC;
924 domain->malloced = NULL;
926 /* Fill in the information about the available tables. */
927 revision = W (domain->must_swap, data->revision);
928 /* We support only the major revisions 0 and 1. */
929 switch (revision >> 16)
933 domain->nstrings = W (domain->must_swap, data->nstrings);
934 domain->orig_tab = (const struct string_desc *)
935 ((char *) data + W (domain->must_swap, data->orig_tab_offset));
936 domain->trans_tab = (const struct string_desc *)
937 ((char *) data + W (domain->must_swap, data->trans_tab_offset));
938 domain->hash_size = W (domain->must_swap, data->hash_tab_size);
940 (domain->hash_size > 2
941 ? (const nls_uint32 *)
942 ((char *) data + W (domain->must_swap, data->hash_tab_offset))
944 domain->must_swap_hash_tab = domain->must_swap;
946 /* Now dispatch on the minor revision. */
947 switch (revision & 0xffff)
950 domain->n_sysdep_strings = 0;
951 domain->orig_sysdep_tab = NULL;
952 domain->trans_sysdep_tab = NULL;
957 nls_uint32 n_sysdep_strings;
959 if (domain->hash_tab == NULL)
960 /* This is invalid. These minor revisions need a hash table. */
964 W (domain->must_swap, data->n_sysdep_strings);
965 if (n_sysdep_strings > 0)
967 nls_uint32 n_sysdep_segments;
968 const struct sysdep_segment *sysdep_segments;
969 const char **sysdep_segment_values;
970 const nls_uint32 *orig_sysdep_tab;
971 const nls_uint32 *trans_sysdep_tab;
972 nls_uint32 n_inmem_sysdep_strings;
975 struct sysdep_string_desc *inmem_orig_sysdep_tab;
976 struct sysdep_string_desc *inmem_trans_sysdep_tab;
977 nls_uint32 *inmem_hash_tab;
980 /* Get the values of the system dependent segments. */
982 W (domain->must_swap, data->n_sysdep_segments);
983 sysdep_segments = (const struct sysdep_segment *)
985 + W (domain->must_swap, data->sysdep_segments_offset));
986 sysdep_segment_values =
988 alloca (n_sysdep_segments * sizeof (const char *));
989 for (i = 0; i < n_sysdep_segments; i++)
993 + W (domain->must_swap, sysdep_segments[i].offset);
995 W (domain->must_swap, sysdep_segments[i].length);
997 if (!(namelen > 0 && name[namelen - 1] == '\0'))
999 freea (sysdep_segment_values);
1003 sysdep_segment_values[i] = get_sysdep_segment_value (name);
1006 orig_sysdep_tab = (const nls_uint32 *)
1008 + W (domain->must_swap, data->orig_sysdep_tab_offset));
1009 trans_sysdep_tab = (const nls_uint32 *)
1011 + W (domain->must_swap, data->trans_sysdep_tab_offset));
1013 /* Compute the amount of additional memory needed for the
1014 system dependent strings and the augmented hash table.
1015 At the same time, also drop string pairs which refer to
1016 an undefined system dependent segment. */
1017 n_inmem_sysdep_strings = 0;
1018 memneed = domain->hash_size * sizeof (nls_uint32);
1019 for (i = 0; i < n_sysdep_strings; i++)
1024 for (j = 0; j < 2; j++)
1026 const struct sysdep_string *sysdep_string =
1027 (const struct sysdep_string *)
1029 + W (domain->must_swap,
1031 ? orig_sysdep_tab[i]
1032 : trans_sysdep_tab[i]));
1034 const struct segment_pair *p = sysdep_string->segments;
1036 if (W (domain->must_swap, p->sysdepref) != SEGMENTS_END)
1037 for (p = sysdep_string->segments;; p++)
1039 nls_uint32 sysdepref;
1041 need += W (domain->must_swap, p->segsize);
1043 sysdepref = W (domain->must_swap, p->sysdepref);
1044 if (sysdepref == SEGMENTS_END)
1047 if (sysdepref >= n_sysdep_segments)
1050 freea (sysdep_segment_values);
1054 if (sysdep_segment_values[sysdepref] == NULL)
1056 /* This particular string pair is invalid. */
1061 need += strlen (sysdep_segment_values[sysdepref]);
1071 n_inmem_sysdep_strings++;
1072 memneed += needs[0] + needs[1];
1075 memneed += 2 * n_inmem_sysdep_strings
1076 * sizeof (struct sysdep_string_desc);
1078 if (n_inmem_sysdep_strings > 0)
1082 /* Allocate additional memory. */
1083 mem = (char *) malloc (memneed);
1087 domain->malloced = mem;
1088 inmem_orig_sysdep_tab = (struct sysdep_string_desc *) mem;
1089 mem += n_inmem_sysdep_strings
1090 * sizeof (struct sysdep_string_desc);
1091 inmem_trans_sysdep_tab = (struct sysdep_string_desc *) mem;
1092 mem += n_inmem_sysdep_strings
1093 * sizeof (struct sysdep_string_desc);
1094 inmem_hash_tab = (nls_uint32 *) mem;
1095 mem += domain->hash_size * sizeof (nls_uint32);
1097 /* Compute the system dependent strings. */
1099 for (i = 0; i < n_sysdep_strings; i++)
1103 for (j = 0; j < 2; j++)
1105 const struct sysdep_string *sysdep_string =
1106 (const struct sysdep_string *)
1108 + W (domain->must_swap,
1110 ? orig_sysdep_tab[i]
1111 : trans_sysdep_tab[i]));
1112 const struct segment_pair *p =
1113 sysdep_string->segments;
1115 if (W (domain->must_swap, p->sysdepref)
1117 for (p = sysdep_string->segments;; p++)
1119 nls_uint32 sysdepref;
1122 W (domain->must_swap, p->sysdepref);
1123 if (sysdepref == SEGMENTS_END)
1126 if (sysdep_segment_values[sysdepref] == NULL)
1128 /* This particular string pair is
1141 for (j = 0; j < 2; j++)
1143 const struct sysdep_string *sysdep_string =
1144 (const struct sysdep_string *)
1146 + W (domain->must_swap,
1148 ? orig_sysdep_tab[i]
1149 : trans_sysdep_tab[i]));
1150 const char *static_segments =
1152 + W (domain->must_swap, sysdep_string->offset);
1153 const struct segment_pair *p =
1154 sysdep_string->segments;
1156 /* Concatenate the segments, and fill
1157 inmem_orig_sysdep_tab[k] (for j == 0) and
1158 inmem_trans_sysdep_tab[k] (for j == 1). */
1160 struct sysdep_string_desc *inmem_tab_entry =
1162 ? inmem_orig_sysdep_tab
1163 : inmem_trans_sysdep_tab)
1166 if (W (domain->must_swap, p->sysdepref)
1169 /* Only one static segment. */
1170 inmem_tab_entry->length =
1171 W (domain->must_swap, p->segsize);
1172 inmem_tab_entry->pointer = static_segments;
1176 inmem_tab_entry->pointer = mem;
1178 for (p = sysdep_string->segments;; p++)
1180 nls_uint32 segsize =
1181 W (domain->must_swap, p->segsize);
1182 nls_uint32 sysdepref =
1183 W (domain->must_swap, p->sysdepref);
1188 memcpy (mem, static_segments, segsize);
1190 static_segments += segsize;
1193 if (sysdepref == SEGMENTS_END)
1196 n = strlen (sysdep_segment_values[sysdepref]);
1197 memcpy (mem, sysdep_segment_values[sysdepref], n);
1201 inmem_tab_entry->length =
1202 mem - inmem_tab_entry->pointer;
1209 if (k != n_inmem_sysdep_strings)
1212 /* Compute the augmented hash table. */
1213 for (i = 0; i < domain->hash_size; i++)
1215 W (domain->must_swap_hash_tab, domain->hash_tab[i]);
1216 for (i = 0; i < n_inmem_sysdep_strings; i++)
1218 const char *msgid = inmem_orig_sysdep_tab[i].pointer;
1219 nls_uint32 hash_val = __hash_string (msgid);
1220 nls_uint32 idx = hash_val % domain->hash_size;
1222 1 + (hash_val % (domain->hash_size - 2));
1226 if (inmem_hash_tab[idx] == 0)
1228 /* Hash table entry is empty. Use it. */
1229 inmem_hash_tab[idx] = 1 + domain->nstrings + i;
1233 if (idx >= domain->hash_size - incr)
1234 idx -= domain->hash_size - incr;
1240 domain->n_sysdep_strings = n_inmem_sysdep_strings;
1241 domain->orig_sysdep_tab = inmem_orig_sysdep_tab;
1242 domain->trans_sysdep_tab = inmem_trans_sysdep_tab;
1244 domain->hash_tab = inmem_hash_tab;
1245 domain->must_swap_hash_tab = 0;
1249 domain->n_sysdep_strings = 0;
1250 domain->orig_sysdep_tab = NULL;
1251 domain->trans_sysdep_tab = NULL;
1254 freea (sysdep_segment_values);
1258 domain->n_sysdep_strings = 0;
1259 domain->orig_sysdep_tab = NULL;
1260 domain->trans_sysdep_tab = NULL;
1267 /* This is an invalid revision. */
1269 /* This is an invalid .mo file or we ran out of resources. */
1270 free (domain->malloced);
1273 munmap ((caddr_t) data, size);
1278 domain_file->data = NULL;
1282 /* No caches of converted translations so far. */
1283 domain->conversions = NULL;
1284 domain->nconversions = 0;
1286 __libc_rwlock_init (domain->conversions_lock);
1288 gl_rwlock_init (domain->conversions_lock);
1291 /* Get the header entry and look for a plural specification. */
1292 #ifdef IN_LIBGLOCALE
1294 _nl_find_msg (domain_file, domainbinding, NULL, "", &nullentrylen);
1296 nullentry = _nl_find_msg (domain_file, domainbinding, "", 0, &nullentrylen);
1298 if (__builtin_expect (nullentry == (char *) -1, 0))
1301 __libc_rwlock_fini (domain->conversions_lock);
1305 EXTRACT_PLURAL_EXPRESSION (nullentry, &domain->plural, &domain->nplurals);
1311 domain_file->decided = 1;
1314 __libc_lock_unlock_recursive (lock);
1320 internal_function __libc_freeres_fn_section
1321 _nl_unload_domain (struct loaded_domain *domain)
1325 if (domain->plural != &__gettext_germanic_plural)
1326 __gettext_free_exp ((struct expression *) domain->plural);
1328 for (i = 0; i < domain->nconversions; i++)
1330 struct converted_domain *convd = &domain->conversions[i];
1332 free ((char *) convd->encoding);
1333 if (convd->conv_tab != NULL && convd->conv_tab != (char **) -1)
1334 free (convd->conv_tab);
1335 if (convd->conv != (__gconv_t) -1)
1336 __gconv_close (convd->conv);
1338 free (domain->conversions);
1339 __libc_rwlock_fini (domain->conversions_lock);
1341 free (domain->malloced);
1343 # ifdef _POSIX_MAPPED_FILES
1344 if (domain->use_mmap)
1345 munmap ((caddr_t) domain->data, domain->mmap_size);
1347 # endif /* _POSIX_MAPPED_FILES */
1348 free ((void *) domain->data);