1 /* Load needed message catalogs.
2 Copyright (C) 1995, 1996, 1997, 1998, 1999 Free Software Foundation, Inc.
4 This file is part of the GNU C Library. Its master source is NOT part of
5 the C library, however.
7 The GNU C Library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Library General Public License as
9 published by the Free Software Foundation; either version 2 of the
10 License, or (at your option) any later version.
12 The GNU C Library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Library General Public License for more details.
17 You should have received a copy of the GNU Library General Public
18 License along with the GNU C Library; see the file COPYING.LIB. If not,
19 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
27 #include <sys/types.h>
30 #if defined STDC_HEADERS || defined _LIBC
34 #if defined HAVE_STRING_H || defined _LIBC
36 # define _GNU_SOURCE 1
43 #if defined HAVE_UNISTD_H || defined _LIBC
48 # include <langinfo.h>
51 #if (defined HAVE_MMAP && defined HAVE_MUNMAP && !defined DISALLOW_MMAP) \
52 || (defined _LIBC && defined _POSIX_MAPPED_FILES)
53 # include <sys/mman.h>
64 # include "../locale/localeinfo.h"
67 /* @@ end of prolog @@ */
70 /* Rename the non ISO C functions. This is required by the standard
71 because some ISO C functions will require linking with this object
72 file and the name space must not be polluted. */
74 # define close __close
77 # define munmap __munmap
80 /* We need a sign, whether a new catalog was loaded, which can be associated
81 with all translations. This is important if the translations are
82 cached by one of GCC's features. */
86 /* Load the message catalogs specified by FILENAME. If it is no valid
87 message catalog do nothing. */
90 _nl_load_domain (domain_file
)
91 struct loaded_l10nfile
*domain_file
;
96 struct mo_file_header
*data
= (struct mo_file_header
*) -1;
98 struct loaded_domain
*domain
;
101 domain_file
->decided
= 1;
102 domain_file
->data
= NULL
;
104 /* If the record does not represent a valid locale the FILENAME
105 might be NULL. This can happen when according to the given
106 specification the locale file name is different for XPG and CEN
108 if (domain_file
->filename
== NULL
)
111 /* Try to open the addressed file. */
112 fd
= open (domain_file
->filename
, O_RDONLY
);
116 /* We must know about the size of the file. */
117 if (fstat (fd
, &st
) != 0
118 || (size
= (size_t) st
.st_size
) != st
.st_size
119 || size
< sizeof (struct mo_file_header
))
121 /* Something went wrong. */
127 /* Now we are ready to load the file. If mmap() is available we try
128 this first. If not available or it failed we try to load it. */
129 data
= (struct mo_file_header
*) mmap (NULL
, size
, PROT_READ
,
132 if (data
!= (struct mo_file_header
*) -1)
134 /* mmap() call was successful. */
140 /* If the data is not yet available (i.e. mmap'ed) we try to load
142 if (data
== (struct mo_file_header
*) -1)
147 data
= (struct mo_file_header
*) malloc (size
);
152 read_ptr
= (char *) data
;
155 long int nb
= (long int) read (fd
, read_ptr
, to_read
);
170 /* Using the magic number we can test whether it really is a message
172 if (data
->magic
!= _MAGIC
&& data
->magic
!= _MAGIC_SWAPPED
)
174 /* The magic number is wrong: not a message catalog file. */
177 munmap ((caddr_t
) data
, size
);
185 = (struct loaded_domain
*) malloc (sizeof (struct loaded_domain
));
186 if (domain_file
->data
== NULL
)
189 domain
= (struct loaded_domain
*) domain_file
->data
;
190 domain
->data
= (char *) data
;
191 domain
->use_mmap
= use_mmap
;
192 domain
->mmap_size
= size
;
193 domain
->must_swap
= data
->magic
!= _MAGIC
;
195 /* Fill in the information about the available tables. */
196 switch (W (domain
->must_swap
, data
->revision
))
199 domain
->nstrings
= W (domain
->must_swap
, data
->nstrings
);
200 domain
->orig_tab
= (struct string_desc
*)
201 ((char *) data
+ W (domain
->must_swap
, data
->orig_tab_offset
));
202 domain
->trans_tab
= (struct string_desc
*)
203 ((char *) data
+ W (domain
->must_swap
, data
->trans_tab_offset
));
204 domain
->hash_size
= W (domain
->must_swap
, data
->hash_tab_size
);
205 domain
->hash_tab
= (nls_uint32
*)
206 ((char *) data
+ W (domain
->must_swap
, data
->hash_tab_offset
));
209 /* This is an invalid revision. */
212 munmap ((caddr_t
) data
, size
);
217 domain_file
->data
= NULL
;
221 /* Now find out about the character set the file is encoded with.
222 This can be found (in textual form) in the entry "". If this
223 entry does not exist or if this does not contain the `charset='
224 information, we will assume the charset matches the one the
225 current locale and we don't have to perform any conversion. */
227 domain
->conv
= (__gconv_t
) -1;
230 domain
->conv
= (iconv_t
) -1;
233 nullentry
= _nl_find_msg (domain_file
, "");
234 if (nullentry
!= NULL
)
236 char *charsetstr
= strstr (nullentry
, "charset=");
238 if (charsetstr
!= NULL
)
242 const char *outcharset
;
244 charsetstr
+= strlen ("charset=");
245 len
= strcspn (charsetstr
, " \t\n");
247 charset
= (char *) alloca (len
+ 1);
248 #if defined _LIBC || HAVE_MEMPCPY
249 *((char *) mempcpy (charset
, charsetstr
, len
)) = '\0';
251 memcpy (charset
, charsetstr
, len
);
255 /* The output charset should normally be determined by the
256 locale. But sometimes the locale is not used or not correctly
257 set up so we provide a possibility to override this. */
258 outcharset
= getenv ("OUTPUT_CHARSET");
259 if (outcharset
== NULL
|| outcharset
[0] == '\0')
260 outcharset
= (*_nl_current
[LC_CTYPE
])->values
[_NL_ITEM_INDEX (CODESET
)].string
;
263 if (__gconv_open (outcharset
, charset
, &domain
->conv
,
266 domain
->conv
= (__gconv_t
) -1;
269 domain
->conv
= iconv_open (outcharset
, charset
);
280 _nl_unload_domain (domain
)
281 struct loaded_domain
*domain
;
283 #ifdef _POSIX_MAPPED_FILES
284 if (domain
->use_mmap
)
285 munmap ((caddr_t
) domain
->data
, domain
->mmap_size
);
287 #endif /* _POSIX_MAPPED_FILES */
288 free ((void *) domain
->data
);