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_FILE && !defined DISALLOW_MMAP) \
66 || (defined _LIBC && defined _POSIX_MAPPED_FILES)
67 # include <sys/mman.h>
78 # include "../locale/localeinfo.h"
81 /* GCC LOCAL: These macros are used below. */
82 /* The extra casts work around common compiler bugs. */
83 #define INTTYPE_SIGNED(t) (! ((t) 0 < (t) -1))
84 /* The outer cast is needed to work around a bug in Cray C 5.0.3.0.
85 It is necessary at least when t == time_t. */
86 #define INTTYPE_MINIMUM(t) ((t) (INTTYPE_SIGNED (t) \
87 ? ~ (t) 0 << (sizeof(t) * CHAR_BIT - 1) : (t) 0))
88 #define INTTYPE_MAXIMUM(t) ((t) (~ (t) 0 - INTTYPE_MINIMUM (t)))
90 /* @@ end of prolog @@ */
93 /* Rename the non ISO C functions. This is required by the standard
94 because some ISO C functions will require linking with this object
95 file and the name space must not be polluted. */
97 # define close __close
100 # define munmap __munmap
103 /* Names for the libintl functions are a problem. They must not clash
104 with existing names and they should follow ANSI C. But this source
105 code is also used in GNU C Library where the names have a __
106 prefix. So we have to make a difference here. */
108 # define PLURAL_PARSE __gettextparse
110 # define PLURAL_PARSE gettextparse__
113 /* For those losing systems which don't have `alloca' we have to add
114 some additional code emulating it. */
116 # define freea(p) /* nothing */
118 # define alloca(n) malloc (n)
119 # define freea(p) free (p)
122 /* For systems that distinguish between text and binary I/O.
123 O_BINARY is usually declared in <fcntl.h>. */
124 #if !defined O_BINARY && defined _O_BINARY
125 /* For MSC-compatible compilers. */
126 # define O_BINARY _O_BINARY
127 # define O_TEXT _O_TEXT
130 /* BeOS 5 has O_BINARY and O_TEXT, but they have no effect. */
134 /* On reasonable systems, binary I/O is the default. */
139 /* We need a sign, whether a new catalog was loaded, which can be associated
140 with all translations. This is important if the translations are
141 cached by one of GCC's features. */
142 int _nl_msg_cat_cntr
;
144 #if (defined __GNUC__ && !defined __APPLE_CC__) \
145 || (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L)
147 /* These structs are the constant expression for the germanic plural
148 form determination. It represents the expression "n != 1".
149 GCC LOCAL: Use __extension__ to suppress -Wtraditional warnings. */
150 __extension__
static const struct expression plvar
=
155 __extension__
static const struct expression plone
=
164 __extension__
static struct expression germanic_plural
=
167 .operation
= not_equal
,
172 [0] = (struct expression
*) &plvar
,
173 [1] = (struct expression
*) &plone
178 # define INIT_GERMANIC_PLURAL()
182 /* For compilers without support for ISO C 99 struct/union initializers:
183 Initialization at run-time. */
185 static struct expression plvar
;
186 static struct expression plone
;
187 static struct expression germanic_plural
;
190 init_germanic_plural ()
192 if (plone
.val
.num
== 0)
195 plvar
.operation
= var
;
198 plone
.operation
= num
;
201 germanic_plural
.nargs
= 2;
202 germanic_plural
.operation
= not_equal
;
203 germanic_plural
.val
.args
[0] = &plvar
;
204 germanic_plural
.val
.args
[1] = &plone
;
208 # define INIT_GERMANIC_PLURAL() init_germanic_plural ()
213 /* Initialize the codeset dependent parts of an opened message catalog.
214 Return the header entry. */
217 _nl_init_domain_conv (domain_file
, domain
, domainbinding
)
218 struct loaded_l10nfile
*domain_file
;
219 struct loaded_domain
*domain
;
220 struct binding
*domainbinding
;
222 /* Find out about the character set the file is encoded with.
223 This can be found (in textual form) in the entry "". If this
224 entry does not exist or if this does not contain the `charset='
225 information, we will assume the charset matches the one the
226 current locale and we don't have to perform any conversion. */
230 /* Preinitialize fields, to avoid recursion during _nl_find_msg. */
231 domain
->codeset_cntr
=
232 (domainbinding
!= NULL
? domainbinding
->codeset_cntr
: 0);
234 domain
->conv
= (__gconv_t
) -1;
237 domain
->conv
= (iconv_t
) -1;
240 domain
->conv_tab
= NULL
;
242 /* Get the header entry. */
243 nullentry
= _nl_find_msg (domain_file
, domainbinding
, "", &nullentrylen
);
245 if (nullentry
!= NULL
)
247 #if defined _LIBC || HAVE_ICONV
248 const char *charsetstr
;
250 charsetstr
= strstr (nullentry
, "charset=");
251 if (charsetstr
!= NULL
)
255 const char *outcharset
;
257 charsetstr
+= strlen ("charset=");
258 len
= strcspn (charsetstr
, " \t\n");
260 charset
= (char *) alloca (len
+ 1);
261 # if defined _LIBC || HAVE_MEMPCPY
262 *((char *) mempcpy (charset
, charsetstr
, len
)) = '\0';
264 memcpy (charset
, charsetstr
, len
);
268 /* The output charset should normally be determined by the
269 locale. But sometimes the locale is not used or not correctly
270 set up, so we provide a possibility for the user to override
271 this. Moreover, the value specified through
272 bind_textdomain_codeset overrides both. */
273 if (domainbinding
!= NULL
&& domainbinding
->codeset
!= NULL
)
274 outcharset
= domainbinding
->codeset
;
277 outcharset
= getenv ("OUTPUT_CHARSET");
278 if (outcharset
== NULL
|| outcharset
[0] == '\0')
281 outcharset
= (*_nl_current
[LC_CTYPE
])->values
[_NL_ITEM_INDEX (CODESET
)].string
;
284 outcharset
= locale_charset ();
291 /* We always want to use transliteration. */
292 outcharset
= norm_add_slashes (outcharset
, "TRANSLIT");
293 charset
= norm_add_slashes (charset
, NULL
);
294 if (__gconv_open (outcharset
, charset
, &domain
->conv
,
297 domain
->conv
= (__gconv_t
) -1;
300 /* When using GNU libiconv, we want to use transliteration. */
301 # if _LIBICONV_VERSION >= 0x0105
302 len
= strlen (outcharset
);
304 char *tmp
= (char *) alloca (len
+ 10 + 1);
305 memcpy (tmp
, outcharset
, len
);
306 memcpy (tmp
+ len
, "//TRANSLIT", 10 + 1);
310 domain
->conv
= iconv_open (outcharset
, charset
);
311 # if _LIBICONV_VERSION >= 0x0105
319 #endif /* _LIBC || HAVE_ICONV */
325 /* Frees the codeset dependent parts of an opened message catalog. */
328 _nl_free_domain_conv (domain
)
329 struct loaded_domain
*domain
;
331 if (domain
->conv_tab
!= NULL
&& domain
->conv_tab
!= (char **) -1)
332 free (domain
->conv_tab
);
335 if (domain
->conv
!= (__gconv_t
) -1)
336 __gconv_close (domain
->conv
);
339 if (domain
->conv
!= (iconv_t
) -1)
340 iconv_close (domain
->conv
);
345 /* Load the message catalogs specified by FILENAME. If it is no valid
346 message catalog do nothing. */
349 _nl_load_domain (domain_file
, domainbinding
)
350 struct loaded_l10nfile
*domain_file
;
351 struct binding
*domainbinding
;
360 struct mo_file_header
*data
= (struct mo_file_header
*) -1;
362 struct loaded_domain
*domain
;
363 const char *nullentry
;
365 domain_file
->decided
= 1;
366 domain_file
->data
= NULL
;
368 /* Note that it would be useless to store domainbinding in domain_file
369 because domainbinding might be == NULL now but != NULL later (after
370 a call to bind_textdomain_codeset). */
372 /* If the record does not represent a valid locale the FILENAME
373 might be NULL. This can happen when according to the given
374 specification the locale file name is different for XPG and CEN
376 if (domain_file
->filename
== NULL
)
379 /* Try to open the addressed file. */
380 fd
= open (domain_file
->filename
, O_RDONLY
| O_BINARY
);
384 /* We must know about the size of the file. */
385 /* GCC_LOCAL: Use INTTYPE_MAXIMUM for overflow check, cast sizeof to
386 off_t, move set of size below if. */
389 __builtin_expect (fstat64 (fd
, &st
) != 0, 0)
391 __builtin_expect (fstat (fd
, &st
) != 0, 0)
393 || __builtin_expect (st
.st_size
> INTTYPE_MAXIMUM (ssize_t
), 0)
394 || __builtin_expect (st
.st_size
< (off_t
) sizeof (struct mo_file_header
),
397 /* Something went wrong. */
401 size
= (size_t) st
.st_size
;
404 /* Now we are ready to load the file. If mmap() is available we try
405 this first. If not available or it failed we try to load it. */
406 data
= (struct mo_file_header
*) mmap (NULL
, size
, PROT_READ
,
409 if (__builtin_expect (data
!= (struct mo_file_header
*) -1, 1))
411 /* mmap() call was successful. */
417 /* If the data is not yet available (i.e. mmap'ed) we try to load
419 if (data
== (struct mo_file_header
*) -1)
424 data
= (struct mo_file_header
*) malloc (size
);
429 read_ptr
= (char *) data
;
432 long int nb
= (long int) read (fd
, read_ptr
, to_read
);
436 if (nb
== -1 && errno
== EINTR
)
450 /* Using the magic number we can test whether it really is a message
452 if (__builtin_expect (data
->magic
!= _MAGIC
&& data
->magic
!= _MAGIC_SWAPPED
,
455 /* The magic number is wrong: not a message catalog file. */
458 munmap ((caddr_t
) data
, size
);
465 domain
= (struct loaded_domain
*) malloc (sizeof (struct loaded_domain
));
468 domain_file
->data
= domain
;
470 domain
->data
= (char *) data
;
471 domain
->use_mmap
= use_mmap
;
472 domain
->mmap_size
= size
;
473 domain
->must_swap
= data
->magic
!= _MAGIC
;
475 /* Fill in the information about the available tables. */
476 switch (W (domain
->must_swap
, data
->revision
))
479 domain
->nstrings
= W (domain
->must_swap
, data
->nstrings
);
480 domain
->orig_tab
= (struct string_desc
*)
481 ((char *) data
+ W (domain
->must_swap
, data
->orig_tab_offset
));
482 domain
->trans_tab
= (struct string_desc
*)
483 ((char *) data
+ W (domain
->must_swap
, data
->trans_tab_offset
));
484 domain
->hash_size
= W (domain
->must_swap
, data
->hash_tab_size
);
485 domain
->hash_tab
= (nls_uint32
*)
486 ((char *) data
+ W (domain
->must_swap
, data
->hash_tab_offset
));
489 /* This is an invalid revision. */
492 munmap ((caddr_t
) data
, size
);
497 domain_file
->data
= NULL
;
501 /* Now initialize the character set converter from the character set
502 the file is encoded with (found in the header entry) to the domain's
503 specified character set or the locale's character set. */
504 nullentry
= _nl_init_domain_conv (domain_file
, domain
, domainbinding
);
506 /* Also look for a plural specification. */
507 if (nullentry
!= NULL
)
510 const char *nplurals
;
512 plural
= strstr (nullentry
, "plural=");
513 nplurals
= strstr (nullentry
, "nplurals=");
514 if (plural
== NULL
|| nplurals
== NULL
)
518 /* First get the number. */
521 struct parse_args args
;
524 while (*nplurals
!= '\0' && isspace ((unsigned char)*nplurals
))
526 #if defined HAVE_STRTOUL || defined _LIBC
527 n
= strtoul (nplurals
, &endp
, 10);
529 for (endp
= nplurals
, n
= 0; *endp
>= '0' && *endp
<= '9'; endp
++)
530 n
= n
* 10 + (*endp
- '0');
532 domain
->nplurals
= n
;
533 if (nplurals
== endp
)
536 /* Due to the restrictions bison imposes onto the interface of the
537 scanner function we have to put the input string and the result
538 passed up from the parser into the same structure which address
539 is passed down to the parser. */
542 if (PLURAL_PARSE (&args
) != 0)
544 domain
->plural
= args
.res
;
549 /* By default we are using the Germanic form: singular form only
550 for `one', the plural form otherwise. Yes, this is also what
551 English is using since English is a Germanic language. */
553 INIT_GERMANIC_PLURAL ();
554 domain
->plural
= &germanic_plural
;
555 domain
->nplurals
= 2;
563 _nl_unload_domain (domain
)
564 struct loaded_domain
*domain
;
566 if (domain
->plural
!= &germanic_plural
)
567 __gettext_free_exp (domain
->plural
);
569 _nl_free_domain_conv (domain
);
571 # ifdef _POSIX_MAPPED_FILES
572 if (domain
->use_mmap
)
573 munmap ((caddr_t
) domain
->data
, domain
->mmap_size
);
575 # endif /* _POSIX_MAPPED_FILES */
576 free ((void *) domain
->data
);