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>
78 # include "../locale/localeinfo.h"
81 /* @@ end of prolog @@ */
84 /* Rename the non ISO C functions. This is required by the standard
85 because some ISO C functions will require linking with this object
86 file and the name space must not be polluted. */
88 # define close __close
91 # define munmap __munmap
94 /* Names for the libintl functions are a problem. They must not clash
95 with existing names and they should follow ANSI C. But this source
96 code is also used in GNU C Library where the names have a __
97 prefix. So we have to make a difference here. */
99 # define PLURAL_PARSE __gettextparse
101 # define PLURAL_PARSE gettextparse__
104 /* For those losing systems which don't have `alloca' we have to add
105 some additional code emulating it. */
107 # define freea(p) /* nothing */
109 # define alloca(n) malloc (n)
110 # define freea(p) free (p)
113 /* For systems that distinguish between text and binary I/O.
114 O_BINARY is usually declared in <fcntl.h>. */
115 #if !defined O_BINARY && defined _O_BINARY
116 /* For MSC-compatible compilers. */
117 # define O_BINARY _O_BINARY
118 # define O_TEXT _O_TEXT
121 /* BeOS 5 has O_BINARY and O_TEXT, but they have no effect. */
125 /* On reasonable systems, binary I/O is the default. */
130 /* We need a sign, whether a new catalog was loaded, which can be associated
131 with all translations. This is important if the translations are
132 cached by one of GCC's features. */
133 int _nl_msg_cat_cntr;
135 #if (defined __GNUC__ && !defined __APPLE_CC__) \
136 || (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L)
138 /* These structs are the constant expression for the germanic plural
139 form determination. It represents the expression "n != 1". */
140 static const struct expression plvar =
145 static const struct expression plone =
154 static struct expression germanic_plural =
157 .operation = not_equal,
162 [0] = (struct expression *) &plvar,
163 [1] = (struct expression *) &plone
168 # define INIT_GERMANIC_PLURAL()
172 /* For compilers without support for ISO C 99 struct/union initializers:
173 Initialization at run-time. */
175 static struct expression plvar;
176 static struct expression plone;
177 static struct expression germanic_plural;
180 init_germanic_plural ()
182 if (plone.val.num == 0)
185 plvar.operation = var;
188 plone.operation = num;
191 germanic_plural.nargs = 2;
192 germanic_plural.operation = not_equal;
193 germanic_plural.val.args[0] = &plvar;
194 germanic_plural.val.args[1] = &plone;
198 # define INIT_GERMANIC_PLURAL() init_germanic_plural ()
203 /* Initialize the codeset dependent parts of an opened message catalog.
204 Return the header entry. */
207 _nl_init_domain_conv (domain_file, domain, domainbinding)
208 struct loaded_l10nfile *domain_file;
209 struct loaded_domain *domain;
210 struct binding *domainbinding;
212 /* Find out about the character set the file is encoded with.
213 This can be found (in textual form) in the entry "". If this
214 entry does not exist or if this does not contain the `charset='
215 information, we will assume the charset matches the one the
216 current locale and we don't have to perform any conversion. */
220 /* Preinitialize fields, to avoid recursion during _nl_find_msg. */
221 domain->codeset_cntr =
222 (domainbinding != NULL ? domainbinding->codeset_cntr : 0);
224 domain->conv = (__gconv_t) -1;
227 domain->conv = (iconv_t) -1;
230 domain->conv_tab = NULL;
232 /* Get the header entry. */
233 nullentry = _nl_find_msg (domain_file, domainbinding, "", &nullentrylen);
235 if (nullentry != NULL)
237 #if defined _LIBC || HAVE_ICONV
238 const char *charsetstr;
240 charsetstr = strstr (nullentry, "charset=");
241 if (charsetstr != NULL)
245 const char *outcharset;
247 charsetstr += strlen ("charset=");
248 len = strcspn (charsetstr, " \t\n");
250 charset = (char *) alloca (len + 1);
251 # if defined _LIBC || HAVE_MEMPCPY
252 *((char *) mempcpy (charset, charsetstr, len)) = '\0';
254 memcpy (charset, charsetstr, len);
258 /* The output charset should normally be determined by the
259 locale. But sometimes the locale is not used or not correctly
260 set up, so we provide a possibility for the user to override
261 this. Moreover, the value specified through
262 bind_textdomain_codeset overrides both. */
263 if (domainbinding != NULL && domainbinding->codeset != NULL)
264 outcharset = domainbinding->codeset;
267 outcharset = getenv ("OUTPUT_CHARSET");
268 if (outcharset == NULL || outcharset[0] == '\0')
271 outcharset = (*_nl_current[LC_CTYPE])->values[_NL_ITEM_INDEX (CODESET)].string;
274 extern const char *locale_charset (void);
275 outcharset = locale_charset ();
282 /* We always want to use transliteration. */
283 outcharset = norm_add_slashes (outcharset, "TRANSLIT");
284 charset = norm_add_slashes (charset, NULL);
285 if (__gconv_open (outcharset, charset, &domain->conv,
288 domain->conv = (__gconv_t) -1;
291 /* When using GNU libiconv, we want to use transliteration. */
292 # if _LIBICONV_VERSION >= 0x0105
293 len = strlen (outcharset);
295 char *tmp = (char *) alloca (len + 10 + 1);
296 memcpy (tmp, outcharset, len);
297 memcpy (tmp + len, "//TRANSLIT", 10 + 1);
301 domain->conv = iconv_open (outcharset, charset);
302 # if _LIBICONV_VERSION >= 0x0105
310 #endif /* _LIBC || HAVE_ICONV */
316 /* Frees the codeset dependent parts of an opened message catalog. */
319 _nl_free_domain_conv (domain)
320 struct loaded_domain *domain;
322 if (domain->conv_tab != NULL && domain->conv_tab != (char **) -1)
323 free (domain->conv_tab);
326 if (domain->conv != (__gconv_t) -1)
327 __gconv_close (domain->conv);
330 if (domain->conv != (iconv_t) -1)
331 iconv_close (domain->conv);
336 /* Load the message catalogs specified by FILENAME. If it is no valid
337 message catalog do nothing. */
340 _nl_load_domain (domain_file, domainbinding)
341 struct loaded_l10nfile *domain_file;
342 struct binding *domainbinding;
351 struct mo_file_header *data = (struct mo_file_header *) -1;
353 struct loaded_domain *domain;
354 const char *nullentry;
356 domain_file->decided = 1;
357 domain_file->data = NULL;
359 /* Note that it would be useless to store domainbinding in domain_file
360 because domainbinding might be == NULL now but != NULL later (after
361 a call to bind_textdomain_codeset). */
363 /* If the record does not represent a valid locale the FILENAME
364 might be NULL. This can happen when according to the given
365 specification the locale file name is different for XPG and CEN
367 if (domain_file->filename == NULL)
370 /* Try to open the addressed file. */
371 fd = open (domain_file->filename, O_RDONLY | O_BINARY);
375 /* We must know about the size of the file. */
378 __builtin_expect (fstat64 (fd, &st) != 0, 0)
380 __builtin_expect (fstat (fd, &st) != 0, 0)
382 || __builtin_expect ((size = (size_t) st.st_size) != st.st_size, 0)
383 || __builtin_expect (size < sizeof (struct mo_file_header), 0))
385 /* Something went wrong. */
391 /* Now we are ready to load the file. If mmap() is available we try
392 this first. If not available or it failed we try to load it. */
393 data = (struct mo_file_header *) mmap (NULL, size, PROT_READ,
396 if (__builtin_expect (data != (struct mo_file_header *) -1, 1))
398 /* mmap() call was successful. */
404 /* If the data is not yet available (i.e. mmap'ed) we try to load
406 if (data == (struct mo_file_header *) -1)
411 data = (struct mo_file_header *) malloc (size);
416 read_ptr = (char *) data;
419 long int nb = (long int) read (fd, read_ptr, to_read);
423 if (nb == -1 && errno == EINTR)
437 /* Using the magic number we can test whether it really is a message
439 if (__builtin_expect (data->magic != _MAGIC && data->magic != _MAGIC_SWAPPED,
442 /* The magic number is wrong: not a message catalog file. */
445 munmap ((caddr_t) data, size);
452 domain = (struct loaded_domain *) malloc (sizeof (struct loaded_domain));
455 domain_file->data = domain;
457 domain->data = (char *) data;
458 domain->use_mmap = use_mmap;
459 domain->mmap_size = size;
460 domain->must_swap = data->magic != _MAGIC;
462 /* Fill in the information about the available tables. */
463 switch (W (domain->must_swap, data->revision))
466 domain->nstrings = W (domain->must_swap, data->nstrings);
467 domain->orig_tab = (struct string_desc *)
468 ((char *) data + W (domain->must_swap, data->orig_tab_offset));
469 domain->trans_tab = (struct string_desc *)
470 ((char *) data + W (domain->must_swap, data->trans_tab_offset));
471 domain->hash_size = W (domain->must_swap, data->hash_tab_size);
472 domain->hash_tab = (nls_uint32 *)
473 ((char *) data + W (domain->must_swap, data->hash_tab_offset));
476 /* This is an invalid revision. */
479 munmap ((caddr_t) data, size);
484 domain_file->data = NULL;
488 /* Now initialize the character set converter from the character set
489 the file is encoded with (found in the header entry) to the domain's
490 specified character set or the locale's character set. */
491 nullentry = _nl_init_domain_conv (domain_file, domain, domainbinding);
493 /* Also look for a plural specification. */
494 if (nullentry != NULL)
497 const char *nplurals;
499 plural = strstr (nullentry, "plural=");
500 nplurals = strstr (nullentry, "nplurals=");
501 if (plural == NULL || nplurals == NULL)
505 /* First get the number. */
508 struct parse_args args;
511 while (*nplurals != '\0' && isspace ((unsigned char) *nplurals))
513 #if defined HAVE_STRTOUL || defined _LIBC
514 n = strtoul (nplurals, &endp, 10);
516 for (endp = nplurals, n = 0; *endp >= '0' && *endp <= '9'; endp++)
517 n = n * 10 + (*endp - '0');
519 domain->nplurals = n;
520 if (nplurals == endp)
523 /* Due to the restrictions bison imposes onto the interface of the
524 scanner function we have to put the input string and the result
525 passed up from the parser into the same structure which address
526 is passed down to the parser. */
529 if (PLURAL_PARSE (&args) != 0)
531 domain->plural = args.res;
536 /* By default we are using the Germanic form: singular form only
537 for `one', the plural form otherwise. Yes, this is also what
538 English is using since English is a Germanic language. */
540 INIT_GERMANIC_PLURAL ();
541 domain->plural = &germanic_plural;
542 domain->nplurals = 2;
550 _nl_unload_domain (domain)
551 struct loaded_domain *domain;
553 if (domain->plural != &germanic_plural)
554 __gettext_free_exp (domain->plural);
556 _nl_free_domain_conv (domain);
558 # ifdef _POSIX_MAPPED_FILES
559 if (domain->use_mmap)
560 munmap ((caddr_t) domain->data, domain->mmap_size);
562 # endif /* _POSIX_MAPPED_FILES */
563 free ((void *) domain->data);