Update.
[glibc.git] / intl / loadmsgcat.c
blobba818ce3b116b7d24520aadd85f4a416c396542e
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. */
22 #ifdef HAVE_CONFIG_H
23 # include <config.h>
24 #endif
26 #include <fcntl.h>
27 #include <sys/types.h>
28 #include <sys/stat.h>
30 #if defined STDC_HEADERS || defined _LIBC
31 # include <stdlib.h>
32 #endif
34 #if defined HAVE_STRING_H || defined _LIBC
35 # ifndef _GNU_SOURCE
36 # define _GNU_SOURCE 1
37 # endif
38 # include <string.h>
39 #else
40 # include <strings.h>
41 #endif
43 #if defined HAVE_UNISTD_H || defined _LIBC
44 # include <unistd.h>
45 #endif
47 #ifdef _LIBC
48 # include <langinfo.h>
49 #endif
51 #if (defined HAVE_MMAP && defined HAVE_MUNMAP && !defined DISALLOW_MMAP) \
52 || (defined _LIBC && defined _POSIX_MAPPED_FILES)
53 # include <sys/mman.h>
54 # undef HAVE_MMAP
55 # define HAVE_MMAP 1
56 #else
57 # undef HAVE_MMAP
58 #endif
60 #include "gettext.h"
61 #include "gettextP.h"
63 #ifdef _LIBC
64 # include "../locale/localeinfo.h"
65 #endif
67 /* @@ end of prolog @@ */
69 #ifdef _LIBC
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. */
73 # define open __open
74 # define close __close
75 # define read __read
76 # define mmap __mmap
77 # define munmap __munmap
78 #endif
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. */
83 int _nl_msg_cat_cntr;
86 /* Load the message catalogs specified by FILENAME. If it is no valid
87 message catalog do nothing. */
88 void
89 internal_function
90 _nl_load_domain (domain_file)
91 struct loaded_l10nfile *domain_file;
93 int fd;
94 size_t size;
95 struct stat st;
96 struct mo_file_header *data = (struct mo_file_header *) -1;
97 int use_mmap = 0;
98 struct loaded_domain *domain;
99 char *nullentry;
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
107 syntax. */
108 if (domain_file->filename == NULL)
109 return;
111 /* Try to open the addressed file. */
112 fd = open (domain_file->filename, O_RDONLY);
113 if (fd == -1)
114 return;
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. */
122 close (fd);
123 return;
126 #ifdef HAVE_MMAP
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,
130 MAP_PRIVATE, fd, 0);
132 if (data != (struct mo_file_header *) -1)
134 /* mmap() call was successful. */
135 close (fd);
136 use_mmap = 1;
138 #endif
140 /* If the data is not yet available (i.e. mmap'ed) we try to load
141 it manually. */
142 if (data == (struct mo_file_header *) -1)
144 size_t to_read;
145 char *read_ptr;
147 data = (struct mo_file_header *) malloc (size);
148 if (data == NULL)
149 return;
151 to_read = size;
152 read_ptr = (char *) data;
155 long int nb = (long int) read (fd, read_ptr, to_read);
156 if (nb == -1)
158 close (fd);
159 return;
162 read_ptr += nb;
163 to_read -= nb;
165 while (to_read > 0);
167 close (fd);
170 /* Using the magic number we can test whether it really is a message
171 catalog file. */
172 if (data->magic != _MAGIC && data->magic != _MAGIC_SWAPPED)
174 /* The magic number is wrong: not a message catalog file. */
175 #ifdef HAVE_MMAP
176 if (use_mmap)
177 munmap ((caddr_t) data, size);
178 else
179 #endif
180 free (data);
181 return;
184 domain_file->data
185 = (struct loaded_domain *) malloc (sizeof (struct loaded_domain));
186 if (domain_file->data == NULL)
187 return;
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))
198 case 0:
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));
207 break;
208 default:
209 /* This is an invalid revision. */
210 #ifdef HAVE_MMAP
211 if (use_mmap)
212 munmap ((caddr_t) data, size);
213 else
214 #endif
215 free (data);
216 free (domain);
217 domain_file->data = NULL;
218 return;
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. */
226 #ifdef _LIBC
227 domain->conv = (__gconv_t) -1;
228 #else
229 # if HAVE_ICONV
230 domain->conv = (iconv_t) -1;
231 # endif
232 #endif
233 nullentry = _nl_find_msg (domain_file, "");
234 if (nullentry != NULL)
236 char *charsetstr = strstr (nullentry, "charset=");
238 if (charsetstr != NULL)
240 size_t len;
241 char *charset;
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';
250 #else
251 memcpy (charset, charsetstr, len);
252 charset[len] = '\0';
253 #endif
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;
262 #ifdef _LIBC
263 if (__gconv_open (outcharset, charset, &domain->conv,
264 GCONV_AVOID_NOCONV)
265 != __GCONV_OK)
266 domain->conv = (__gconv_t) -1;
267 #else
268 # if HAVE_ICONV
269 domain->conv = iconv_open (outcharset, charset);
270 # endif
271 #endif
277 #ifdef _LIBC
278 void
279 internal_function
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);
286 else
287 #endif /* _POSIX_MAPPED_FILES */
288 free ((void *) domain->data);
290 free (domain);
292 #endif