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>
36 #if defined STDC_HEADERS || defined _LIBC
40 #if defined HAVE_STRING_H || defined _LIBC
46 #if defined HAVE_UNISTD_H || defined _LIBC
51 # include <langinfo.h>
55 #if (defined HAVE_MMAP && defined HAVE_MUNMAP && !defined DISALLOW_MMAP) \
56 || (defined _LIBC && defined _POSIX_MAPPED_FILES)
57 # include <sys/mman.h>
68 # include "../locale/localeinfo.h"
71 /* @@ end of prolog @@ */
74 /* Rename the non ISO C functions. This is required by the standard
75 because some ISO C functions will require linking with this object
76 file and the name space must not be polluted. */
78 # define close __close
81 # define munmap __munmap
84 /* We need a sign, whether a new catalog was loaded, which can be associated
85 with all translations. This is important if the translations are
86 cached by one of GCC's features. */
89 #if defined __GNUC__ \
90 || (defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L)
92 /* These structs are the constant expression for the germanic plural
93 form determination. It represents the expression "n != 1". */
94 static const struct expression plvar
=
98 static const struct expression plone
=
106 static struct expression germanic_plural
=
108 .operation
= not_equal
,
113 .left
= (struct expression
*) &plvar
,
114 .right
= (struct expression
*) &plone
119 # define INIT_GERMANIC_PLURAL()
123 /* For compilers without support for ISO C 99 struct/union initializers:
124 Initialization at run-time. */
126 static struct expression plvar
;
127 static struct expression plone
;
128 static struct expression germanic_plural
;
131 init_germanic_plural ()
133 if (plone
.val
.num
== 0)
135 plvar
.operation
= var
;
137 plone
.operation
= num
;
140 germanic_plural
.operation
= not_equal
;
141 germanic_plural
.val
.args2
.left
= &plvar
;
142 germanic_plural
.val
.args2
.right
= &plone
;
146 # define INIT_GERMANIC_PLURAL() init_germanic_plural ()
151 /* Load the message catalogs specified by FILENAME. If it is no valid
152 message catalog do nothing. */
155 _nl_load_domain (domain_file
)
156 struct loaded_l10nfile
*domain_file
;
161 struct mo_file_header
*data
= (struct mo_file_header
*) -1;
163 struct loaded_domain
*domain
;
167 domain_file
->decided
= 1;
168 domain_file
->data
= NULL
;
170 /* If the record does not represent a valid locale the FILENAME
171 might be NULL. This can happen when according to the given
172 specification the locale file name is different for XPG and CEN
174 if (domain_file
->filename
== NULL
)
177 /* Try to open the addressed file. */
178 fd
= open (domain_file
->filename
, O_RDONLY
);
182 /* We must know about the size of the file. */
183 if (__builtin_expect (fstat64 (fd
, &st
) != 0, 0)
184 || __builtin_expect ((size
= (size_t) st
.st_size
) != st
.st_size
, 0)
185 || __builtin_expect (size
< sizeof (struct mo_file_header
), 0))
187 /* Something went wrong. */
193 /* Now we are ready to load the file. If mmap() is available we try
194 this first. If not available or it failed we try to load it. */
195 data
= (struct mo_file_header
*) mmap (NULL
, size
, PROT_READ
,
198 if (__builtin_expect (data
!= (struct mo_file_header
*) -1, 1))
200 /* mmap() call was successful. */
206 /* If the data is not yet available (i.e. mmap'ed) we try to load
208 if (data
== (struct mo_file_header
*) -1)
213 data
= (struct mo_file_header
*) malloc (size
);
218 read_ptr
= (char *) data
;
221 long int nb
= (long int) read (fd
, read_ptr
, to_read
);
225 if (nb
== -1 && errno
== EINTR
)
239 /* Using the magic number we can test whether it really is a message
241 if (__builtin_expect (data
->magic
!= _MAGIC
&& data
->magic
!= _MAGIC_SWAPPED
,
244 /* The magic number is wrong: not a message catalog file. */
247 munmap ((caddr_t
) data
, size
);
254 domain
= (struct loaded_domain
*) malloc (sizeof (struct loaded_domain
));
257 domain_file
->data
= domain
;
259 domain
->data
= (char *) data
;
260 domain
->use_mmap
= use_mmap
;
261 domain
->mmap_size
= size
;
262 domain
->must_swap
= data
->magic
!= _MAGIC
;
264 /* Fill in the information about the available tables. */
265 switch (W (domain
->must_swap
, data
->revision
))
268 domain
->nstrings
= W (domain
->must_swap
, data
->nstrings
);
269 domain
->orig_tab
= (struct string_desc
*)
270 ((char *) data
+ W (domain
->must_swap
, data
->orig_tab_offset
));
271 domain
->trans_tab
= (struct string_desc
*)
272 ((char *) data
+ W (domain
->must_swap
, data
->trans_tab_offset
));
273 domain
->hash_size
= W (domain
->must_swap
, data
->hash_tab_size
);
274 domain
->hash_tab
= (nls_uint32
*)
275 ((char *) data
+ W (domain
->must_swap
, data
->hash_tab_offset
));
278 /* This is an invalid revision. */
281 munmap ((caddr_t
) data
, size
);
286 domain_file
->data
= NULL
;
290 /* Now find out about the character set the file is encoded with.
291 This can be found (in textual form) in the entry "". If this
292 entry does not exist or if this does not contain the `charset='
293 information, we will assume the charset matches the one the
294 current locale and we don't have to perform any conversion. */
296 domain
->conv
= (__gconv_t
) -1;
299 domain
->conv
= (iconv_t
) -1;
302 domain
->conv_tab
= NULL
;
303 nullentry
= _nl_find_msg (domain_file
, "", &nullentrylen
);
304 if (nullentry
!= NULL
)
306 #if defined _LIBC || HAVE_ICONV
307 const char *charsetstr
;
309 charsetstr
= strstr (nullentry
, "charset=");
310 if (charsetstr
!= NULL
)
314 const char *outcharset
;
316 charsetstr
+= strlen ("charset=");
317 len
= strcspn (charsetstr
, " \t\n");
319 charset
= (char *) alloca (len
+ 1);
320 # if defined _LIBC || HAVE_MEMPCPY
321 *((char *) mempcpy (charset
, charsetstr
, len
)) = '\0';
323 memcpy (charset
, charsetstr
, len
);
327 /* The output charset should normally be determined by the
328 locale. But sometimes the locale is not used or not correctly
329 set up, so we provide a possibility for the user to override
330 this. Moreover, the value specified through
331 bind_textdomain_codeset overrides both. */
332 if (domain_file
->domainbinding
!= NULL
333 && domain_file
->domainbinding
->codeset
!= NULL
)
334 outcharset
= domain_file
->domainbinding
->codeset
;
337 outcharset
= getenv ("OUTPUT_CHARSET");
338 if (outcharset
== NULL
|| outcharset
[0] == '\0')
341 outcharset
= (*_nl_current
[LC_CTYPE
])->values
[_NL_ITEM_INDEX (CODESET
)].string
;
344 extern const char *locale_charset (void);
345 outcharset
= locale_charset ();
346 if (outcharset
== NULL
)
354 /* We always want to use transliteration. */
355 outcharset
= norm_add_slashes (outcharset
, "TRANSLIT");
356 charset
= norm_add_slashes (charset
, NULL
);
357 if (__gconv_open (outcharset
, charset
, &domain
->conv
,
360 domain
->conv
= (__gconv_t
) -1;
363 domain
->conv
= iconv_open (outcharset
, charset
);
367 #endif /* _LIBC || HAVE_ICONV */
370 /* Also look for a plural specification. */
371 if (nullentry
!= NULL
)
374 const char *nplurals
;
376 plural
= strstr (nullentry
, "plural=");
377 nplurals
= strstr (nullentry
, "nplurals=");
378 if (plural
== NULL
|| nplurals
== NULL
)
382 /* First get the number. */
384 struct parse_args args
;
387 while (*nplurals
!= '\0' && isspace (*nplurals
))
389 domain
->nplurals
= strtoul (nplurals
, &endp
, 10);
390 if (nplurals
== endp
)
393 /* Due to the restrictions bison imposes onto the interface of the
394 scanner function we have to put the input string and the result
395 passed up from the parser into the same structure which address
396 is passed down to the parser. */
399 if (__gettextparse (&args
) != 0)
401 domain
->plural
= args
.res
;
406 /* By default we are using the Germanic form: singular form only
407 for `one', the plural form otherwise. Yes, this is also what
408 English is using since English is a Germanic language. */
410 INIT_GERMANIC_PLURAL ();
411 domain
->plural
= &germanic_plural
;
412 domain
->nplurals
= 2;
420 _nl_unload_domain (domain
)
421 struct loaded_domain
*domain
;
423 if (domain
->plural
!= &germanic_plural
)
424 __gettext_free_exp (domain
->plural
);
426 if (domain
->conv_tab
!= NULL
&& domain
->conv_tab
!= (char **) -1)
427 free (domain
->conv_tab
);
429 if (domain
->conv
!= (__gconv_t
) -1)
430 __gconv_close (domain
->conv
);
432 # ifdef _POSIX_MAPPED_FILES
433 if (domain
->use_mmap
)
434 munmap ((caddr_t
) domain
->data
, domain
->mmap_size
);
436 # endif /* _POSIX_MAPPED_FILES */
437 free ((void *) domain
->data
);