1
1
/* Load needed message catalogs.
2
Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
2
Copyright (C) 1995-1999, 2000, 2001 Free Software Foundation, Inc.
4
This program is free software; you can redistribute it and/or modify
5
it under the terms of the GNU General Public License as published by
6
the Free Software Foundation; either version 2, or (at your option)
4
This program is free software; you can redistribute it and/or modify it
5
under the terms of the GNU Library General Public License as published
6
by the Free Software Foundation; either version 2, or (at your option)
9
9
This program is distributed in the hope that it will be useful,
10
10
but WITHOUT ANY WARRANTY; without even the implied warranty of
11
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
GNU General Public License for more details.
14
You should have received a copy of the GNU General Public License
15
along with this program; if not, write to the Free Software Foundation,
16
Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
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 this program; if not, write to the Free Software
16
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
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
18
26
#ifdef HAVE_CONFIG_H
19
27
# include <config.h>
23
33
#include <sys/types.h>
24
34
#include <sys/stat.h>
26
#if defined STDC_HEADERS || defined _LIBC
37
# define alloca __builtin_alloca
38
# define HAVE_ALLOCA 1
40
# if defined HAVE_ALLOCA_H || defined _LIBC
30
56
#if defined HAVE_UNISTD_H || defined _LIBC
31
57
# include <unistd.h>
34
#if (defined HAVE_MMAP && defined HAVE_MUNMAP) || defined _LIBC
61
# include <langinfo.h>
65
#if (defined HAVE_MMAP && defined HAVE_MUNMAP && !defined DISALLOW_MMAP) \
66
|| (defined _LIBC && defined _POSIX_MAPPED_FILES)
35
67
# include <sys/mman.h>
39
75
#include "gettextP.h"
76
#include "plural-exp.h"
79
# include "../locale/localeinfo.h"
41
82
/* @@ end of prolog @@ */
51
92
# define munmap __munmap
95
/* For those losing systems which don't have `alloca' we have to add
96
some additional code emulating it. */
98
# define freea(p) /* nothing */
100
# define alloca(n) malloc (n)
101
# define freea(p) free (p)
104
/* For systems that distinguish between text and binary I/O.
105
O_BINARY is usually declared in <fcntl.h>. */
106
#if !defined O_BINARY && defined _O_BINARY
107
/* For MSC-compatible compilers. */
108
# define O_BINARY _O_BINARY
109
# define O_TEXT _O_TEXT
112
/* BeOS 5 has O_BINARY and O_TEXT, but they have no effect. */
116
/* On reasonable systems, binary I/O is the default. */
54
121
/* We need a sign, whether a new catalog was loaded, which can be associated
55
122
with all translations. This is important if the translations are
56
123
cached by one of GCC's features. */
57
int _nl_msg_cat_cntr = 0;
124
int _nl_msg_cat_cntr;
127
/* Initialize the codeset dependent parts of an opened message catalog.
128
Return the header entry. */
131
_nl_init_domain_conv (domain_file, domain, domainbinding)
132
struct loaded_l10nfile *domain_file;
133
struct loaded_domain *domain;
134
struct binding *domainbinding;
136
/* Find out about the character set the file is encoded with.
137
This can be found (in textual form) in the entry "". If this
138
entry does not exist or if this does not contain the `charset='
139
information, we will assume the charset matches the one the
140
current locale and we don't have to perform any conversion. */
144
/* Preinitialize fields, to avoid recursion during _nl_find_msg. */
145
domain->codeset_cntr =
146
(domainbinding != NULL ? domainbinding->codeset_cntr : 0);
148
domain->conv = (__gconv_t) -1;
151
domain->conv = (iconv_t) -1;
154
domain->conv_tab = NULL;
156
/* Get the header entry. */
157
nullentry = _nl_find_msg (domain_file, domainbinding, "", &nullentrylen);
159
if (nullentry != NULL)
161
#if defined _LIBC || HAVE_ICONV
162
const char *charsetstr;
164
charsetstr = strstr (nullentry, "charset=");
165
if (charsetstr != NULL)
169
const char *outcharset;
171
charsetstr += strlen ("charset=");
172
len = strcspn (charsetstr, " \t\n");
174
charset = (char *) alloca (len + 1);
175
# if defined _LIBC || HAVE_MEMPCPY
176
*((char *) mempcpy (charset, charsetstr, len)) = '\0';
178
memcpy (charset, charsetstr, len);
182
/* The output charset should normally be determined by the
183
locale. But sometimes the locale is not used or not correctly
184
set up, so we provide a possibility for the user to override
185
this. Moreover, the value specified through
186
bind_textdomain_codeset overrides both. */
187
if (domainbinding != NULL && domainbinding->codeset != NULL)
188
outcharset = domainbinding->codeset;
191
outcharset = getenv ("OUTPUT_CHARSET");
192
if (outcharset == NULL || outcharset[0] == '\0')
195
outcharset = (*_nl_current[LC_CTYPE])->values[_NL_ITEM_INDEX (CODESET)].string;
198
extern const char *locale_charset PARAMS ((void));
199
outcharset = locale_charset ();
206
/* We always want to use transliteration. */
207
outcharset = norm_add_slashes (outcharset, "TRANSLIT");
208
charset = norm_add_slashes (charset, NULL);
209
if (__gconv_open (outcharset, charset, &domain->conv,
212
domain->conv = (__gconv_t) -1;
215
/* When using GNU libc >= 2.2 or GNU libiconv >= 1.5,
216
we want to use transliteration. */
217
# if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2) || __GLIBC__ > 2 \
218
|| _LIBICONV_VERSION >= 0x0105
219
len = strlen (outcharset);
221
char *tmp = (char *) alloca (len + 10 + 1);
222
memcpy (tmp, outcharset, len);
223
memcpy (tmp + len, "//TRANSLIT", 10 + 1);
227
domain->conv = iconv_open (outcharset, charset);
228
# if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2) || __GLIBC__ > 2 \
229
|| _LIBICONV_VERSION >= 0x0105
237
#endif /* _LIBC || HAVE_ICONV */
243
/* Frees the codeset dependent parts of an opened message catalog. */
246
_nl_free_domain_conv (domain)
247
struct loaded_domain *domain;
249
if (domain->conv_tab != NULL && domain->conv_tab != (char **) -1)
250
free (domain->conv_tab);
253
if (domain->conv != (__gconv_t) -1)
254
__gconv_close (domain->conv);
257
if (domain->conv != (iconv_t) -1)
258
iconv_close (domain->conv);
60
263
/* Load the message catalogs specified by FILENAME. If it is no valid
61
264
message catalog do nothing. */
64
_nl_load_domain (domain_file)
267
_nl_load_domain (domain_file, domainbinding)
65
268
struct loaded_l10nfile *domain_file;
269
struct binding *domainbinding;
70
278
struct mo_file_header *data = (struct mo_file_header *) -1;
71
#if (defined HAVE_MMAP && defined HAVE_MUNMAP && !defined DISALLOW_MMAP) \
75
280
struct loaded_domain *domain;
281
const char *nullentry;
77
283
domain_file->decided = 1;
78
284
domain_file->data = NULL;
286
/* Note that it would be useless to store domainbinding in domain_file
287
because domainbinding might be == NULL now but != NULL later (after
288
a call to bind_textdomain_codeset). */
80
290
/* If the record does not represent a valid locale the FILENAME
81
291
might be NULL. This can happen when according to the given
82
292
specification the locale file name is different for XPG and CEN
87
297
/* Try to open the addressed file. */
88
fd = open (domain_file->filename, O_RDONLY);
298
fd = open (domain_file->filename, O_RDONLY | O_BINARY);
92
302
/* We must know about the size of the file. */
93
if (fstat (fd, &st) != 0
94
|| (size = (size_t) st.st_size) != st.st_size
95
|| size < sizeof (struct mo_file_header))
305
__builtin_expect (fstat64 (fd, &st) != 0, 0)
307
__builtin_expect (fstat (fd, &st) != 0, 0)
309
|| __builtin_expect ((size = (size_t) st.st_size) != st.st_size, 0)
310
|| __builtin_expect (size < sizeof (struct mo_file_header), 0))
97
312
/* Something went wrong. */
102
#if (defined HAVE_MMAP && defined HAVE_MUNMAP && !defined DISALLOW_MMAP) \
104
318
/* Now we are ready to load the file. If mmap() is available we try
105
319
this first. If not available or it failed we try to load it. */
106
320
data = (struct mo_file_header *) mmap (NULL, size, PROT_READ,
107
321
MAP_PRIVATE, fd, 0);
109
if (data != (struct mo_file_header *) -1)
323
if (__builtin_expect (data != (struct mo_file_header *) -1, 1))
111
325
/* mmap() call was successful. */