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 (*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);