* string/string.h (strndupa): Add cast for C++ conformance.
[glibc.git] / intl / loadmsgcat.c
blob660dc7b6ed850bdf04ad71811afbcea2ba65aee1
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 /* Load the message catalogs specified by FILENAME. If it is no valid
194 message catalog do nothing. */
195 void
196 internal_function
197 _nl_load_domain (domain_file)
198 struct loaded_l10nfile *domain_file;
200 int fd;
201 size_t size;
202 #ifdef _LIBC
203 struct stat64 st;
204 #else
205 struct stat st;
206 #endif
207 struct mo_file_header *data = (struct mo_file_header *) -1;
208 int use_mmap = 0;
209 struct loaded_domain *domain;
210 char *nullentry;
211 size_t nullentrylen;
213 domain_file->decided = 1;
214 domain_file->data = NULL;
216 /* If the record does not represent a valid locale the FILENAME
217 might be NULL. This can happen when according to the given
218 specification the locale file name is different for XPG and CEN
219 syntax. */
220 if (domain_file->filename == NULL)
221 return;
223 /* Try to open the addressed file. */
224 fd = open (domain_file->filename, O_RDONLY);
225 if (fd == -1)
226 return;
228 /* We must know about the size of the file. */
229 if (
230 #ifdef _LIBC
231 __builtin_expect (fstat64 (fd, &st) != 0, 0)
232 #else
233 __builtin_expect (fstat (fd, &st) != 0, 0)
234 #endif
235 || __builtin_expect ((size = (size_t) st.st_size) != st.st_size, 0)
236 || __builtin_expect (size < sizeof (struct mo_file_header), 0))
238 /* Something went wrong. */
239 close (fd);
240 return;
243 #ifdef HAVE_MMAP
244 /* Now we are ready to load the file. If mmap() is available we try
245 this first. If not available or it failed we try to load it. */
246 data = (struct mo_file_header *) mmap (NULL, size, PROT_READ,
247 MAP_PRIVATE, fd, 0);
249 if (__builtin_expect (data != (struct mo_file_header *) -1, 1))
251 /* mmap() call was successful. */
252 close (fd);
253 use_mmap = 1;
255 #endif
257 /* If the data is not yet available (i.e. mmap'ed) we try to load
258 it manually. */
259 if (data == (struct mo_file_header *) -1)
261 size_t to_read;
262 char *read_ptr;
264 data = (struct mo_file_header *) malloc (size);
265 if (data == NULL)
266 return;
268 to_read = size;
269 read_ptr = (char *) data;
272 long int nb = (long int) read (fd, read_ptr, to_read);
273 if (nb <= 0)
275 #ifdef EINTR
276 if (nb == -1 && errno == EINTR)
277 continue;
278 #endif
279 close (fd);
280 return;
282 read_ptr += nb;
283 to_read -= nb;
285 while (to_read > 0);
287 close (fd);
290 /* Using the magic number we can test whether it really is a message
291 catalog file. */
292 if (__builtin_expect (data->magic != _MAGIC && data->magic != _MAGIC_SWAPPED,
295 /* The magic number is wrong: not a message catalog file. */
296 #ifdef HAVE_MMAP
297 if (use_mmap)
298 munmap ((caddr_t) data, size);
299 else
300 #endif
301 free (data);
302 return;
305 domain = (struct loaded_domain *) malloc (sizeof (struct loaded_domain));
306 if (domain == NULL)
307 return;
308 domain_file->data = domain;
310 domain->data = (char *) data;
311 domain->use_mmap = use_mmap;
312 domain->mmap_size = size;
313 domain->must_swap = data->magic != _MAGIC;
315 /* Fill in the information about the available tables. */
316 switch (W (domain->must_swap, data->revision))
318 case 0:
319 domain->nstrings = W (domain->must_swap, data->nstrings);
320 domain->orig_tab = (struct string_desc *)
321 ((char *) data + W (domain->must_swap, data->orig_tab_offset));
322 domain->trans_tab = (struct string_desc *)
323 ((char *) data + W (domain->must_swap, data->trans_tab_offset));
324 domain->hash_size = W (domain->must_swap, data->hash_tab_size);
325 domain->hash_tab = (nls_uint32 *)
326 ((char *) data + W (domain->must_swap, data->hash_tab_offset));
327 break;
328 default:
329 /* This is an invalid revision. */
330 #ifdef HAVE_MMAP
331 if (use_mmap)
332 munmap ((caddr_t) data, size);
333 else
334 #endif
335 free (data);
336 free (domain);
337 domain_file->data = NULL;
338 return;
341 /* Now find out about the character set the file is encoded with.
342 This can be found (in textual form) in the entry "". If this
343 entry does not exist or if this does not contain the `charset='
344 information, we will assume the charset matches the one the
345 current locale and we don't have to perform any conversion. */
346 #ifdef _LIBC
347 domain->conv = (__gconv_t) -1;
348 #else
349 # if HAVE_ICONV
350 domain->conv = (iconv_t) -1;
351 # endif
352 #endif
353 domain->conv_tab = NULL;
354 nullentry = _nl_find_msg (domain_file, "", &nullentrylen);
355 if (nullentry != NULL)
357 #if defined _LIBC || HAVE_ICONV
358 const char *charsetstr;
360 charsetstr = strstr (nullentry, "charset=");
361 if (charsetstr != NULL)
363 size_t len;
364 char *charset;
365 const char *outcharset;
367 charsetstr += strlen ("charset=");
368 len = strcspn (charsetstr, " \t\n");
370 charset = (char *) alloca (len + 1);
371 # if defined _LIBC || HAVE_MEMPCPY
372 *((char *) mempcpy (charset, charsetstr, len)) = '\0';
373 # else
374 memcpy (charset, charsetstr, len);
375 charset[len] = '\0';
376 # endif
378 /* The output charset should normally be determined by the
379 locale. But sometimes the locale is not used or not correctly
380 set up, so we provide a possibility for the user to override
381 this. Moreover, the value specified through
382 bind_textdomain_codeset overrides both. */
383 if (domain_file->domainbinding != NULL
384 && domain_file->domainbinding->codeset != NULL)
385 outcharset = domain_file->domainbinding->codeset;
386 else
388 outcharset = getenv ("OUTPUT_CHARSET");
389 if (outcharset == NULL || outcharset[0] == '\0')
391 # ifdef _LIBC
392 outcharset = (*_nl_current[LC_CTYPE])->values[_NL_ITEM_INDEX (CODESET)].string;
393 # else
394 # if HAVE_ICONV
395 extern const char *locale_charset (void);
396 outcharset = locale_charset ();
397 # endif
398 # endif
402 # ifdef _LIBC
403 /* We always want to use transliteration. */
404 outcharset = norm_add_slashes (outcharset, "TRANSLIT");
405 charset = norm_add_slashes (charset, NULL);
406 if (__gconv_open (outcharset, charset, &domain->conv,
407 GCONV_AVOID_NOCONV)
408 != __GCONV_OK)
409 domain->conv = (__gconv_t) -1;
410 # else
411 # if HAVE_ICONV
412 domain->conv = iconv_open (outcharset, charset);
413 # endif
414 # endif
416 freea (charset);
418 #endif /* _LIBC || HAVE_ICONV */
421 /* Also look for a plural specification. */
422 if (nullentry != NULL)
424 const char *plural;
425 const char *nplurals;
427 plural = strstr (nullentry, "plural=");
428 nplurals = strstr (nullentry, "nplurals=");
429 if (plural == NULL || nplurals == NULL)
430 goto no_plural;
431 else
433 /* First get the number. */
434 char *endp;
435 unsigned long int n;
436 struct parse_args args;
438 nplurals += 9;
439 while (*nplurals != '\0' && isspace (*nplurals))
440 ++nplurals;
441 #if defined HAVE_STRTOUL || defined _LIBC
442 n = strtoul (nplurals, &endp, 10);
443 #else
444 for (endp = nplurals, n = 0; *endp >= '0' && *endp <= '9'; endp++)
445 n = n * 10 + (*endp - '0');
446 #endif
447 domain->nplurals = n;
448 if (nplurals == endp)
449 goto no_plural;
451 /* Due to the restrictions bison imposes onto the interface of the
452 scanner function we have to put the input string and the result
453 passed up from the parser into the same structure which address
454 is passed down to the parser. */
455 plural += 7;
456 args.cp = plural;
457 if (PLURAL_PARSE (&args) != 0)
458 goto no_plural;
459 domain->plural = args.res;
462 else
464 /* By default we are using the Germanic form: singular form only
465 for `one', the plural form otherwise. Yes, this is also what
466 English is using since English is a Germanic language. */
467 no_plural:
468 INIT_GERMANIC_PLURAL ();
469 domain->plural = &germanic_plural;
470 domain->nplurals = 2;
475 #ifdef _LIBC
476 void
477 internal_function
478 _nl_unload_domain (domain)
479 struct loaded_domain *domain;
481 if (domain->plural != &germanic_plural)
482 __gettext_free_exp (domain->plural);
484 if (domain->conv_tab != NULL && domain->conv_tab != (char **) -1)
485 free (domain->conv_tab);
487 if (domain->conv != (__gconv_t) -1)
488 __gconv_close (domain->conv);
490 # ifdef _POSIX_MAPPED_FILES
491 if (domain->use_mmap)
492 munmap ((caddr_t) domain->data, domain->mmap_size);
493 else
494 # endif /* _POSIX_MAPPED_FILES */
495 free ((void *) domain->data);
497 free (domain);
499 #endif