1 /* Load needed message catalogs.
2 Copyright (C) 1995-1999, 2000, 2001 Free Software Foundation, Inc.
4 The GNU C Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public License as
6 published by the Free Software Foundation; either version 2 of the
7 License, or (at your option) any later version.
9 The GNU C Library 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 the GNU C Library; see the file COPYING.LIB. If not,
16 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 Boston, MA 02111-1307, USA. */
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
53 #if defined STDC_HEADERS || defined _LIBC
57 #if defined HAVE_STRING_H || defined _LIBC
63 #if defined HAVE_UNISTD_H || defined _LIBC
68 # include <langinfo.h>
72 #if (defined HAVE_MMAP && defined HAVE_MUNMAP && !defined DISALLOW_MMAP) \
73 || (defined _LIBC && defined _POSIX_MAPPED_FILES)
74 # include <sys/mman.h>
85 # include "../locale/localeinfo.h"
88 /* @@ end of prolog @@ */
91 /* Rename the non ISO C functions. This is required by the standard
92 because some ISO C functions will require linking with this object
93 file and the name space must not be polluted. */
95 # define close __close
98 # define munmap __munmap
101 /* Names for the libintl functions are a problem. They must not clash
102 with existing names and they should follow ANSI C. But this source
103 code is also used in GNU C Library where the names have a __
104 prefix. So we have to make a difference here. */
106 # define PLURAL_PARSE __gettextparse
108 # define PLURAL_PARSE gettextparse__
111 /* For those losing systems which don't have `alloca' we have to add
112 some additional code emulating it. */
114 # define freea(p) /* nothing */
116 # define alloca(n) malloc (n)
117 # define freea(p) free (p)
120 /* We need a sign, whether a new catalog was loaded, which can be associated
121 with all translations. This is important if the translations are
122 cached by one of GCC's features. */
123 int _nl_msg_cat_cntr
;
125 #if defined __GNUC__ \
126 || (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L)
128 /* These structs are the constant expression for the germanic plural
129 form determination. It represents the expression "n != 1". */
130 static const struct expression plvar
=
135 static const struct expression plone
=
144 static struct expression germanic_plural
=
147 .operation
= not_equal
,
152 [0] = (struct expression
*) &plvar
,
153 [1] = (struct expression
*) &plone
158 # define INIT_GERMANIC_PLURAL()
162 /* For compilers without support for ISO C 99 struct/union initializers:
163 Initialization at run-time. */
165 static struct expression plvar
;
166 static struct expression plone
;
167 static struct expression germanic_plural
;
170 init_germanic_plural ()
172 if (plone
.val
.num
== 0)
175 plvar
.operation
= var
;
178 plone
.operation
= num
;
181 germanic_plural
.nargs
= 2;
182 germanic_plural
.operation
= not_equal
;
183 germanic_plural
.val
.args
[0] = &plvar
;
184 germanic_plural
.val
.args
[1] = &plone
;
188 # define INIT_GERMANIC_PLURAL() init_germanic_plural ()
193 /* Initialize the codeset dependent parts of an opened message catalog.
194 Return the header entry. */
197 _nl_init_domain_conv (domain_file
, domain
, domainbinding
)
198 struct loaded_l10nfile
*domain_file
;
199 struct loaded_domain
*domain
;
200 struct binding
*domainbinding
;
202 /* Find out about the character set the file is encoded with.
203 This can be found (in textual form) in the entry "". If this
204 entry does not exist or if this does not contain the `charset='
205 information, we will assume the charset matches the one the
206 current locale and we don't have to perform any conversion. */
210 /* Preinitialize fields, to avoid recursion during _nl_find_msg. */
211 domain
->codeset_cntr
=
212 (domainbinding
!= NULL
? domainbinding
->codeset_cntr
: 0);
214 domain
->conv
= (__gconv_t
) -1;
217 domain
->conv
= (iconv_t
) -1;
220 domain
->conv_tab
= NULL
;
222 /* Get the header entry. */
223 nullentry
= _nl_find_msg (domain_file
, domainbinding
, "", &nullentrylen
);
225 if (nullentry
!= NULL
)
227 #if defined _LIBC || HAVE_ICONV
228 const char *charsetstr
;
230 charsetstr
= strstr (nullentry
, "charset=");
231 if (charsetstr
!= NULL
)
235 const char *outcharset
;
237 charsetstr
+= strlen ("charset=");
238 len
= strcspn (charsetstr
, " \t\n");
240 charset
= (char *) alloca (len
+ 1);
241 # if defined _LIBC || HAVE_MEMPCPY
242 *((char *) mempcpy (charset
, charsetstr
, len
)) = '\0';
244 memcpy (charset
, charsetstr
, len
);
248 /* The output charset should normally be determined by the
249 locale. But sometimes the locale is not used or not correctly
250 set up, so we provide a possibility for the user to override
251 this. Moreover, the value specified through
252 bind_textdomain_codeset overrides both. */
253 if (domainbinding
!= NULL
&& domainbinding
->codeset
!= NULL
)
254 outcharset
= domainbinding
->codeset
;
257 outcharset
= getenv ("OUTPUT_CHARSET");
258 if (outcharset
== NULL
|| outcharset
[0] == '\0')
261 outcharset
= (*_nl_current
[LC_CTYPE
])->values
[_NL_ITEM_INDEX (CODESET
)].string
;
264 extern const char *locale_charset (void);
265 outcharset
= locale_charset ();
272 /* We always want to use transliteration. */
273 outcharset
= norm_add_slashes (outcharset
, "TRANSLIT");
274 charset
= norm_add_slashes (charset
, NULL
);
275 if (__gconv_open (outcharset
, charset
, &domain
->conv
,
278 domain
->conv
= (__gconv_t
) -1;
281 /* When using GNU libiconv, we want to use transliteration. */
282 # if _LIBICONV_VERSION
283 len
= strlen (outcharset
);
285 char *tmp
= (char *) alloca (len
+ 10 + 1);
286 memcpy (tmp
, outcharset
, len
);
287 memcpy (tmp
+ len
, "//TRANSLIT", 10 + 1);
291 domain
->conv
= iconv_open (outcharset
, charset
);
292 # if _LIBICONV_VERSION
300 #endif /* _LIBC || HAVE_ICONV */
306 /* Frees the codeset dependent parts of an opened message catalog. */
309 _nl_free_domain_conv (domain
)
310 struct loaded_domain
*domain
;
312 if (domain
->conv_tab
!= NULL
&& domain
->conv_tab
!= (char **) -1)
313 free (domain
->conv_tab
);
316 if (domain
->conv
!= (__gconv_t
) -1)
317 __gconv_close (domain
->conv
);
320 if (domain
->conv
!= (iconv_t
) -1)
321 iconv_close (domain
->conv
);
326 /* Load the message catalogs specified by FILENAME. If it is no valid
327 message catalog do nothing. */
330 _nl_load_domain (domain_file
, domainbinding
)
331 struct loaded_l10nfile
*domain_file
;
332 struct binding
*domainbinding
;
341 struct mo_file_header
*data
= (struct mo_file_header
*) -1;
343 struct loaded_domain
*domain
;
344 const char *nullentry
;
346 domain_file
->decided
= 1;
347 domain_file
->data
= NULL
;
349 /* Note that it would be useless to store domainbinding in domain_file
350 because domainbinding might be == NULL now but != NULL later (after
351 a call to bind_textdomain_codeset). */
353 /* If the record does not represent a valid locale the FILENAME
354 might be NULL. This can happen when according to the given
355 specification the locale file name is different for XPG and CEN
357 if (domain_file
->filename
== NULL
)
360 /* Try to open the addressed file. */
361 fd
= open (domain_file
->filename
, O_RDONLY
);
365 /* We must know about the size of the file. */
368 __builtin_expect (fstat64 (fd
, &st
) != 0, 0)
370 __builtin_expect (fstat (fd
, &st
) != 0, 0)
372 || __builtin_expect ((size
= (size_t) st
.st_size
) != st
.st_size
, 0)
373 || __builtin_expect (size
< sizeof (struct mo_file_header
), 0))
375 /* Something went wrong. */
381 /* Now we are ready to load the file. If mmap() is available we try
382 this first. If not available or it failed we try to load it. */
383 data
= (struct mo_file_header
*) mmap (NULL
, size
, PROT_READ
,
386 if (__builtin_expect (data
!= (struct mo_file_header
*) -1, 1))
388 /* mmap() call was successful. */
394 /* If the data is not yet available (i.e. mmap'ed) we try to load
396 if (data
== (struct mo_file_header
*) -1)
401 data
= (struct mo_file_header
*) malloc (size
);
406 read_ptr
= (char *) data
;
409 long int nb
= (long int) read (fd
, read_ptr
, to_read
);
413 if (nb
== -1 && errno
== EINTR
)
427 /* Using the magic number we can test whether it really is a message
429 if (__builtin_expect (data
->magic
!= _MAGIC
&& data
->magic
!= _MAGIC_SWAPPED
,
432 /* The magic number is wrong: not a message catalog file. */
435 munmap ((caddr_t
) data
, size
);
442 domain
= (struct loaded_domain
*) malloc (sizeof (struct loaded_domain
));
445 domain_file
->data
= domain
;
447 domain
->data
= (char *) data
;
448 domain
->use_mmap
= use_mmap
;
449 domain
->mmap_size
= size
;
450 domain
->must_swap
= data
->magic
!= _MAGIC
;
452 /* Fill in the information about the available tables. */
453 switch (W (domain
->must_swap
, data
->revision
))
456 domain
->nstrings
= W (domain
->must_swap
, data
->nstrings
);
457 domain
->orig_tab
= (struct string_desc
*)
458 ((char *) data
+ W (domain
->must_swap
, data
->orig_tab_offset
));
459 domain
->trans_tab
= (struct string_desc
*)
460 ((char *) data
+ W (domain
->must_swap
, data
->trans_tab_offset
));
461 domain
->hash_size
= W (domain
->must_swap
, data
->hash_tab_size
);
462 domain
->hash_tab
= (nls_uint32
*)
463 ((char *) data
+ W (domain
->must_swap
, data
->hash_tab_offset
));
466 /* This is an invalid revision. */
469 munmap ((caddr_t
) data
, size
);
474 domain_file
->data
= NULL
;
478 /* Now initialize the character set converter from the character set
479 the file is encoded with (found in the header entry) to the domain's
480 specified character set or the locale's character set. */
481 nullentry
= _nl_init_domain_conv (domain_file
, domain
, domainbinding
);
483 /* Also look for a plural specification. */
484 if (nullentry
!= NULL
)
487 const char *nplurals
;
489 plural
= strstr (nullentry
, "plural=");
490 nplurals
= strstr (nullentry
, "nplurals=");
491 if (plural
== NULL
|| nplurals
== NULL
)
495 /* First get the number. */
498 struct parse_args args
;
501 while (*nplurals
!= '\0' && isspace (*nplurals
))
503 #if defined HAVE_STRTOUL || defined _LIBC
504 n
= strtoul (nplurals
, &endp
, 10);
506 for (endp
= nplurals
, n
= 0; *endp
>= '0' && *endp
<= '9'; endp
++)
507 n
= n
* 10 + (*endp
- '0');
509 domain
->nplurals
= n
;
510 if (nplurals
== endp
)
513 /* Due to the restrictions bison imposes onto the interface of the
514 scanner function we have to put the input string and the result
515 passed up from the parser into the same structure which address
516 is passed down to the parser. */
519 if (PLURAL_PARSE (&args
) != 0)
521 domain
->plural
= args
.res
;
526 /* By default we are using the Germanic form: singular form only
527 for `one', the plural form otherwise. Yes, this is also what
528 English is using since English is a Germanic language. */
530 INIT_GERMANIC_PLURAL ();
531 domain
->plural
= &germanic_plural
;
532 domain
->nplurals
= 2;
540 _nl_unload_domain (domain
)
541 struct loaded_domain
*domain
;
543 if (domain
->plural
!= &germanic_plural
)
544 __gettext_free_exp (domain
->plural
);
546 _nl_free_domain_conv (domain
);
548 # ifdef _POSIX_MAPPED_FILES
549 if (domain
->use_mmap
)
550 munmap ((caddr_t
) domain
->data
, domain
->mmap_size
);
552 # endif /* _POSIX_MAPPED_FILES */
553 free ((void *) domain
->data
);