VirtualBox

source: kBuild/vendor/sed/current/intl/loadmsgcat.c

Last change on this file was 599, checked in by bird, 18 years ago

GNU sed 4.1.5.

File size: 11.8 KB
Line 
1/* Load needed message catalogs.
2 Copyright (C) 1995-1999, 2000, 2001 Free Software Foundation, Inc.
3
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)
7 any later version.
8
9 This program 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.
13
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
17 USA. */
18
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
25
26#ifdef HAVE_CONFIG_H
27# include <config.h>
28#endif
29
30#include <ctype.h>
31#include <errno.h>
32#include <fcntl.h>
33#include <sys/types.h>
34#include <sys/stat.h>
35
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
47char *alloca ();
48# endif
49# endif
50# endif
51#endif
52
53#include <stdlib.h>
54#include <string.h>
55
56#if defined HAVE_UNISTD_H || defined _LIBC
57# include <unistd.h>
58#endif
59
60#ifdef _LIBC
61# include <langinfo.h>
62# include <locale.h>
63#endif
64
65#if (defined HAVE_MMAP && defined HAVE_MUNMAP && !defined DISALLOW_MMAP) \
66 || (defined _LIBC && defined _POSIX_MAPPED_FILES)
67# include <sys/mman.h>
68# undef HAVE_MMAP
69# define HAVE_MMAP 1
70#else
71# undef HAVE_MMAP
72#endif
73
74#include "gmo.h"
75#include "gettextP.h"
76#include "plural-exp.h"
77
78#ifdef _LIBC
79# include "../locale/localeinfo.h"
80#endif
81
82/* @@ end of prolog @@ */
83
84#ifdef _LIBC
85/* Rename the non ISO C functions. This is required by the standard
86 because some ISO C functions will require linking with this object
87 file and the name space must not be polluted. */
88# define open __open
89# define close __close
90# define read __read
91# define mmap __mmap
92# define munmap __munmap
93#endif
94
95/* For those losing systems which don't have `alloca' we have to add
96 some additional code emulating it. */
97#ifdef HAVE_ALLOCA
98# define freea(p) /* nothing */
99#else
100# define alloca(n) malloc (n)
101# define freea(p) free (p)
102#endif
103
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
110#endif
111#ifdef __BEOS__
112 /* BeOS 5 has O_BINARY and O_TEXT, but they have no effect. */
113# undef O_BINARY
114# undef O_TEXT
115#endif
116/* On reasonable systems, binary I/O is the default. */
117#ifndef O_BINARY
118# define O_BINARY 0
119#endif
120
121/* We need a sign, whether a new catalog was loaded, which can be associated
122 with all translations. This is important if the translations are
123 cached by one of GCC's features. */
124int _nl_msg_cat_cntr;
125
126
127/* Initialize the codeset dependent parts of an opened message catalog.
128 Return the header entry. */
129const char *
130internal_function
131_nl_init_domain_conv (domain_file, domain, domainbinding)
132 struct loaded_l10nfile *domain_file;
133 struct loaded_domain *domain;
134 struct binding *domainbinding;
135{
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. */
141 char *nullentry;
142 size_t nullentrylen;
143
144 /* Preinitialize fields, to avoid recursion during _nl_find_msg. */
145 domain->codeset_cntr =
146 (domainbinding != NULL ? domainbinding->codeset_cntr : 0);
147#ifdef _LIBC
148 domain->conv = (__gconv_t) -1;
149#else
150# if HAVE_ICONV
151 domain->conv = (iconv_t) -1;
152# endif
153#endif
154 domain->conv_tab = NULL;
155
156 /* Get the header entry. */
157 nullentry = _nl_find_msg (domain_file, domainbinding, "", &nullentrylen);
158
159 if (nullentry != NULL)
160 {
161#if defined _LIBC || HAVE_ICONV
162 const char *charsetstr;
163
164 charsetstr = strstr (nullentry, "charset=");
165 if (charsetstr != NULL)
166 {
167 size_t len;
168 char *charset;
169 const char *outcharset;
170
171 charsetstr += strlen ("charset=");
172 len = strcspn (charsetstr, " \t\n");
173
174 charset = (char *) alloca (len + 1);
175# if defined _LIBC || HAVE_MEMPCPY
176 *((char *) mempcpy (charset, charsetstr, len)) = '\0';
177# else
178 memcpy (charset, charsetstr, len);
179 charset[len] = '\0';
180# endif
181
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;
189 else
190 {
191 outcharset = getenv ("OUTPUT_CHARSET");
192 if (outcharset == NULL || outcharset[0] == '\0')
193 {
194# ifdef _LIBC
195 outcharset = (*_nl_current[LC_CTYPE])->values[_NL_ITEM_INDEX (CODESET)].string;
196# else
197# if HAVE_ICONV
198 extern const char *locale_charset PARAMS ((void));
199 outcharset = locale_charset ();
200# endif
201# endif
202 }
203 }
204
205# ifdef _LIBC
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,
210 GCONV_AVOID_NOCONV)
211 != __GCONV_OK)
212 domain->conv = (__gconv_t) -1;
213# else
214# if HAVE_ICONV
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);
220 {
221 char *tmp = (char *) alloca (len + 10 + 1);
222 memcpy (tmp, outcharset, len);
223 memcpy (tmp + len, "//TRANSLIT", 10 + 1);
224 outcharset = tmp;
225 }
226# endif
227 domain->conv = iconv_open (outcharset, charset);
228# if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2) || __GLIBC__ > 2 \
229 || _LIBICONV_VERSION >= 0x0105
230 freea (outcharset);
231# endif
232# endif
233# endif
234
235 freea (charset);
236 }
237#endif /* _LIBC || HAVE_ICONV */
238 }
239
240 return nullentry;
241}
242
243/* Frees the codeset dependent parts of an opened message catalog. */
244void
245internal_function
246_nl_free_domain_conv (domain)
247 struct loaded_domain *domain;
248{
249 if (domain->conv_tab != NULL && domain->conv_tab != (char **) -1)
250 free (domain->conv_tab);
251
252#ifdef _LIBC
253 if (domain->conv != (__gconv_t) -1)
254 __gconv_close (domain->conv);
255#else
256# if HAVE_ICONV
257 if (domain->conv != (iconv_t) -1)
258 iconv_close (domain->conv);
259# endif
260#endif
261}
262
263/* Load the message catalogs specified by FILENAME. If it is no valid
264 message catalog do nothing. */
265void
266internal_function
267_nl_load_domain (domain_file, domainbinding)
268 struct loaded_l10nfile *domain_file;
269 struct binding *domainbinding;
270{
271 int fd;
272 size_t size;
273#ifdef _LIBC
274 struct stat64 st;
275#else
276 struct stat st;
277#endif
278 struct mo_file_header *data = (struct mo_file_header *) -1;
279 int use_mmap = 0;
280 struct loaded_domain *domain;
281 const char *nullentry;
282
283 domain_file->decided = 1;
284 domain_file->data = NULL;
285
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). */
289
290 /* If the record does not represent a valid locale the FILENAME
291 might be NULL. This can happen when according to the given
292 specification the locale file name is different for XPG and CEN
293 syntax. */
294 if (domain_file->filename == NULL)
295 return;
296
297 /* Try to open the addressed file. */
298 fd = open (domain_file->filename, O_RDONLY | O_BINARY);
299 if (fd == -1)
300 return;
301
302 /* We must know about the size of the file. */
303 if (
304#ifdef _LIBC
305 __builtin_expect (fstat64 (fd, &st) != 0, 0)
306#else
307 __builtin_expect (fstat (fd, &st) != 0, 0)
308#endif
309 || __builtin_expect ((size = (size_t) st.st_size) != st.st_size, 0)
310 || __builtin_expect (size < sizeof (struct mo_file_header), 0))
311 {
312 /* Something went wrong. */
313 close (fd);
314 return;
315 }
316
317#ifdef HAVE_MMAP
318 /* Now we are ready to load the file. If mmap() is available we try
319 this first. If not available or it failed we try to load it. */
320 data = (struct mo_file_header *) mmap (NULL, size, PROT_READ,
321 MAP_PRIVATE, fd, 0);
322
323 if (__builtin_expect (data != (struct mo_file_header *) -1, 1))
324 {
325 /* mmap() call was successful. */
326 close (fd);
327 use_mmap = 1;
328 }
329#endif
330
331 /* If the data is not yet available (i.e. mmap'ed) we try to load
332 it manually. */
333 if (data == (struct mo_file_header *) -1)
334 {
335 size_t to_read;
336 char *read_ptr;
337
338 data = (struct mo_file_header *) malloc (size);
339 if (data == NULL)
340 return;
341
342 to_read = size;
343 read_ptr = (char *) data;
344 do
345 {
346 long int nb = (long int) read (fd, read_ptr, to_read);
347 if (nb <= 0)
348 {
349#ifdef EINTR
350 if (nb == -1 && errno == EINTR)
351 continue;
352#endif
353 close (fd);
354 return;
355 }
356 read_ptr += nb;
357 to_read -= nb;
358 }
359 while (to_read > 0);
360
361 close (fd);
362 }
363
364 /* Using the magic number we can test whether it really is a message
365 catalog file. */
366 if (__builtin_expect (data->magic != _MAGIC && data->magic != _MAGIC_SWAPPED,
367 0))
368 {
369 /* The magic number is wrong: not a message catalog file. */
370#ifdef HAVE_MMAP
371 if (use_mmap)
372 munmap ((caddr_t) data, size);
373 else
374#endif
375 free (data);
376 return;
377 }
378
379 domain = (struct loaded_domain *) malloc (sizeof (struct loaded_domain));
380 if (domain == NULL)
381 return;
382 domain_file->data = domain;
383
384 domain->data = (char *) data;
385 domain->use_mmap = use_mmap;
386 domain->mmap_size = size;
387 domain->must_swap = data->magic != _MAGIC;
388
389 /* Fill in the information about the available tables. */
390 switch (W (domain->must_swap, data->revision))
391 {
392 case 0:
393 domain->nstrings = W (domain->must_swap, data->nstrings);
394 domain->orig_tab = (struct string_desc *)
395 ((char *) data + W (domain->must_swap, data->orig_tab_offset));
396 domain->trans_tab = (struct string_desc *)
397 ((char *) data + W (domain->must_swap, data->trans_tab_offset));
398 domain->hash_size = W (domain->must_swap, data->hash_tab_size);
399 domain->hash_tab = (nls_uint32 *)
400 ((char *) data + W (domain->must_swap, data->hash_tab_offset));
401 break;
402 default:
403 /* This is an invalid revision. */
404#ifdef HAVE_MMAP
405 if (use_mmap)
406 munmap ((caddr_t) data, size);
407 else
408#endif
409 free (data);
410 free (domain);
411 domain_file->data = NULL;
412 return;
413 }
414
415 /* Now initialize the character set converter from the character set
416 the file is encoded with (found in the header entry) to the domain's
417 specified character set or the locale's character set. */
418 nullentry = _nl_init_domain_conv (domain_file, domain, domainbinding);
419
420 /* Also look for a plural specification. */
421 EXTRACT_PLURAL_EXPRESSION (nullentry, &domain->plural, &domain->nplurals);
422}
423
424
425#ifdef _LIBC
426void
427internal_function
428_nl_unload_domain (domain)
429 struct loaded_domain *domain;
430{
431 if (domain->plural != &__gettext_germanic_plural)
432 __gettext_free_exp (domain->plural);
433
434 _nl_free_domain_conv (domain);
435
436# ifdef _POSIX_MAPPED_FILES
437 if (domain->use_mmap)
438 munmap ((caddr_t) domain->data, domain->mmap_size);
439 else
440# endif /* _POSIX_MAPPED_FILES */
441 free ((void *) domain->data);
442
443 free (domain);
444}
445#endif
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette