1 /* Load needed message catalogs.
2 Copyright (C) 1995-1999, 2000, 2001 Free Software Foundation, Inc.
4 This program is free software; you can redistribute it and/or modify it
5 under the terms of the GNU Library General Public License as published
6 by the Free Software Foundation; either version 2, or (at your option)
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 GNU
12 Library General Public License for more details.
14 You should have received a copy of the GNU Library General Public
15 License along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
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>
37 # define alloca __builtin_alloca
38 # define HAVE_ALLOCA 1
40 # if defined HAVE_ALLOCA_H || defined _LIBC
56 #if defined HAVE_UNISTD_H || defined _LIBC
61 # include <langinfo.h>
65 #if (defined HAVE_MMAP && defined HAVE_MUNMAP && !defined DISALLOW_MMAP) \
66 || (defined _LIBC && defined _POSIX_MAPPED_FILES)
67 # include <sys/mman.h>
76 #include "plural-exp.h"
79 # include "../locale/localeinfo.h"
82 /* @@ end of prolog @@ */
85 /* Rename the non ISO C functions. This is required by the standard
86 because some ISO C functions will require linking with this object
87 file and the name space must not be polluted. */
89 # define close __close
92 # define munmap __munmap
95 /* For those losing systems which don't have `alloca' we have to add
96 some additional code emulating it. */
98 # define freea(p) /* nothing */
100 # define alloca(n) malloc (n)
101 # define freea(p) free (p)
104 /* For systems that distinguish between text and binary I/O.
105 O_BINARY is usually declared in <fcntl.h>. */
106 #if !defined O_BINARY && defined _O_BINARY
107 /* For MSC-compatible compilers. */
108 # define O_BINARY _O_BINARY
109 # define O_TEXT _O_TEXT
112 /* BeOS 5 has O_BINARY and O_TEXT, but they have no effect. */
116 /* On reasonable systems, binary I/O is the default. */
121 /* We need a sign, whether a new catalog was loaded, which can be associated
122 with all translations. This is important if the translations are
123 cached by one of GCC's features. */
124 int _nl_msg_cat_cntr;
127 /* Initialize the codeset dependent parts of an opened message catalog.
128 Return the header entry. */
131 _nl_init_domain_conv (domain_file, domain, domainbinding)
132 struct loaded_l10nfile *domain_file;
133 struct loaded_domain *domain;
134 struct binding *domainbinding;
136 /* Find out about the character set the file is encoded with.
137 This can be found (in textual form) in the entry "". If this
138 entry does not exist or if this does not contain the `charset='
139 information, we will assume the charset matches the one the
140 current locale and we don't have to perform any conversion. */
144 /* Preinitialize fields, to avoid recursion during _nl_find_msg. */
145 domain->codeset_cntr =
146 (domainbinding != NULL ? domainbinding->codeset_cntr : 0);
148 domain->conv = (__gconv_t) -1;
151 domain->conv = (iconv_t) -1;
154 domain->conv_tab = NULL;
156 /* Get the header entry. */
157 nullentry = _nl_find_msg (domain_file, domainbinding, "", &nullentrylen);
159 if (nullentry != NULL)
161 #if defined _LIBC || HAVE_ICONV
162 const char *charsetstr;
164 charsetstr = strstr (nullentry, "charset=");
165 if (charsetstr != NULL)
169 const char *outcharset;
171 charsetstr += strlen ("charset=");
172 len = strcspn (charsetstr, " \t\n");
174 charset = (char *) alloca (len + 1);
175 # if defined _LIBC || HAVE_MEMPCPY
176 *((char *) mempcpy (charset, charsetstr, len)) = '\0';
178 memcpy (charset, charsetstr, len);
182 /* The output charset should normally be determined by the
183 locale. But sometimes the locale is not used or not correctly
184 set up, so we provide a possibility for the user to override
185 this. Moreover, the value specified through
186 bind_textdomain_codeset overrides both. */
187 if (domainbinding != NULL && domainbinding->codeset != NULL)
188 outcharset = domainbinding->codeset;
191 outcharset = getenv ("OUTPUT_CHARSET");
192 if (outcharset == NULL || outcharset[0] == '\0')
195 outcharset = (*_nl_current[LC_CTYPE])->values[_NL_ITEM_INDEX (CODESET)].string;
198 extern const char *locale_charset PARAMS ((void));
199 outcharset = locale_charset ();
206 /* We always want to use transliteration. */
207 outcharset = norm_add_slashes (outcharset, "TRANSLIT");
208 charset = norm_add_slashes (charset, NULL);
209 if (__gconv_open (outcharset, charset, &domain->conv,
212 domain->conv = (__gconv_t) -1;
215 /* When using GNU libc >= 2.2 or GNU libiconv >= 1.5,
216 we want to use transliteration. */
217 # if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2) || __GLIBC__ > 2 \
218 || _LIBICONV_VERSION >= 0x0105
219 len = strlen (outcharset);
221 char *tmp = (char *) alloca (len + 10 + 1);
222 memcpy (tmp, outcharset, len);
223 memcpy (tmp + len, "//TRANSLIT", 10 + 1);
227 domain->conv = iconv_open (outcharset, charset);
228 # if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2) || __GLIBC__ > 2 \
229 || _LIBICONV_VERSION >= 0x0105
237 #endif /* _LIBC || HAVE_ICONV */
243 /* Frees the codeset dependent parts of an opened message catalog. */
246 _nl_free_domain_conv (domain)
247 struct loaded_domain *domain;
249 if (domain->conv_tab != NULL && domain->conv_tab != (char **) -1)
250 free (domain->conv_tab);
253 if (domain->conv != (__gconv_t) -1)
254 __gconv_close (domain->conv);
257 if (domain->conv != (iconv_t) -1)
258 iconv_close (domain->conv);
263 /* Load the message catalogs specified by FILENAME. If it is no valid
264 message catalog do nothing. */
267 _nl_load_domain (domain_file, domainbinding)
268 struct loaded_l10nfile *domain_file;
269 struct binding *domainbinding;
278 struct mo_file_header *data = (struct mo_file_header *) -1;
280 struct loaded_domain *domain;
281 const char *nullentry;
283 domain_file->decided = 1;
284 domain_file->data = NULL;
286 /* Note that it would be useless to store domainbinding in domain_file
287 because domainbinding might be == NULL now but != NULL later (after
288 a call to bind_textdomain_codeset). */
290 /* If the record does not represent a valid locale the FILENAME
291 might be NULL. This can happen when according to the given
292 specification the locale file name is different for XPG and CEN
294 if (domain_file->filename == NULL)
297 /* Try to open the addressed file. */
298 fd = open (domain_file->filename, O_RDONLY | O_BINARY);
302 /* We must know about the size of the file. */
305 __builtin_expect (fstat64 (fd, &st) != 0, 0)
307 __builtin_expect (fstat (fd, &st) != 0, 0)
309 || __builtin_expect ((size = (size_t) st.st_size) != st.st_size, 0)
310 || __builtin_expect (size < sizeof (struct mo_file_header), 0))
312 /* Something went wrong. */
318 /* Now we are ready to load the file. If mmap() is available we try
319 this first. If not available or it failed we try to load it. */
320 data = (struct mo_file_header *) mmap (NULL, size, PROT_READ,
323 if (__builtin_expect (data != (struct mo_file_header *) -1, 1))
325 /* mmap() call was successful. */
331 /* If the data is not yet available (i.e. mmap'ed) we try to load
333 if (data == (struct mo_file_header *) -1)
338 data = (struct mo_file_header *) malloc (size);
343 read_ptr = (char *) data;
346 long int nb = (long int) read (fd, read_ptr, to_read);
350 if (nb == -1 && errno == EINTR)
364 /* Using the magic number we can test whether it really is a message
366 if (__builtin_expect (data->magic != _MAGIC && data->magic != _MAGIC_SWAPPED,
369 /* The magic number is wrong: not a message catalog file. */
372 munmap ((caddr_t) data, size);
379 domain = (struct loaded_domain *) malloc (sizeof (struct loaded_domain));
382 domain_file->data = domain;
384 domain->data = (char *) data;
385 domain->use_mmap = use_mmap;
386 domain->mmap_size = size;
387 domain->must_swap = data->magic != _MAGIC;
389 /* Fill in the information about the available tables. */
390 switch (W (domain->must_swap, data->revision))
393 domain->nstrings = W (domain->must_swap, data->nstrings);
394 domain->orig_tab = (struct string_desc *)
395 ((char *) data + W (domain->must_swap, data->orig_tab_offset));
396 domain->trans_tab = (struct string_desc *)
397 ((char *) data + W (domain->must_swap, data->trans_tab_offset));
398 domain->hash_size = W (domain->must_swap, data->hash_tab_size);
399 domain->hash_tab = (nls_uint32 *)
400 ((char *) data + W (domain->must_swap, data->hash_tab_offset));
403 /* This is an invalid revision. */
406 munmap ((caddr_t) data, size);
411 domain_file->data = NULL;
415 /* Now initialize the character set converter from the character set
416 the file is encoded with (found in the header entry) to the domain's
417 specified character set or the locale's character set. */
418 nullentry = _nl_init_domain_conv (domain_file, domain, domainbinding);
420 /* Also look for a plural specification. */
421 EXTRACT_PLURAL_EXPRESSION (nullentry, &domain->plural, &domain->nplurals);
428 _nl_unload_domain (domain)
429 struct loaded_domain *domain;
431 if (domain->plural != &__gettext_germanic_plural)
432 __gettext_free_exp (domain->plural);
434 _nl_free_domain_conv (domain);
436 # ifdef _POSIX_MAPPED_FILES
437 if (domain->use_mmap)
438 munmap ((caddr_t) domain->data, domain->mmap_size);
440 # endif /* _POSIX_MAPPED_FILES */
441 free ((void *) domain->data);