3 /* Load needed message catalogs.
4 Copyright (C) 1995-1999, 2000, 2001 Free Software Foundation, Inc.
6 This program is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Library General Public License as published
8 by the Free Software Foundation; either version 2, or (at your option)
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Library General Public License for more details.
16 You should have received a copy of the GNU Library General Public
17 License along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
21 /* Tell glibc's <string.h> to provide a prototype for mempcpy().
22 This must come before <config.h> because <config.h> may include
23 <features.h>, and once <features.h> has been included, it's too late. */
25 # define _GNU_SOURCE 1
35 #include <sys/types.h>
39 # define alloca __builtin_alloca
40 # define HAVE_ALLOCA 1
42 # if defined HAVE_ALLOCA_H || defined _LIBC
58 #if defined HAVE_UNISTD_H || defined _LIBC
63 # include <langinfo.h>
67 #if (defined HAVE_MMAP && defined HAVE_MUNMAP && !defined DISALLOW_MMAP) \
68 || (defined _LIBC && defined _POSIX_MAPPED_FILES)
69 # include <sys/mman.h>
78 #include "plural-exp.h"
81 # include "../locale/localeinfo.h"
84 /* @@ end of prolog @@ */
87 /* Rename the non ISO C functions. This is required by the standard
88 because some ISO C functions will require linking with this object
89 file and the name space must not be polluted. */
91 # define close __close
94 # define munmap __munmap
97 /* For those losing systems which don't have `alloca' we have to add
98 some additional code emulating it. */
100 # define freea(p) /* nothing */
102 # define alloca(n) malloc (n)
103 # define freea(p) free (p)
106 /* For systems that distinguish between text and binary I/O.
107 O_BINARY is usually declared in <fcntl.h>. */
108 #if !defined O_BINARY && defined _O_BINARY
109 /* For MSC-compatible compilers. */
110 # define O_BINARY _O_BINARY
111 # define O_TEXT _O_TEXT
114 /* BeOS 5 has O_BINARY and O_TEXT, but they have no effect. */
118 /* On reasonable systems, binary I/O is the default. */
123 /* We need a sign, whether a new catalog was loaded, which can be associated
124 with all translations. This is important if the translations are
125 cached by one of GCC's features. */
126 int _nl_msg_cat_cntr
;
129 /* Initialize the codeset dependent parts of an opened message catalog.
130 Return the header entry. */
133 _nl_init_domain_conv (domain_file
, domain
, domainbinding
)
134 struct loaded_l10nfile
*domain_file
;
135 struct loaded_domain
*domain
;
136 struct binding
*domainbinding
;
138 /* Find out about the character set the file is encoded with.
139 This can be found (in textual form) in the entry "". If this
140 entry does not exist or if this does not contain the `charset='
141 information, we will assume the charset matches the one the
142 current locale and we don't have to perform any conversion. */
146 /* Preinitialize fields, to avoid recursion during _nl_find_msg. */
147 domain
->codeset_cntr
=
148 (domainbinding
!= NULL
? domainbinding
->codeset_cntr
: 0);
150 domain
->conv
= (__gconv_t
) -1;
153 domain
->conv
= (iconv_t
) -1;
156 domain
->conv_tab
= NULL
;
158 /* Get the header entry. */
159 nullentry
= _nl_find_msg (domain_file
, domainbinding
, "", &nullentrylen
);
161 if (nullentry
!= NULL
)
163 #if defined _LIBC || HAVE_ICONV
164 const char *charsetstr
;
166 charsetstr
= strstr (nullentry
, "charset=");
167 if (charsetstr
!= NULL
)
171 const char *outcharset
;
173 charsetstr
+= strlen ("charset=");
174 len
= strcspn (charsetstr
, " \t\n");
176 charset
= (char *) alloca (len
+ 1);
177 # if defined _LIBC || HAVE_MEMPCPY
178 *((char *) mempcpy (charset
, charsetstr
, len
)) = '\0';
180 memcpy (charset
, charsetstr
, len
);
184 /* The output charset should normally be determined by the
185 locale. But sometimes the locale is not used or not correctly
186 set up, so we provide a possibility for the user to override
187 this. Moreover, the value specified through
188 bind_textdomain_codeset overrides both. */
189 if (domainbinding
!= NULL
&& domainbinding
->codeset
!= NULL
)
190 outcharset
= domainbinding
->codeset
;
193 outcharset
= getenv ("OUTPUT_CHARSET");
194 if (outcharset
== NULL
|| outcharset
[0] == '\0')
197 outcharset
= (*_nl_current
[LC_CTYPE
])->values
[_NL_ITEM_INDEX (CODESET
)].string
;
200 extern const char *locale_charset
PARAMS ((void));
201 outcharset
= locale_charset ();
208 /* We always want to use transliteration. */
209 outcharset
= norm_add_slashes (outcharset
, "TRANSLIT");
210 charset
= norm_add_slashes (charset
, NULL
);
211 if (__gconv_open (outcharset
, charset
, &domain
->conv
,
214 domain
->conv
= (__gconv_t
) -1;
217 /* When using GNU libc >= 2.2 or GNU libiconv >= 1.5,
218 we want to use transliteration. */
219 # if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2) || __GLIBC__ > 2 \
220 || _LIBICONV_VERSION >= 0x0105
221 len
= strlen (outcharset
);
223 char *tmp
= (char *) alloca (len
+ 10 + 1);
224 memcpy (tmp
, outcharset
, len
);
225 memcpy (tmp
+ len
, "//TRANSLIT", 10 + 1);
229 domain
->conv
= iconv_open (outcharset
, charset
);
230 # if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2) || __GLIBC__ > 2 \
231 || _LIBICONV_VERSION >= 0x0105
239 #endif /* _LIBC || HAVE_ICONV */
245 /* Frees the codeset dependent parts of an opened message catalog. */
248 _nl_free_domain_conv (domain
)
249 struct loaded_domain
*domain
;
251 if (domain
->conv_tab
!= NULL
&& domain
->conv_tab
!= (char **) -1)
252 free (domain
->conv_tab
);
255 if (domain
->conv
!= (__gconv_t
) -1)
256 __gconv_close (domain
->conv
);
259 if (domain
->conv
!= (iconv_t
) -1)
260 iconv_close (domain
->conv
);
265 /* Load the message catalogs specified by FILENAME. If it is no valid
266 message catalog do nothing. */
269 _nl_load_domain (domain_file
, domainbinding
)
270 struct loaded_l10nfile
*domain_file
;
271 struct binding
*domainbinding
;
280 struct mo_file_header
*data
= (struct mo_file_header
*) -1;
282 struct loaded_domain
*domain
;
283 const char *nullentry
;
285 domain_file
->decided
= 1;
286 domain_file
->data
= NULL
;
288 /* Note that it would be useless to store domainbinding in domain_file
289 because domainbinding might be == NULL now but != NULL later (after
290 a call to bind_textdomain_codeset). */
292 /* If the record does not represent a valid locale the FILENAME
293 might be NULL. This can happen when according to the given
294 specification the locale file name is different for XPG and CEN
296 if (domain_file
->filename
== NULL
)
299 /* Try to open the addressed file. */
300 fd
= open (domain_file
->filename
, O_RDONLY
| O_BINARY
);
304 /* We must know about the size of the file. */
307 __builtin_expect (fstat64 (fd
, &st
) != 0, 0)
309 __builtin_expect (fstat (fd
, &st
) != 0, 0)
311 || __builtin_expect ((size
= (size_t) st
.st_size
) != st
.st_size
, 0)
312 || __builtin_expect (size
< sizeof (struct mo_file_header
), 0))
314 /* Something went wrong. */
320 /* Now we are ready to load the file. If mmap() is available we try
321 this first. If not available or it failed we try to load it. */
322 data
= (struct mo_file_header
*) mmap (NULL
, size
, PROT_READ
,
325 if (__builtin_expect (data
!= (struct mo_file_header
*) -1, 1))
327 /* mmap() call was successful. */
333 /* If the data is not yet available (i.e. mmap'ed) we try to load
335 if (data
== (struct mo_file_header
*) -1)
340 data
= (struct mo_file_header
*) malloc (size
);
345 read_ptr
= (char *) data
;
348 long int nb
= (long int) read (fd
, read_ptr
, to_read
);
352 if (nb
== -1 && errno
== EINTR
)
366 /* Using the magic number we can test whether it really is a message
368 if (__builtin_expect (data
->magic
!= _MAGIC
&& data
->magic
!= _MAGIC_SWAPPED
,
371 /* The magic number is wrong: not a message catalog file. */
374 munmap ((caddr_t
) data
, size
);
381 domain
= (struct loaded_domain
*) malloc (sizeof (struct loaded_domain
));
384 domain_file
->data
= domain
;
386 domain
->data
= (char *) data
;
387 domain
->use_mmap
= use_mmap
;
388 domain
->mmap_size
= size
;
389 domain
->must_swap
= data
->magic
!= _MAGIC
;
391 /* Fill in the information about the available tables. */
392 switch (W (domain
->must_swap
, data
->revision
))
395 domain
->nstrings
= W (domain
->must_swap
, data
->nstrings
);
396 domain
->orig_tab
= (struct string_desc
*)
397 ((char *) data
+ W (domain
->must_swap
, data
->orig_tab_offset
));
398 domain
->trans_tab
= (struct string_desc
*)
399 ((char *) data
+ W (domain
->must_swap
, data
->trans_tab_offset
));
400 domain
->hash_size
= W (domain
->must_swap
, data
->hash_tab_size
);
401 domain
->hash_tab
= (nls_uint32
*)
402 ((char *) data
+ W (domain
->must_swap
, data
->hash_tab_offset
));
405 /* This is an invalid revision. */
408 munmap ((caddr_t
) data
, size
);
413 domain_file
->data
= NULL
;
417 /* Now initialize the character set converter from the character set
418 the file is encoded with (found in the header entry) to the domain's
419 specified character set or the locale's character set. */
420 nullentry
= _nl_init_domain_conv (domain_file
, domain
, domainbinding
);
422 /* Also look for a plural specification. */
423 EXTRACT_PLURAL_EXPRESSION (nullentry
, &domain
->plural
, &domain
->nplurals
);
430 _nl_unload_domain (domain
)
431 struct loaded_domain
*domain
;
433 if (domain
->plural
!= &__gettext_germanic_plural
)
434 __gettext_free_exp (domain
->plural
);
436 _nl_free_domain_conv (domain
);
438 # ifdef _POSIX_MAPPED_FILES
439 if (domain
->use_mmap
)
440 munmap ((caddr_t
) domain
->data
, domain
->mmap_size
);
442 # endif /* _POSIX_MAPPED_FILES */
443 free ((void *) domain
->data
);