* sysdeps/m68k/fpu/bits/mathinline.h: Don't define log2 as inline.
[glibc.git] / intl / loadmsgcat.c
blobb7b237bc70a3537aa81f27fd7e365b7ddb0230a6
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. */
22 #ifndef _GNU_SOURCE
23 # define _GNU_SOURCE 1
24 #endif
26 #ifdef HAVE_CONFIG_H
27 # include <config.h>
28 #endif
30 #include <ctype.h>
31 #include <errno.h>
32 #include <fcntl.h>
33 #include <sys/types.h>
34 #include <sys/stat.h>
36 #ifdef __GNUC__
37 # define alloca __builtin_alloca
38 # define HAVE_ALLOCA 1
39 #else
40 # if defined HAVE_ALLOCA_H || defined _LIBC
41 # include <alloca.h>
42 # else
43 # ifdef _AIX
44 #pragma alloca
45 # else
46 # ifndef alloca
47 char *alloca ();
48 # endif
49 # endif
50 # endif
51 #endif
53 #if defined STDC_HEADERS || defined _LIBC
54 # include <stdlib.h>
55 #endif
57 #if defined HAVE_STRING_H || defined _LIBC
58 # include <string.h>
59 #else
60 # include <strings.h>
61 #endif
63 #if defined HAVE_UNISTD_H || defined _LIBC
64 # include <unistd.h>
65 #endif
67 #ifdef _LIBC
68 # include <langinfo.h>
69 # include <locale.h>
70 #endif
72 #if (defined HAVE_MMAP && defined HAVE_MUNMAP && !defined DISALLOW_MMAP) \
73 || (defined _LIBC && defined _POSIX_MAPPED_FILES)
74 # include <sys/mman.h>
75 # undef HAVE_MMAP
76 # define HAVE_MMAP 1
77 #else
78 # undef HAVE_MMAP
79 #endif
81 #include "gettext.h"
82 #include "gettextP.h"
84 #ifdef _LIBC
85 # include "../locale/localeinfo.h"
86 #endif
88 /* @@ end of prolog @@ */
90 #ifdef _LIBC
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. */
94 # define open __open
95 # define close __close
96 # define read __read
97 # define mmap __mmap
98 # define munmap __munmap
99 #endif
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. */
105 #ifdef _LIBC
106 # define PLURAL_PARSE __gettextparse
107 #else
108 # define PLURAL_PARSE gettextparse__
109 #endif
111 /* For those losing systems which don't have `alloca' we have to add
112 some additional code emulating it. */
113 #ifdef HAVE_ALLOCA
114 # define freea(p) /* nothing */
115 #else
116 # define alloca(n) malloc (n)
117 # define freea(p) free (p)
118 #endif
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 =
132 .nargs = 0,
133 .operation = var,
135 static const struct expression plone =
137 .nargs = 0,
138 .operation = num,
139 .val =
141 .num = 1
144 static struct expression germanic_plural =
146 .nargs = 2,
147 .operation = not_equal,
148 .val =
150 .args =
152 [0] = (struct expression *) &plvar,
153 [1] = (struct expression *) &plone
158 # define INIT_GERMANIC_PLURAL()
160 #else
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;
169 static void
170 init_germanic_plural ()
172 if (plone.val.num == 0)
174 plvar.nargs = 0;
175 plvar.operation = var;
177 plone.nargs = 0;
178 plone.operation = num;
179 plone.val.num = 1;
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 ()
190 #endif
193 /* Initialize the codeset dependent parts of an opened message catalog.
194 Return the header entry. */
195 const char *
196 internal_function
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. */
207 char *nullentry;
208 size_t nullentrylen;
210 /* Preinitialize fields, to avoid recursion during _nl_find_msg. */
211 domain->codeset_cntr =
212 (domainbinding != NULL ? domainbinding->codeset_cntr : 0);
213 #ifdef _LIBC
214 domain->conv = (__gconv_t) -1;
215 #else
216 # if HAVE_ICONV
217 domain->conv = (iconv_t) -1;
218 # endif
219 #endif
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)
233 size_t len;
234 char *charset;
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';
243 # else
244 memcpy (charset, charsetstr, len);
245 charset[len] = '\0';
246 # endif
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;
255 else
257 outcharset = getenv ("OUTPUT_CHARSET");
258 if (outcharset == NULL || outcharset[0] == '\0')
260 # ifdef _LIBC
261 outcharset = (*_nl_current[LC_CTYPE])->values[_NL_ITEM_INDEX (CODESET)].string;
262 # else
263 # if HAVE_ICONV
264 extern const char *locale_charset (void);
265 outcharset = locale_charset ();
266 # endif
267 # endif
271 # ifdef _LIBC
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,
276 GCONV_AVOID_NOCONV)
277 != __GCONV_OK)
278 domain->conv = (__gconv_t) -1;
279 # else
280 # if HAVE_ICONV
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);
288 outcharset = tmp;
290 # endif
291 domain->conv = iconv_open (outcharset, charset);
292 # if _LIBICONV_VERSION
293 freea (outcharset);
294 # endif
295 # endif
296 # endif
298 freea (charset);
300 #endif /* _LIBC || HAVE_ICONV */
303 return nullentry;
306 /* Frees the codeset dependent parts of an opened message catalog. */
307 void
308 internal_function
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);
315 #ifdef _LIBC
316 if (domain->conv != (__gconv_t) -1)
317 __gconv_close (domain->conv);
318 #else
319 # if HAVE_ICONV
320 if (domain->conv != (iconv_t) -1)
321 iconv_close (domain->conv);
322 # endif
323 #endif
326 /* Load the message catalogs specified by FILENAME. If it is no valid
327 message catalog do nothing. */
328 void
329 internal_function
330 _nl_load_domain (domain_file, domainbinding)
331 struct loaded_l10nfile *domain_file;
332 struct binding *domainbinding;
334 int fd;
335 size_t size;
336 #ifdef _LIBC
337 struct stat64 st;
338 #else
339 struct stat st;
340 #endif
341 struct mo_file_header *data = (struct mo_file_header *) -1;
342 int use_mmap = 0;
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
356 syntax. */
357 if (domain_file->filename == NULL)
358 return;
360 /* Try to open the addressed file. */
361 fd = open (domain_file->filename, O_RDONLY);
362 if (fd == -1)
363 return;
365 /* We must know about the size of the file. */
366 if (
367 #ifdef _LIBC
368 __builtin_expect (fstat64 (fd, &st) != 0, 0)
369 #else
370 __builtin_expect (fstat (fd, &st) != 0, 0)
371 #endif
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. */
376 close (fd);
377 return;
380 #ifdef HAVE_MMAP
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,
384 MAP_PRIVATE, fd, 0);
386 if (__builtin_expect (data != (struct mo_file_header *) -1, 1))
388 /* mmap() call was successful. */
389 close (fd);
390 use_mmap = 1;
392 #endif
394 /* If the data is not yet available (i.e. mmap'ed) we try to load
395 it manually. */
396 if (data == (struct mo_file_header *) -1)
398 size_t to_read;
399 char *read_ptr;
401 data = (struct mo_file_header *) malloc (size);
402 if (data == NULL)
403 return;
405 to_read = size;
406 read_ptr = (char *) data;
409 long int nb = (long int) read (fd, read_ptr, to_read);
410 if (nb <= 0)
412 #ifdef EINTR
413 if (nb == -1 && errno == EINTR)
414 continue;
415 #endif
416 close (fd);
417 return;
419 read_ptr += nb;
420 to_read -= nb;
422 while (to_read > 0);
424 close (fd);
427 /* Using the magic number we can test whether it really is a message
428 catalog file. */
429 if (__builtin_expect (data->magic != _MAGIC && data->magic != _MAGIC_SWAPPED,
432 /* The magic number is wrong: not a message catalog file. */
433 #ifdef HAVE_MMAP
434 if (use_mmap)
435 munmap ((caddr_t) data, size);
436 else
437 #endif
438 free (data);
439 return;
442 domain = (struct loaded_domain *) malloc (sizeof (struct loaded_domain));
443 if (domain == NULL)
444 return;
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))
455 case 0:
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));
464 break;
465 default:
466 /* This is an invalid revision. */
467 #ifdef HAVE_MMAP
468 if (use_mmap)
469 munmap ((caddr_t) data, size);
470 else
471 #endif
472 free (data);
473 free (domain);
474 domain_file->data = NULL;
475 return;
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)
486 const char *plural;
487 const char *nplurals;
489 plural = strstr (nullentry, "plural=");
490 nplurals = strstr (nullentry, "nplurals=");
491 if (plural == NULL || nplurals == NULL)
492 goto no_plural;
493 else
495 /* First get the number. */
496 char *endp;
497 unsigned long int n;
498 struct parse_args args;
500 nplurals += 9;
501 while (*nplurals != '\0' && isspace (*nplurals))
502 ++nplurals;
503 #if defined HAVE_STRTOUL || defined _LIBC
504 n = strtoul (nplurals, &endp, 10);
505 #else
506 for (endp = nplurals, n = 0; *endp >= '0' && *endp <= '9'; endp++)
507 n = n * 10 + (*endp - '0');
508 #endif
509 domain->nplurals = n;
510 if (nplurals == endp)
511 goto no_plural;
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. */
517 plural += 7;
518 args.cp = plural;
519 if (PLURAL_PARSE (&args) != 0)
520 goto no_plural;
521 domain->plural = args.res;
524 else
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. */
529 no_plural:
530 INIT_GERMANIC_PLURAL ();
531 domain->plural = &germanic_plural;
532 domain->nplurals = 2;
537 #ifdef _LIBC
538 void
539 internal_function
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);
551 else
552 # endif /* _POSIX_MAPPED_FILES */
553 free ((void *) domain->data);
555 free (domain);
557 #endif