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
)
788 __libc_lock_define_initialized_recursive (static, lock
);
796 struct mo_file_header
*data
= (struct mo_file_header
*) -1;
798 struct loaded_domain
*domain
;
800 const char *nullentry
;
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
)
899 /* Using the magic number we can test whether it really is a message
901 if (__builtin_expect (data
->magic
!= _MAGIC
&& data
->magic
!= _MAGIC_SWAPPED
,
904 /* The magic number is wrong: not a message catalog file. */
907 munmap ((caddr_t
) data
, size
);
914 domain
= (struct loaded_domain
*) malloc (sizeof (struct loaded_domain
));
917 domain_file
->data
= domain
;
919 domain
->data
= (char *) data
;
920 domain
->use_mmap
= use_mmap
;
921 domain
->mmap_size
= size
;
922 domain
->must_swap
= data
->magic
!= _MAGIC
;
923 domain
->malloced
= NULL
;
925 /* Fill in the information about the available tables. */
926 revision
= W (domain
->must_swap
, data
->revision
);
927 /* We support only the major revisions 0 and 1. */
928 switch (revision
>> 16)
932 domain
->nstrings
= W (domain
->must_swap
, data
->nstrings
);
933 domain
->orig_tab
= (const struct string_desc
*)
934 ((char *) data
+ W (domain
->must_swap
, data
->orig_tab_offset
));
935 domain
->trans_tab
= (const struct string_desc
*)
936 ((char *) data
+ W (domain
->must_swap
, data
->trans_tab_offset
));
937 domain
->hash_size
= W (domain
->must_swap
, data
->hash_tab_size
);
939 (domain
->hash_size
> 2
940 ? (const nls_uint32
*)
941 ((char *) data
+ W (domain
->must_swap
, data
->hash_tab_offset
))
943 domain
->must_swap_hash_tab
= domain
->must_swap
;
945 /* Now dispatch on the minor revision. */
946 switch (revision
& 0xffff)
949 domain
->n_sysdep_strings
= 0;
950 domain
->orig_sysdep_tab
= NULL
;
951 domain
->trans_sysdep_tab
= NULL
;
956 nls_uint32 n_sysdep_strings
;
958 if (domain
->hash_tab
== NULL
)
959 /* This is invalid. These minor revisions need a hash table. */
963 W (domain
->must_swap
, data
->n_sysdep_strings
);
964 if (n_sysdep_strings
> 0)
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
;
971 nls_uint32 n_inmem_sysdep_strings
;
974 struct sysdep_string_desc
*inmem_orig_sysdep_tab
;
975 struct sysdep_string_desc
*inmem_trans_sysdep_tab
;
976 nls_uint32
*inmem_hash_tab
;
979 /* Get the values of the system dependent segments. */
981 W (domain
->must_swap
, data
->n_sysdep_segments
);
982 sysdep_segments
= (const struct sysdep_segment
*)
984 + W (domain
->must_swap
, data
->sysdep_segments_offset
));
985 sysdep_segment_values
=
987 alloca (n_sysdep_segments
* sizeof (const char *));
988 for (i
= 0; i
< n_sysdep_segments
; i
++)
992 + W (domain
->must_swap
, sysdep_segments
[i
].offset
);
994 W (domain
->must_swap
, sysdep_segments
[i
].length
);
996 if (!(namelen
> 0 && name
[namelen
- 1] == '\0'))
998 freea (sysdep_segment_values
);
1002 sysdep_segment_values
[i
] = get_sysdep_segment_value (name
);
1005 orig_sysdep_tab
= (const nls_uint32
*)
1007 + W (domain
->must_swap
, data
->orig_sysdep_tab_offset
));
1008 trans_sysdep_tab
= (const nls_uint32
*)
1010 + W (domain
->must_swap
, data
->trans_sysdep_tab_offset
));
1012 /* Compute the amount of additional memory needed for the
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
++)
1023 for (j
= 0; j
< 2; j
++)
1025 const struct sysdep_string
*sysdep_string
=
1026 (const struct sysdep_string
*)
1028 + W (domain
->must_swap
,
1030 ? orig_sysdep_tab
[i
]
1031 : trans_sysdep_tab
[i
]));
1033 const struct segment_pair
*p
= sysdep_string
->segments
;
1035 if (W (domain
->must_swap
, p
->sysdepref
) != SEGMENTS_END
)
1036 for (p
= sysdep_string
->segments
;; p
++)
1038 nls_uint32 sysdepref
;
1040 need
+= W (domain
->must_swap
, p
->segsize
);
1042 sysdepref
= W (domain
->must_swap
, p
->sysdepref
);
1043 if (sysdepref
== SEGMENTS_END
)
1046 if (sysdepref
>= n_sysdep_segments
)
1049 freea (sysdep_segment_values
);
1053 if (sysdep_segment_values
[sysdepref
] == NULL
)
1055 /* This particular string pair is invalid. */
1060 need
+= strlen (sysdep_segment_values
[sysdepref
]);
1070 n_inmem_sysdep_strings
++;
1071 memneed
+= needs
[0] + needs
[1];
1074 memneed
+= 2 * n_inmem_sysdep_strings
1075 * sizeof (struct sysdep_string_desc
);
1077 if (n_inmem_sysdep_strings
> 0)
1081 /* Allocate additional memory. */
1082 mem
= (char *) malloc (memneed
);
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
);
1096 /* Compute the system dependent strings. */
1098 for (i
= 0; i
< n_sysdep_strings
; i
++)
1102 for (j
= 0; j
< 2; j
++)
1104 const struct sysdep_string
*sysdep_string
=
1105 (const struct sysdep_string
*)
1107 + W (domain
->must_swap
,
1109 ? orig_sysdep_tab
[i
]
1110 : trans_sysdep_tab
[i
]));
1111 const struct segment_pair
*p
=
1112 sysdep_string
->segments
;
1114 if (W (domain
->must_swap
, p
->sysdepref
)
1116 for (p
= sysdep_string
->segments
;; p
++)
1118 nls_uint32 sysdepref
;
1121 W (domain
->must_swap
, p
->sysdepref
);
1122 if (sysdepref
== SEGMENTS_END
)
1125 if (sysdep_segment_values
[sysdepref
] == NULL
)
1127 /* This particular string pair is
1140 for (j
= 0; j
< 2; j
++)
1142 const struct sysdep_string
*sysdep_string
=
1143 (const struct sysdep_string
*)
1145 + W (domain
->must_swap
,
1147 ? orig_sysdep_tab
[i
]
1148 : trans_sysdep_tab
[i
]));
1149 const char *static_segments
=
1151 + W (domain
->must_swap
, sysdep_string
->offset
);
1152 const struct segment_pair
*p
=
1153 sysdep_string
->segments
;
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). */
1159 struct sysdep_string_desc
*inmem_tab_entry
=
1161 ? inmem_orig_sysdep_tab
1162 : inmem_trans_sysdep_tab
)
1165 if (W (domain
->must_swap
, p
->sysdepref
)
1168 /* Only one static segment. */
1169 inmem_tab_entry
->length
=
1170 W (domain
->must_swap
, p
->segsize
);
1171 inmem_tab_entry
->pointer
= static_segments
;
1175 inmem_tab_entry
->pointer
= mem
;
1177 for (p
= sysdep_string
->segments
;; p
++)
1179 nls_uint32 segsize
=
1180 W (domain
->must_swap
, p
->segsize
);
1181 nls_uint32 sysdepref
=
1182 W (domain
->must_swap
, p
->sysdepref
);
1187 memcpy (mem
, static_segments
, segsize
);
1189 static_segments
+= segsize
;
1192 if (sysdepref
== SEGMENTS_END
)
1195 n
= strlen (sysdep_segment_values
[sysdepref
]);
1196 memcpy (mem
, sysdep_segment_values
[sysdepref
], n
);
1200 inmem_tab_entry
->length
=
1201 mem
- inmem_tab_entry
->pointer
;
1208 if (k
!= n_inmem_sysdep_strings
)
1211 /* Compute the augmented hash table. */
1212 for (i
= 0; i
< domain
->hash_size
; i
++)
1214 W (domain
->must_swap_hash_tab
, domain
->hash_tab
[i
]);
1215 for (i
= 0; i
< n_inmem_sysdep_strings
; i
++)
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
;
1221 1 + (hash_val
% (domain
->hash_size
- 2));
1225 if (inmem_hash_tab
[idx
] == 0)
1227 /* Hash table entry is empty. Use it. */
1228 inmem_hash_tab
[idx
] = 1 + domain
->nstrings
+ i
;
1232 if (idx
>= domain
->hash_size
- incr
)
1233 idx
-= domain
->hash_size
- incr
;
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
;
1243 domain
->hash_tab
= inmem_hash_tab
;
1244 domain
->must_swap_hash_tab
= 0;
1248 domain
->n_sysdep_strings
= 0;
1249 domain
->orig_sysdep_tab
= NULL
;
1250 domain
->trans_sysdep_tab
= NULL
;
1253 freea (sysdep_segment_values
);
1257 domain
->n_sysdep_strings
= 0;
1258 domain
->orig_sysdep_tab
= NULL
;
1259 domain
->trans_sysdep_tab
= NULL
;
1266 /* This is an invalid revision. */
1268 /* This is an invalid .mo file or we ran out of resources. */
1269 free (domain
->malloced
);
1272 munmap ((caddr_t
) data
, size
);
1277 domain_file
->data
= NULL
;
1281 /* No caches of converted translations so far. */
1282 domain
->conversions
= NULL
;
1283 domain
->nconversions
= 0;
1285 __libc_rwlock_init (domain
->conversions_lock
);
1287 gl_rwlock_init (domain
->conversions_lock
);
1290 /* Get the header entry and look for a plural specification. */
1291 #ifdef IN_LIBGLOCALE
1293 _nl_find_msg (domain_file
, domainbinding
, NULL
, "", &nullentrylen
);
1295 nullentry
= _nl_find_msg (domain_file
, domainbinding
, "", 0, &nullentrylen
);
1297 if (__builtin_expect (nullentry
== (char *) -1, 0))
1300 __libc_rwlock_fini (domain
->conversions_lock
);
1304 EXTRACT_PLURAL_EXPRESSION (nullentry
, &domain
->plural
, &domain
->nplurals
);
1310 domain_file
->decided
= 1;
1313 __libc_lock_unlock_recursive (lock
);
1319 internal_function __libc_freeres_fn_section
1320 _nl_unload_domain (struct loaded_domain
*domain
)
1324 if (domain
->plural
!= &__gettext_germanic_plural
)
1325 __gettext_free_exp ((struct expression
*) domain
->plural
);
1327 for (i
= 0; i
< domain
->nconversions
; i
++)
1329 struct converted_domain
*convd
= &domain
->conversions
[i
];
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
);
1337 free (domain
->conversions
);
1338 __libc_rwlock_fini (domain
->conversions_lock
);
1340 free (domain
->malloced
);
1342 # ifdef _POSIX_MAPPED_FILES
1343 if (domain
->use_mmap
)
1344 munmap ((caddr_t
) domain
->data
, domain
->mmap_size
);
1346 # endif /* _POSIX_MAPPED_FILES */
1347 free ((void *) domain
->data
);