00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifndef _GNU_SOURCE
00023 # define _GNU_SOURCE 1
00024 #endif
00025
00026 #ifdef HAVE_CONFIG_H
00027 # include <config.h>
00028 #endif
00029
00030 #include <ctype.h>
00031 #include <errno.h>
00032 #include <fcntl.h>
00033 #include <sys/types.h>
00034 #include <sys/stat.h>
00035
00036 #ifdef __GNUC__
00037 # define alloca __builtin_alloca
00038 # define HAVE_ALLOCA 1
00039 #else
00040 # if defined HAVE_ALLOCA_H || defined _LIBC
00041 # include <alloca.h>
00042 # else
00043 # ifdef _AIX
00044 #pragma alloca
00045 # else
00046 # ifndef alloca
00047 char *alloca ();
00048 # endif
00049 # endif
00050 # endif
00051 #endif
00052
00053 #include <stdlib.h>
00054 #include <string.h>
00055
00056 #if defined HAVE_UNISTD_H || defined _LIBC
00057 # include <unistd.h>
00058 #endif
00059
00060 #ifdef _LIBC
00061 # include <langinfo.h>
00062 # include <locale.h>
00063 #endif
00064
00065 #if (defined HAVE_MMAP && defined HAVE_MUNMAP && !defined DISALLOW_MMAP) \
00066 || (defined _LIBC && defined _POSIX_MAPPED_FILES)
00067 # include <sys/mman.h>
00068 # undef HAVE_MMAP
00069 # define HAVE_MMAP 1
00070 #else
00071 # undef HAVE_MMAP
00072 #endif
00073
00074 #include "gmo.h"
00075 #include "gettextP.h"
00076 #include "plural-exp.h"
00077
00078 #ifdef _LIBC
00079 # include "../locale/localeinfo.h"
00080 #endif
00081
00082
00083
00084 #ifdef _LIBC
00085
00086
00087
00088 # define open __open
00089 # define close __close
00090 # define read __read
00091 # define mmap __mmap
00092 # define munmap __munmap
00093 #endif
00094
00095
00096
00097 #ifdef HAVE_ALLOCA
00098 # define freea(p)
00099 #else
00100 # define alloca(n) malloc (n)
00101 # define freea(p) free (p)
00102 #endif
00103
00104
00105
00106 #if !defined O_BINARY && defined _O_BINARY
00107
00108 # define O_BINARY _O_BINARY
00109 # define O_TEXT _O_TEXT
00110 #endif
00111 #ifdef __BEOS__
00112
00113 # undef O_BINARY
00114 # undef O_TEXT
00115 #endif
00116
00117 #ifndef O_BINARY
00118 # define O_BINARY 0
00119 #endif
00120
00121
00122
00123
00124 int _nl_msg_cat_cntr;
00125
00126
00127
00128
00129 const char *
00130 internal_function
00131 _nl_init_domain_conv (domain_file, domain, domainbinding)
00132 struct loaded_l10nfile *domain_file;
00133 struct loaded_domain *domain;
00134 struct binding *domainbinding;
00135 {
00136
00137
00138
00139
00140
00141 char *nullentry;
00142 size_t nullentrylen;
00143
00144
00145 domain->codeset_cntr =
00146 (domainbinding != NULL ? domainbinding->codeset_cntr : 0);
00147 #ifdef _LIBC
00148 domain->conv = (__gconv_t) -1;
00149 #else
00150 # if HAVE_ICONV
00151 domain->conv = (iconv_t) -1;
00152 # endif
00153 #endif
00154 domain->conv_tab = NULL;
00155
00156
00157 nullentry = _nl_find_msg (domain_file, domainbinding, "", &nullentrylen);
00158
00159 if (nullentry != NULL)
00160 {
00161 #if defined _LIBC || HAVE_ICONV
00162 const char *charsetstr;
00163
00164 charsetstr = strstr (nullentry, "charset=");
00165 if (charsetstr != NULL)
00166 {
00167 size_t len;
00168 char *charset;
00169 const char *outcharset;
00170
00171 charsetstr += strlen ("charset=");
00172 len = strcspn (charsetstr, " \t\n");
00173
00174 charset = (char *) alloca (len + 1);
00175 # if defined _LIBC || HAVE_MEMPCPY
00176 *((char *) mempcpy (charset, charsetstr, len)) = '\0';
00177 # else
00178 memcpy (charset, charsetstr, len);
00179 charset[len] = '\0';
00180 # endif
00181
00182
00183
00184
00185
00186
00187 if (domainbinding != NULL && domainbinding->codeset != NULL)
00188 outcharset = domainbinding->codeset;
00189 else
00190 {
00191 outcharset = getenv ("OUTPUT_CHARSET");
00192 if (outcharset == NULL || outcharset[0] == '\0')
00193 {
00194 # ifdef _LIBC
00195 outcharset = (*_nl_current[LC_CTYPE])->values[_NL_ITEM_INDEX (CODESET)].string;
00196 # else
00197 # if HAVE_ICONV
00198 extern const char *locale_charset PARAMS ((void));
00199 outcharset = locale_charset ();
00200 # endif
00201 # endif
00202 }
00203 }
00204
00205 # ifdef _LIBC
00206
00207 outcharset = norm_add_slashes (outcharset, "TRANSLIT");
00208 charset = norm_add_slashes (charset, NULL);
00209 if (__gconv_open (outcharset, charset, &domain->conv,
00210 GCONV_AVOID_NOCONV)
00211 != __GCONV_OK)
00212 domain->conv = (__gconv_t) -1;
00213 # else
00214 # if HAVE_ICONV
00215
00216
00217 # if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2) || __GLIBC__ > 2 \
00218 || _LIBICONV_VERSION >= 0x0105
00219 len = strlen (outcharset);
00220 {
00221 char *tmp = (char *) alloca (len + 10 + 1);
00222 memcpy (tmp, outcharset, len);
00223 memcpy (tmp + len, "//TRANSLIT", 10 + 1);
00224 outcharset = tmp;
00225 }
00226 # endif
00227 domain->conv = iconv_open (outcharset, charset);
00228 # if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2) || __GLIBC__ > 2 \
00229 || _LIBICONV_VERSION >= 0x0105
00230 freea (outcharset);
00231 # endif
00232 # endif
00233 # endif
00234
00235 freea (charset);
00236 }
00237 #endif
00238 }
00239
00240 return nullentry;
00241 }
00242
00243
00244 void
00245 internal_function
00246 _nl_free_domain_conv (domain)
00247 struct loaded_domain *domain;
00248 {
00249 if (domain->conv_tab != NULL && domain->conv_tab != (char **) -1)
00250 free (domain->conv_tab);
00251
00252 #ifdef _LIBC
00253 if (domain->conv != (__gconv_t) -1)
00254 __gconv_close (domain->conv);
00255 #else
00256 # if HAVE_ICONV
00257 if (domain->conv != (iconv_t) -1)
00258 iconv_close (domain->conv);
00259 # endif
00260 #endif
00261 }
00262
00263
00264
00265 void
00266 internal_function
00267 _nl_load_domain (domain_file, domainbinding)
00268 struct loaded_l10nfile *domain_file;
00269 struct binding *domainbinding;
00270 {
00271 int fd;
00272 size_t size;
00273 #ifdef _LIBC
00274 struct stat64 st;
00275 #else
00276 struct stat st;
00277 #endif
00278 struct mo_file_header *data = (struct mo_file_header *) -1;
00279 int use_mmap = 0;
00280 struct loaded_domain *domain;
00281 const char *nullentry;
00282
00283 domain_file->decided = 1;
00284 domain_file->data = NULL;
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294 if (domain_file->filename == NULL)
00295 return;
00296
00297
00298 fd = open (domain_file->filename, O_RDONLY | O_BINARY);
00299 if (fd == -1)
00300 return;
00301
00302
00303 if (
00304 #ifdef _LIBC
00305 __builtin_expect (fstat64 (fd, &st) != 0, 0)
00306 #else
00307 __builtin_expect (fstat (fd, &st) != 0, 0)
00308 #endif
00309 || __builtin_expect ((size = (size_t) st.st_size) != st.st_size, 0)
00310 || __builtin_expect (size < sizeof (struct mo_file_header), 0))
00311 {
00312
00313 close (fd);
00314 return;
00315 }
00316
00317 #ifdef HAVE_MMAP
00318
00319
00320 data = (struct mo_file_header *) mmap (NULL, size, PROT_READ,
00321 MAP_PRIVATE, fd, 0);
00322
00323 if (__builtin_expect (data != (struct mo_file_header *) -1, 1))
00324 {
00325
00326 close (fd);
00327 use_mmap = 1;
00328 }
00329 #endif
00330
00331
00332
00333 if (data == (struct mo_file_header *) -1)
00334 {
00335 size_t to_read;
00336 char *read_ptr;
00337
00338 data = (struct mo_file_header *) malloc (size);
00339 if (data == NULL)
00340 return;
00341
00342 to_read = size;
00343 read_ptr = (char *) data;
00344 do
00345 {
00346 long int nb = (long int) read (fd, read_ptr, to_read);
00347 if (nb <= 0)
00348 {
00349 #ifdef EINTR
00350 if (nb == -1 && errno == EINTR)
00351 continue;
00352 #endif
00353 close (fd);
00354 return;
00355 }
00356 read_ptr += nb;
00357 to_read -= nb;
00358 }
00359 while (to_read > 0);
00360
00361 close (fd);
00362 }
00363
00364
00365
00366 if (__builtin_expect (data->magic != _MAGIC && data->magic != _MAGIC_SWAPPED,
00367 0))
00368 {
00369
00370 #ifdef HAVE_MMAP
00371 if (use_mmap)
00372 munmap ((caddr_t) data, size);
00373 else
00374 #endif
00375 free (data);
00376 return;
00377 }
00378
00379 domain = (struct loaded_domain *) malloc (sizeof (struct loaded_domain));
00380 if (domain == NULL)
00381 return;
00382 domain_file->data = domain;
00383
00384 domain->data = (char *) data;
00385 domain->use_mmap = use_mmap;
00386 domain->mmap_size = size;
00387 domain->must_swap = data->magic != _MAGIC;
00388
00389
00390 switch (W (domain->must_swap, data->revision))
00391 {
00392 case 0:
00393 domain->nstrings = W (domain->must_swap, data->nstrings);
00394 domain->orig_tab = (struct string_desc *)
00395 ((char *) data + W (domain->must_swap, data->orig_tab_offset));
00396 domain->trans_tab = (struct string_desc *)
00397 ((char *) data + W (domain->must_swap, data->trans_tab_offset));
00398 domain->hash_size = W (domain->must_swap, data->hash_tab_size);
00399 domain->hash_tab = (nls_uint32 *)
00400 ((char *) data + W (domain->must_swap, data->hash_tab_offset));
00401 break;
00402 default:
00403
00404 #ifdef HAVE_MMAP
00405 if (use_mmap)
00406 munmap ((caddr_t) data, size);
00407 else
00408 #endif
00409 free (data);
00410 free (domain);
00411 domain_file->data = NULL;
00412 return;
00413 }
00414
00415
00416
00417
00418 nullentry = _nl_init_domain_conv (domain_file, domain, domainbinding);
00419
00420
00421 EXTRACT_PLURAL_EXPRESSION (nullentry, &domain->plural, &domain->nplurals);
00422 }
00423
00424
00425 #ifdef _LIBC
00426 void
00427 internal_function
00428 _nl_unload_domain (domain)
00429 struct loaded_domain *domain;
00430 {
00431 if (domain->plural != &__gettext_germanic_plural)
00432 __gettext_free_exp (domain->plural);
00433
00434 _nl_free_domain_conv (domain);
00435
00436 # ifdef _POSIX_MAPPED_FILES
00437 if (domain->use_mmap)
00438 munmap ((caddr_t) domain->data, domain->mmap_size);
00439 else
00440 # endif
00441 free ((void *) domain->data);
00442
00443 free (domain);
00444 }
00445 #endif