Home | History | Annotate | Line # | Download | only in intl
loadmsgcat.c revision 1.1
      1 /* Load needed message catalogs.
      2    Copyright (C) 1995-1999, 2000-2005 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 # undef  alloca
     38 # define alloca __builtin_alloca
     39 # define HAVE_ALLOCA 1
     40 #else
     41 # ifdef _MSC_VER
     42 #  include <malloc.h>
     43 #  define alloca _alloca
     44 # else
     45 #  if defined HAVE_ALLOCA_H || defined _LIBC
     46 #   include <alloca.h>
     47 #  else
     48 #   ifdef _AIX
     49  #pragma alloca
     50 #   else
     51 #    ifndef alloca
     52 char *alloca ();
     53 #    endif
     54 #   endif
     55 #  endif
     56 # endif
     57 #endif
     58 
     59 #include <stdlib.h>
     60 #include <string.h>
     61 
     62 #if defined HAVE_UNISTD_H || defined _LIBC
     63 # include <unistd.h>
     64 #endif
     65 
     66 #ifdef _LIBC
     67 # include <langinfo.h>
     68 # include <locale.h>
     69 #endif
     70 
     71 #if (defined HAVE_MMAP && defined HAVE_MUNMAP && !defined DISALLOW_MMAP) \
     72     || (defined _LIBC && defined _POSIX_MAPPED_FILES)
     73 # include <sys/mman.h>
     74 # undef HAVE_MMAP
     75 # define HAVE_MMAP	1
     76 #else
     77 # undef HAVE_MMAP
     78 #endif
     79 
     80 #if defined HAVE_STDINT_H_WITH_UINTMAX || defined _LIBC
     81 # include <stdint.h>
     82 #endif
     83 #if defined HAVE_INTTYPES_H || defined _LIBC
     84 # include <inttypes.h>
     85 #endif
     86 
     87 #include "gmo.h"
     88 #include "gettextP.h"
     89 #include "hash-string.h"
     90 #include "plural-exp.h"
     91 
     92 #ifdef _LIBC
     93 # include "../locale/localeinfo.h"
     94 # include <not-cancel.h>
     95 #endif
     96 
     97 /* Handle multi-threaded applications.  */
     98 #ifdef _LIBC
     99 # include <bits/libc-lock.h>
    100 #else
    101 # include "lock.h"
    102 #endif
    103 
    104 /* Provide fallback values for macros that ought to be defined in <inttypes.h>.
    105    Note that our fallback values need not be literal strings, because we don't
    106    use them with preprocessor string concatenation.  */
    107 #if !defined PRId8 || PRI_MACROS_BROKEN
    108 # undef PRId8
    109 # define PRId8 "d"
    110 #endif
    111 #if !defined PRIi8 || PRI_MACROS_BROKEN
    112 # undef PRIi8
    113 # define PRIi8 "i"
    114 #endif
    115 #if !defined PRIo8 || PRI_MACROS_BROKEN
    116 # undef PRIo8
    117 # define PRIo8 "o"
    118 #endif
    119 #if !defined PRIu8 || PRI_MACROS_BROKEN
    120 # undef PRIu8
    121 # define PRIu8 "u"
    122 #endif
    123 #if !defined PRIx8 || PRI_MACROS_BROKEN
    124 # undef PRIx8
    125 # define PRIx8 "x"
    126 #endif
    127 #if !defined PRIX8 || PRI_MACROS_BROKEN
    128 # undef PRIX8
    129 # define PRIX8 "X"
    130 #endif
    131 #if !defined PRId16 || PRI_MACROS_BROKEN
    132 # undef PRId16
    133 # define PRId16 "d"
    134 #endif
    135 #if !defined PRIi16 || PRI_MACROS_BROKEN
    136 # undef PRIi16
    137 # define PRIi16 "i"
    138 #endif
    139 #if !defined PRIo16 || PRI_MACROS_BROKEN
    140 # undef PRIo16
    141 # define PRIo16 "o"
    142 #endif
    143 #if !defined PRIu16 || PRI_MACROS_BROKEN
    144 # undef PRIu16
    145 # define PRIu16 "u"
    146 #endif
    147 #if !defined PRIx16 || PRI_MACROS_BROKEN
    148 # undef PRIx16
    149 # define PRIx16 "x"
    150 #endif
    151 #if !defined PRIX16 || PRI_MACROS_BROKEN
    152 # undef PRIX16
    153 # define PRIX16 "X"
    154 #endif
    155 #if !defined PRId32 || PRI_MACROS_BROKEN
    156 # undef PRId32
    157 # define PRId32 "d"
    158 #endif
    159 #if !defined PRIi32 || PRI_MACROS_BROKEN
    160 # undef PRIi32
    161 # define PRIi32 "i"
    162 #endif
    163 #if !defined PRIo32 || PRI_MACROS_BROKEN
    164 # undef PRIo32
    165 # define PRIo32 "o"
    166 #endif
    167 #if !defined PRIu32 || PRI_MACROS_BROKEN
    168 # undef PRIu32
    169 # define PRIu32 "u"
    170 #endif
    171 #if !defined PRIx32 || PRI_MACROS_BROKEN
    172 # undef PRIx32
    173 # define PRIx32 "x"
    174 #endif
    175 #if !defined PRIX32 || PRI_MACROS_BROKEN
    176 # undef PRIX32
    177 # define PRIX32 "X"
    178 #endif
    179 #if !defined PRId64 || PRI_MACROS_BROKEN
    180 # undef PRId64
    181 # define PRId64 (sizeof (long) == 8 ? "ld" : "lld")
    182 #endif
    183 #if !defined PRIi64 || PRI_MACROS_BROKEN
    184 # undef PRIi64
    185 # define PRIi64 (sizeof (long) == 8 ? "li" : "lli")
    186 #endif
    187 #if !defined PRIo64 || PRI_MACROS_BROKEN
    188 # undef PRIo64
    189 # define PRIo64 (sizeof (long) == 8 ? "lo" : "llo")
    190 #endif
    191 #if !defined PRIu64 || PRI_MACROS_BROKEN
    192 # undef PRIu64
    193 # define PRIu64 (sizeof (long) == 8 ? "lu" : "llu")
    194 #endif
    195 #if !defined PRIx64 || PRI_MACROS_BROKEN
    196 # undef PRIx64
    197 # define PRIx64 (sizeof (long) == 8 ? "lx" : "llx")
    198 #endif
    199 #if !defined PRIX64 || PRI_MACROS_BROKEN
    200 # undef PRIX64
    201 # define PRIX64 (sizeof (long) == 8 ? "lX" : "llX")
    202 #endif
    203 #if !defined PRIdLEAST8 || PRI_MACROS_BROKEN
    204 # undef PRIdLEAST8
    205 # define PRIdLEAST8 "d"
    206 #endif
    207 #if !defined PRIiLEAST8 || PRI_MACROS_BROKEN
    208 # undef PRIiLEAST8
    209 # define PRIiLEAST8 "i"
    210 #endif
    211 #if !defined PRIoLEAST8 || PRI_MACROS_BROKEN
    212 # undef PRIoLEAST8
    213 # define PRIoLEAST8 "o"
    214 #endif
    215 #if !defined PRIuLEAST8 || PRI_MACROS_BROKEN
    216 # undef PRIuLEAST8
    217 # define PRIuLEAST8 "u"
    218 #endif
    219 #if !defined PRIxLEAST8 || PRI_MACROS_BROKEN
    220 # undef PRIxLEAST8
    221 # define PRIxLEAST8 "x"
    222 #endif
    223 #if !defined PRIXLEAST8 || PRI_MACROS_BROKEN
    224 # undef PRIXLEAST8
    225 # define PRIXLEAST8 "X"
    226 #endif
    227 #if !defined PRIdLEAST16 || PRI_MACROS_BROKEN
    228 # undef PRIdLEAST16
    229 # define PRIdLEAST16 "d"
    230 #endif
    231 #if !defined PRIiLEAST16 || PRI_MACROS_BROKEN
    232 # undef PRIiLEAST16
    233 # define PRIiLEAST16 "i"
    234 #endif
    235 #if !defined PRIoLEAST16 || PRI_MACROS_BROKEN
    236 # undef PRIoLEAST16
    237 # define PRIoLEAST16 "o"
    238 #endif
    239 #if !defined PRIuLEAST16 || PRI_MACROS_BROKEN
    240 # undef PRIuLEAST16
    241 # define PRIuLEAST16 "u"
    242 #endif
    243 #if !defined PRIxLEAST16 || PRI_MACROS_BROKEN
    244 # undef PRIxLEAST16
    245 # define PRIxLEAST16 "x"
    246 #endif
    247 #if !defined PRIXLEAST16 || PRI_MACROS_BROKEN
    248 # undef PRIXLEAST16
    249 # define PRIXLEAST16 "X"
    250 #endif
    251 #if !defined PRIdLEAST32 || PRI_MACROS_BROKEN
    252 # undef PRIdLEAST32
    253 # define PRIdLEAST32 "d"
    254 #endif
    255 #if !defined PRIiLEAST32 || PRI_MACROS_BROKEN
    256 # undef PRIiLEAST32
    257 # define PRIiLEAST32 "i"
    258 #endif
    259 #if !defined PRIoLEAST32 || PRI_MACROS_BROKEN
    260 # undef PRIoLEAST32
    261 # define PRIoLEAST32 "o"
    262 #endif
    263 #if !defined PRIuLEAST32 || PRI_MACROS_BROKEN
    264 # undef PRIuLEAST32
    265 # define PRIuLEAST32 "u"
    266 #endif
    267 #if !defined PRIxLEAST32 || PRI_MACROS_BROKEN
    268 # undef PRIxLEAST32
    269 # define PRIxLEAST32 "x"
    270 #endif
    271 #if !defined PRIXLEAST32 || PRI_MACROS_BROKEN
    272 # undef PRIXLEAST32
    273 # define PRIXLEAST32 "X"
    274 #endif
    275 #if !defined PRIdLEAST64 || PRI_MACROS_BROKEN
    276 # undef PRIdLEAST64
    277 # define PRIdLEAST64 PRId64
    278 #endif
    279 #if !defined PRIiLEAST64 || PRI_MACROS_BROKEN
    280 # undef PRIiLEAST64
    281 # define PRIiLEAST64 PRIi64
    282 #endif
    283 #if !defined PRIoLEAST64 || PRI_MACROS_BROKEN
    284 # undef PRIoLEAST64
    285 # define PRIoLEAST64 PRIo64
    286 #endif
    287 #if !defined PRIuLEAST64 || PRI_MACROS_BROKEN
    288 # undef PRIuLEAST64
    289 # define PRIuLEAST64 PRIu64
    290 #endif
    291 #if !defined PRIxLEAST64 || PRI_MACROS_BROKEN
    292 # undef PRIxLEAST64
    293 # define PRIxLEAST64 PRIx64
    294 #endif
    295 #if !defined PRIXLEAST64 || PRI_MACROS_BROKEN
    296 # undef PRIXLEAST64
    297 # define PRIXLEAST64 PRIX64
    298 #endif
    299 #if !defined PRIdFAST8 || PRI_MACROS_BROKEN
    300 # undef PRIdFAST8
    301 # define PRIdFAST8 "d"
    302 #endif
    303 #if !defined PRIiFAST8 || PRI_MACROS_BROKEN
    304 # undef PRIiFAST8
    305 # define PRIiFAST8 "i"
    306 #endif
    307 #if !defined PRIoFAST8 || PRI_MACROS_BROKEN
    308 # undef PRIoFAST8
    309 # define PRIoFAST8 "o"
    310 #endif
    311 #if !defined PRIuFAST8 || PRI_MACROS_BROKEN
    312 # undef PRIuFAST8
    313 # define PRIuFAST8 "u"
    314 #endif
    315 #if !defined PRIxFAST8 || PRI_MACROS_BROKEN
    316 # undef PRIxFAST8
    317 # define PRIxFAST8 "x"
    318 #endif
    319 #if !defined PRIXFAST8 || PRI_MACROS_BROKEN
    320 # undef PRIXFAST8
    321 # define PRIXFAST8 "X"
    322 #endif
    323 #if !defined PRIdFAST16 || PRI_MACROS_BROKEN
    324 # undef PRIdFAST16
    325 # define PRIdFAST16 "d"
    326 #endif
    327 #if !defined PRIiFAST16 || PRI_MACROS_BROKEN
    328 # undef PRIiFAST16
    329 # define PRIiFAST16 "i"
    330 #endif
    331 #if !defined PRIoFAST16 || PRI_MACROS_BROKEN
    332 # undef PRIoFAST16
    333 # define PRIoFAST16 "o"
    334 #endif
    335 #if !defined PRIuFAST16 || PRI_MACROS_BROKEN
    336 # undef PRIuFAST16
    337 # define PRIuFAST16 "u"
    338 #endif
    339 #if !defined PRIxFAST16 || PRI_MACROS_BROKEN
    340 # undef PRIxFAST16
    341 # define PRIxFAST16 "x"
    342 #endif
    343 #if !defined PRIXFAST16 || PRI_MACROS_BROKEN
    344 # undef PRIXFAST16
    345 # define PRIXFAST16 "X"
    346 #endif
    347 #if !defined PRIdFAST32 || PRI_MACROS_BROKEN
    348 # undef PRIdFAST32
    349 # define PRIdFAST32 "d"
    350 #endif
    351 #if !defined PRIiFAST32 || PRI_MACROS_BROKEN
    352 # undef PRIiFAST32
    353 # define PRIiFAST32 "i"
    354 #endif
    355 #if !defined PRIoFAST32 || PRI_MACROS_BROKEN
    356 # undef PRIoFAST32
    357 # define PRIoFAST32 "o"
    358 #endif
    359 #if !defined PRIuFAST32 || PRI_MACROS_BROKEN
    360 # undef PRIuFAST32
    361 # define PRIuFAST32 "u"
    362 #endif
    363 #if !defined PRIxFAST32 || PRI_MACROS_BROKEN
    364 # undef PRIxFAST32
    365 # define PRIxFAST32 "x"
    366 #endif
    367 #if !defined PRIXFAST32 || PRI_MACROS_BROKEN
    368 # undef PRIXFAST32
    369 # define PRIXFAST32 "X"
    370 #endif
    371 #if !defined PRIdFAST64 || PRI_MACROS_BROKEN
    372 # undef PRIdFAST64
    373 # define PRIdFAST64 PRId64
    374 #endif
    375 #if !defined PRIiFAST64 || PRI_MACROS_BROKEN
    376 # undef PRIiFAST64
    377 # define PRIiFAST64 PRIi64
    378 #endif
    379 #if !defined PRIoFAST64 || PRI_MACROS_BROKEN
    380 # undef PRIoFAST64
    381 # define PRIoFAST64 PRIo64
    382 #endif
    383 #if !defined PRIuFAST64 || PRI_MACROS_BROKEN
    384 # undef PRIuFAST64
    385 # define PRIuFAST64 PRIu64
    386 #endif
    387 #if !defined PRIxFAST64 || PRI_MACROS_BROKEN
    388 # undef PRIxFAST64
    389 # define PRIxFAST64 PRIx64
    390 #endif
    391 #if !defined PRIXFAST64 || PRI_MACROS_BROKEN
    392 # undef PRIXFAST64
    393 # define PRIXFAST64 PRIX64
    394 #endif
    395 #if !defined PRIdMAX || PRI_MACROS_BROKEN
    396 # undef PRIdMAX
    397 # define PRIdMAX (sizeof (uintmax_t) == sizeof (long) ? "ld" : "lld")
    398 #endif
    399 #if !defined PRIiMAX || PRI_MACROS_BROKEN
    400 # undef PRIiMAX
    401 # define PRIiMAX (sizeof (uintmax_t) == sizeof (long) ? "li" : "lli")
    402 #endif
    403 #if !defined PRIoMAX || PRI_MACROS_BROKEN
    404 # undef PRIoMAX
    405 # define PRIoMAX (sizeof (uintmax_t) == sizeof (long) ? "lo" : "llo")
    406 #endif
    407 #if !defined PRIuMAX || PRI_MACROS_BROKEN
    408 # undef PRIuMAX
    409 # define PRIuMAX (sizeof (uintmax_t) == sizeof (long) ? "lu" : "llu")
    410 #endif
    411 #if !defined PRIxMAX || PRI_MACROS_BROKEN
    412 # undef PRIxMAX
    413 # define PRIxMAX (sizeof (uintmax_t) == sizeof (long) ? "lx" : "llx")
    414 #endif
    415 #if !defined PRIXMAX || PRI_MACROS_BROKEN
    416 # undef PRIXMAX
    417 # define PRIXMAX (sizeof (uintmax_t) == sizeof (long) ? "lX" : "llX")
    418 #endif
    419 #if !defined PRIdPTR || PRI_MACROS_BROKEN
    420 # undef PRIdPTR
    421 # define PRIdPTR \
    422   (sizeof (void *) == sizeof (long) ? "ld" : \
    423    sizeof (void *) == sizeof (int) ? "d" : \
    424    "lld")
    425 #endif
    426 #if !defined PRIiPTR || PRI_MACROS_BROKEN
    427 # undef PRIiPTR
    428 # define PRIiPTR \
    429   (sizeof (void *) == sizeof (long) ? "li" : \
    430    sizeof (void *) == sizeof (int) ? "i" : \
    431    "lli")
    432 #endif
    433 #if !defined PRIoPTR || PRI_MACROS_BROKEN
    434 # undef PRIoPTR
    435 # define PRIoPTR \
    436   (sizeof (void *) == sizeof (long) ? "lo" : \
    437    sizeof (void *) == sizeof (int) ? "o" : \
    438    "llo")
    439 #endif
    440 #if !defined PRIuPTR || PRI_MACROS_BROKEN
    441 # undef PRIuPTR
    442 # define PRIuPTR \
    443   (sizeof (void *) == sizeof (long) ? "lu" : \
    444    sizeof (void *) == sizeof (int) ? "u" : \
    445    "llu")
    446 #endif
    447 #if !defined PRIxPTR || PRI_MACROS_BROKEN
    448 # undef PRIxPTR
    449 # define PRIxPTR \
    450   (sizeof (void *) == sizeof (long) ? "lx" : \
    451    sizeof (void *) == sizeof (int) ? "x" : \
    452    "llx")
    453 #endif
    454 #if !defined PRIXPTR || PRI_MACROS_BROKEN
    455 # undef PRIXPTR
    456 # define PRIXPTR \
    457   (sizeof (void *) == sizeof (long) ? "lX" : \
    458    sizeof (void *) == sizeof (int) ? "X" : \
    459    "llX")
    460 #endif
    461 
    462 /* @@ end of prolog @@ */
    463 
    464 #ifdef _LIBC
    465 /* Rename the non ISO C functions.  This is required by the standard
    466    because some ISO C functions will require linking with this object
    467    file and the name space must not be polluted.  */
    468 # define open(name, flags)	open_not_cancel_2 (name, flags)
    469 # define close(fd)		close_not_cancel_no_status (fd)
    470 # define read(fd, buf, n)	read_not_cancel (fd, buf, n)
    471 # define mmap(addr, len, prot, flags, fd, offset) \
    472   __mmap (addr, len, prot, flags, fd, offset)
    473 # define munmap(addr, len)	__munmap (addr, len)
    474 #endif
    475 
    476 /* For those losing systems which don't have `alloca' we have to add
    477    some additional code emulating it.  */
    478 #ifdef HAVE_ALLOCA
    479 # define freea(p) /* nothing */
    480 #else
    481 # define alloca(n) malloc (n)
    482 # define freea(p) free (p)
    483 #endif
    484 
    485 /* For systems that distinguish between text and binary I/O.
    486    O_BINARY is usually declared in <fcntl.h>. */
    487 #if !defined O_BINARY && defined _O_BINARY
    488   /* For MSC-compatible compilers.  */
    489 # define O_BINARY _O_BINARY
    490 # define O_TEXT _O_TEXT
    491 #endif
    492 #ifdef __BEOS__
    493   /* BeOS 5 has O_BINARY and O_TEXT, but they have no effect.  */
    494 # undef O_BINARY
    495 # undef O_TEXT
    496 #endif
    497 /* On reasonable systems, binary I/O is the default.  */
    498 #ifndef O_BINARY
    499 # define O_BINARY 0
    500 #endif
    501 
    502 
    503 /* We need a sign, whether a new catalog was loaded, which can be associated
    504    with all translations.  This is important if the translations are
    505    cached by one of GCC's features.  */
    506 int _nl_msg_cat_cntr;
    507 
    508 
    509 /* Expand a system dependent string segment.  Return NULL if unsupported.  */
    510 static const char *
    511 get_sysdep_segment_value (const char *name)
    512 {
    513   /* Test for an ISO C 99 section 7.8.1 format string directive.
    514      Syntax:
    515      P R I { d | i | o | u | x | X }
    516      { { | LEAST | FAST } { 8 | 16 | 32 | 64 } | MAX | PTR }  */
    517   /* We don't use a table of 14 times 6 'const char *' strings here, because
    518      data relocations cost startup time.  */
    519   if (name[0] == 'P' && name[1] == 'R' && name[2] == 'I')
    520     {
    521       if (name[3] == 'd' || name[3] == 'i' || name[3] == 'o' || name[3] == 'u'
    522 	  || name[3] == 'x' || name[3] == 'X')
    523 	{
    524 	  if (name[4] == '8' && name[5] == '\0')
    525 	    {
    526 	      if (name[3] == 'd')
    527 		return PRId8;
    528 	      if (name[3] == 'i')
    529 		return PRIi8;
    530 	      if (name[3] == 'o')
    531 		return PRIo8;
    532 	      if (name[3] == 'u')
    533 		return PRIu8;
    534 	      if (name[3] == 'x')
    535 		return PRIx8;
    536 	      if (name[3] == 'X')
    537 		return PRIX8;
    538 	      abort ();
    539 	    }
    540 	  if (name[4] == '1' && name[5] == '6' && name[6] == '\0')
    541 	    {
    542 	      if (name[3] == 'd')
    543 		return PRId16;
    544 	      if (name[3] == 'i')
    545 		return PRIi16;
    546 	      if (name[3] == 'o')
    547 		return PRIo16;
    548 	      if (name[3] == 'u')
    549 		return PRIu16;
    550 	      if (name[3] == 'x')
    551 		return PRIx16;
    552 	      if (name[3] == 'X')
    553 		return PRIX16;
    554 	      abort ();
    555 	    }
    556 	  if (name[4] == '3' && name[5] == '2' && name[6] == '\0')
    557 	    {
    558 	      if (name[3] == 'd')
    559 		return PRId32;
    560 	      if (name[3] == 'i')
    561 		return PRIi32;
    562 	      if (name[3] == 'o')
    563 		return PRIo32;
    564 	      if (name[3] == 'u')
    565 		return PRIu32;
    566 	      if (name[3] == 'x')
    567 		return PRIx32;
    568 	      if (name[3] == 'X')
    569 		return PRIX32;
    570 	      abort ();
    571 	    }
    572 	  if (name[4] == '6' && name[5] == '4' && name[6] == '\0')
    573 	    {
    574 	      if (name[3] == 'd')
    575 		return PRId64;
    576 	      if (name[3] == 'i')
    577 		return PRIi64;
    578 	      if (name[3] == 'o')
    579 		return PRIo64;
    580 	      if (name[3] == 'u')
    581 		return PRIu64;
    582 	      if (name[3] == 'x')
    583 		return PRIx64;
    584 	      if (name[3] == 'X')
    585 		return PRIX64;
    586 	      abort ();
    587 	    }
    588 	  if (name[4] == 'L' && name[5] == 'E' && name[6] == 'A'
    589 	      && name[7] == 'S' && name[8] == 'T')
    590 	    {
    591 	      if (name[9] == '8' && name[10] == '\0')
    592 		{
    593 		  if (name[3] == 'd')
    594 		    return PRIdLEAST8;
    595 		  if (name[3] == 'i')
    596 		    return PRIiLEAST8;
    597 		  if (name[3] == 'o')
    598 		    return PRIoLEAST8;
    599 		  if (name[3] == 'u')
    600 		    return PRIuLEAST8;
    601 		  if (name[3] == 'x')
    602 		    return PRIxLEAST8;
    603 		  if (name[3] == 'X')
    604 		    return PRIXLEAST8;
    605 		  abort ();
    606 		}
    607 	      if (name[9] == '1' && name[10] == '6' && name[11] == '\0')
    608 		{
    609 		  if (name[3] == 'd')
    610 		    return PRIdLEAST16;
    611 		  if (name[3] == 'i')
    612 		    return PRIiLEAST16;
    613 		  if (name[3] == 'o')
    614 		    return PRIoLEAST16;
    615 		  if (name[3] == 'u')
    616 		    return PRIuLEAST16;
    617 		  if (name[3] == 'x')
    618 		    return PRIxLEAST16;
    619 		  if (name[3] == 'X')
    620 		    return PRIXLEAST16;
    621 		  abort ();
    622 		}
    623 	      if (name[9] == '3' && name[10] == '2' && name[11] == '\0')
    624 		{
    625 		  if (name[3] == 'd')
    626 		    return PRIdLEAST32;
    627 		  if (name[3] == 'i')
    628 		    return PRIiLEAST32;
    629 		  if (name[3] == 'o')
    630 		    return PRIoLEAST32;
    631 		  if (name[3] == 'u')
    632 		    return PRIuLEAST32;
    633 		  if (name[3] == 'x')
    634 		    return PRIxLEAST32;
    635 		  if (name[3] == 'X')
    636 		    return PRIXLEAST32;
    637 		  abort ();
    638 		}
    639 	      if (name[9] == '6' && name[10] == '4' && name[11] == '\0')
    640 		{
    641 		  if (name[3] == 'd')
    642 		    return PRIdLEAST64;
    643 		  if (name[3] == 'i')
    644 		    return PRIiLEAST64;
    645 		  if (name[3] == 'o')
    646 		    return PRIoLEAST64;
    647 		  if (name[3] == 'u')
    648 		    return PRIuLEAST64;
    649 		  if (name[3] == 'x')
    650 		    return PRIxLEAST64;
    651 		  if (name[3] == 'X')
    652 		    return PRIXLEAST64;
    653 		  abort ();
    654 		}
    655 	    }
    656 	  if (name[4] == 'F' && name[5] == 'A' && name[6] == 'S'
    657 	      && name[7] == 'T')
    658 	    {
    659 	      if (name[8] == '8' && name[9] == '\0')
    660 		{
    661 		  if (name[3] == 'd')
    662 		    return PRIdFAST8;
    663 		  if (name[3] == 'i')
    664 		    return PRIiFAST8;
    665 		  if (name[3] == 'o')
    666 		    return PRIoFAST8;
    667 		  if (name[3] == 'u')
    668 		    return PRIuFAST8;
    669 		  if (name[3] == 'x')
    670 		    return PRIxFAST8;
    671 		  if (name[3] == 'X')
    672 		    return PRIXFAST8;
    673 		  abort ();
    674 		}
    675 	      if (name[8] == '1' && name[9] == '6' && name[10] == '\0')
    676 		{
    677 		  if (name[3] == 'd')
    678 		    return PRIdFAST16;
    679 		  if (name[3] == 'i')
    680 		    return PRIiFAST16;
    681 		  if (name[3] == 'o')
    682 		    return PRIoFAST16;
    683 		  if (name[3] == 'u')
    684 		    return PRIuFAST16;
    685 		  if (name[3] == 'x')
    686 		    return PRIxFAST16;
    687 		  if (name[3] == 'X')
    688 		    return PRIXFAST16;
    689 		  abort ();
    690 		}
    691 	      if (name[8] == '3' && name[9] == '2' && name[10] == '\0')
    692 		{
    693 		  if (name[3] == 'd')
    694 		    return PRIdFAST32;
    695 		  if (name[3] == 'i')
    696 		    return PRIiFAST32;
    697 		  if (name[3] == 'o')
    698 		    return PRIoFAST32;
    699 		  if (name[3] == 'u')
    700 		    return PRIuFAST32;
    701 		  if (name[3] == 'x')
    702 		    return PRIxFAST32;
    703 		  if (name[3] == 'X')
    704 		    return PRIXFAST32;
    705 		  abort ();
    706 		}
    707 	      if (name[8] == '6' && name[9] == '4' && name[10] == '\0')
    708 		{
    709 		  if (name[3] == 'd')
    710 		    return PRIdFAST64;
    711 		  if (name[3] == 'i')
    712 		    return PRIiFAST64;
    713 		  if (name[3] == 'o')
    714 		    return PRIoFAST64;
    715 		  if (name[3] == 'u')
    716 		    return PRIuFAST64;
    717 		  if (name[3] == 'x')
    718 		    return PRIxFAST64;
    719 		  if (name[3] == 'X')
    720 		    return PRIXFAST64;
    721 		  abort ();
    722 		}
    723 	    }
    724 	  if (name[4] == 'M' && name[5] == 'A' && name[6] == 'X'
    725 	      && name[7] == '\0')
    726 	    {
    727 	      if (name[3] == 'd')
    728 		return PRIdMAX;
    729 	      if (name[3] == 'i')
    730 		return PRIiMAX;
    731 	      if (name[3] == 'o')
    732 		return PRIoMAX;
    733 	      if (name[3] == 'u')
    734 		return PRIuMAX;
    735 	      if (name[3] == 'x')
    736 		return PRIxMAX;
    737 	      if (name[3] == 'X')
    738 		return PRIXMAX;
    739 	      abort ();
    740 	    }
    741 	  if (name[4] == 'P' && name[5] == 'T' && name[6] == 'R'
    742 	      && name[7] == '\0')
    743 	    {
    744 	      if (name[3] == 'd')
    745 		return PRIdPTR;
    746 	      if (name[3] == 'i')
    747 		return PRIiPTR;
    748 	      if (name[3] == 'o')
    749 		return PRIoPTR;
    750 	      if (name[3] == 'u')
    751 		return PRIuPTR;
    752 	      if (name[3] == 'x')
    753 		return PRIxPTR;
    754 	      if (name[3] == 'X')
    755 		return PRIXPTR;
    756 	      abort ();
    757 	    }
    758 	}
    759     }
    760   /* Test for a glibc specific printf() format directive flag.  */
    761   if (name[0] == 'I' && name[1] == '\0')
    762     {
    763 #if defined _LIBC || __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2)
    764       /* The 'I' flag, in numeric format directives, replaces ASCII digits
    765 	 with the 'outdigits' defined in the LC_CTYPE locale facet.  This is
    766 	 used for Farsi (Persian) and maybe Arabic.  */
    767       return "I";
    768 #else
    769       return "";
    770 #endif
    771     }
    772   /* Other system dependent strings are not valid.  */
    773   return NULL;
    774 }
    775 
    776 /* Load the message catalogs specified by FILENAME.  If it is no valid
    777    message catalog do nothing.  */
    778 void
    779 internal_function
    780 _nl_load_domain (struct loaded_l10nfile *domain_file,
    781 		 struct binding *domainbinding)
    782 {
    783   __libc_lock_define_initialized_recursive (static, lock)
    784   int fd = -1;
    785   size_t size;
    786 #ifdef _LIBC
    787   struct stat64 st;
    788 #else
    789   struct stat st;
    790 #endif
    791   struct mo_file_header *data = (struct mo_file_header *) -1;
    792   int use_mmap = 0;
    793   struct loaded_domain *domain;
    794   int revision;
    795   const char *nullentry;
    796   size_t nullentrylen;
    797 
    798   __libc_lock_lock_recursive (lock);
    799   if (domain_file->decided != 0)
    800     {
    801       /* There are two possibilities:
    802 
    803 	 + this is the same thread calling again during this initialization
    804 	   via _nl_find_msg.  We have initialized everything this call needs.
    805 
    806 	 + this is another thread which tried to initialize this object.
    807 	   Not necessary anymore since if the lock is available this
    808 	   is finished.
    809       */
    810       goto done;
    811     }
    812 
    813   domain_file->decided = -1;
    814   domain_file->data = NULL;
    815 
    816   /* Note that it would be useless to store domainbinding in domain_file
    817      because domainbinding might be == NULL now but != NULL later (after
    818      a call to bind_textdomain_codeset).  */
    819 
    820   /* If the record does not represent a valid locale the FILENAME
    821      might be NULL.  This can happen when according to the given
    822      specification the locale file name is different for XPG and CEN
    823      syntax.  */
    824   if (domain_file->filename == NULL)
    825     goto out;
    826 
    827   /* Try to open the addressed file.  */
    828   fd = open (domain_file->filename, O_RDONLY | O_BINARY);
    829   if (fd == -1)
    830     goto out;
    831 
    832   /* We must know about the size of the file.  */
    833   if (
    834 #ifdef _LIBC
    835       __builtin_expect (fstat64 (fd, &st) != 0, 0)
    836 #else
    837       __builtin_expect (fstat (fd, &st) != 0, 0)
    838 #endif
    839       || __builtin_expect ((size = (size_t) st.st_size) != st.st_size, 0)
    840       || __builtin_expect (size < sizeof (struct mo_file_header), 0))
    841     /* Something went wrong.  */
    842     goto out;
    843 
    844 #ifdef HAVE_MMAP
    845   /* Now we are ready to load the file.  If mmap() is available we try
    846      this first.  If not available or it failed we try to load it.  */
    847   data = (struct mo_file_header *) mmap (NULL, size, PROT_READ,
    848 					 MAP_PRIVATE, fd, 0);
    849 
    850   if (__builtin_expect (data != (struct mo_file_header *) -1, 1))
    851     {
    852       /* mmap() call was successful.  */
    853       close (fd);
    854       fd = -1;
    855       use_mmap = 1;
    856     }
    857 #endif
    858 
    859   /* If the data is not yet available (i.e. mmap'ed) we try to load
    860      it manually.  */
    861   if (data == (struct mo_file_header *) -1)
    862     {
    863       size_t to_read;
    864       char *read_ptr;
    865 
    866       data = (struct mo_file_header *) malloc (size);
    867       if (data == NULL)
    868 	goto out;
    869 
    870       to_read = size;
    871       read_ptr = (char *) data;
    872       do
    873 	{
    874 	  long int nb = (long int) read (fd, read_ptr, to_read);
    875 	  if (nb <= 0)
    876 	    {
    877 #ifdef EINTR
    878 	      if (nb == -1 && errno == EINTR)
    879 		continue;
    880 #endif
    881 	      goto out;
    882 	    }
    883 	  read_ptr += nb;
    884 	  to_read -= nb;
    885 	}
    886       while (to_read > 0);
    887 
    888       close (fd);
    889       fd = -1;
    890     }
    891 
    892   /* Using the magic number we can test whether it really is a message
    893      catalog file.  */
    894   if (__builtin_expect (data->magic != _MAGIC && data->magic != _MAGIC_SWAPPED,
    895 			0))
    896     {
    897       /* The magic number is wrong: not a message catalog file.  */
    898 #ifdef HAVE_MMAP
    899       if (use_mmap)
    900 	munmap ((caddr_t) data, size);
    901       else
    902 #endif
    903 	free (data);
    904       goto out;
    905     }
    906 
    907   domain = (struct loaded_domain *) malloc (sizeof (struct loaded_domain));
    908   if (domain == NULL)
    909     goto out;
    910   domain_file->data = domain;
    911 
    912   domain->data = (char *) data;
    913   domain->use_mmap = use_mmap;
    914   domain->mmap_size = size;
    915   domain->must_swap = data->magic != _MAGIC;
    916   domain->malloced = NULL;
    917 
    918   /* Fill in the information about the available tables.  */
    919   revision = W (domain->must_swap, data->revision);
    920   /* We support only the major revisions 0 and 1.  */
    921   switch (revision >> 16)
    922     {
    923     case 0:
    924     case 1:
    925       domain->nstrings = W (domain->must_swap, data->nstrings);
    926       domain->orig_tab = (const struct string_desc *)
    927 	((char *) data + W (domain->must_swap, data->orig_tab_offset));
    928       domain->trans_tab = (const struct string_desc *)
    929 	((char *) data + W (domain->must_swap, data->trans_tab_offset));
    930       domain->hash_size = W (domain->must_swap, data->hash_tab_size);
    931       domain->hash_tab =
    932 	(domain->hash_size > 2
    933 	 ? (const nls_uint32 *)
    934 	   ((char *) data + W (domain->must_swap, data->hash_tab_offset))
    935 	 : NULL);
    936       domain->must_swap_hash_tab = domain->must_swap;
    937 
    938       /* Now dispatch on the minor revision.  */
    939       switch (revision & 0xffff)
    940 	{
    941 	case 0:
    942 	  domain->n_sysdep_strings = 0;
    943 	  domain->orig_sysdep_tab = NULL;
    944 	  domain->trans_sysdep_tab = NULL;
    945 	  break;
    946 	case 1:
    947 	default:
    948 	  {
    949 	    nls_uint32 n_sysdep_strings;
    950 
    951 	    if (domain->hash_tab == NULL)
    952 	      /* This is invalid.  These minor revisions need a hash table.  */
    953 	      goto invalid;
    954 
    955 	    n_sysdep_strings =
    956 	      W (domain->must_swap, data->n_sysdep_strings);
    957 	    if (n_sysdep_strings > 0)
    958 	      {
    959 		nls_uint32 n_sysdep_segments;
    960 		const struct sysdep_segment *sysdep_segments;
    961 		const char **sysdep_segment_values;
    962 		const nls_uint32 *orig_sysdep_tab;
    963 		const nls_uint32 *trans_sysdep_tab;
    964 		nls_uint32 n_inmem_sysdep_strings;
    965 		size_t memneed;
    966 		char *mem;
    967 		struct sysdep_string_desc *inmem_orig_sysdep_tab;
    968 		struct sysdep_string_desc *inmem_trans_sysdep_tab;
    969 		nls_uint32 *inmem_hash_tab;
    970 		unsigned int i, j;
    971 
    972 		/* Get the values of the system dependent segments.  */
    973 		n_sysdep_segments =
    974 		  W (domain->must_swap, data->n_sysdep_segments);
    975 		sysdep_segments = (const struct sysdep_segment *)
    976 		  ((char *) data
    977 		   + W (domain->must_swap, data->sysdep_segments_offset));
    978 		sysdep_segment_values =
    979 		  alloca (n_sysdep_segments * sizeof (const char *));
    980 		for (i = 0; i < n_sysdep_segments; i++)
    981 		  {
    982 		    const char *name =
    983 		      (char *) data
    984 		      + W (domain->must_swap, sysdep_segments[i].offset);
    985 		    nls_uint32 namelen =
    986 		      W (domain->must_swap, sysdep_segments[i].length);
    987 
    988 		    if (!(namelen > 0 && name[namelen - 1] == '\0'))
    989 		      {
    990 			freea (sysdep_segment_values);
    991 			goto invalid;
    992 		      }
    993 
    994 		    sysdep_segment_values[i] = get_sysdep_segment_value (name);
    995 		  }
    996 
    997 		orig_sysdep_tab = (const nls_uint32 *)
    998 		  ((char *) data
    999 		   + W (domain->must_swap, data->orig_sysdep_tab_offset));
   1000 		trans_sysdep_tab = (const nls_uint32 *)
   1001 		  ((char *) data
   1002 		   + W (domain->must_swap, data->trans_sysdep_tab_offset));
   1003 
   1004 		/* Compute the amount of additional memory needed for the
   1005 		   system dependent strings and the augmented hash table.
   1006 		   At the same time, also drop string pairs which refer to
   1007 		   an undefined system dependent segment.  */
   1008 		n_inmem_sysdep_strings = 0;
   1009 		memneed = domain->hash_size * sizeof (nls_uint32);
   1010 		for (i = 0; i < n_sysdep_strings; i++)
   1011 		  {
   1012 		    int valid = 1;
   1013 		    size_t needs[2];
   1014 
   1015 		    for (j = 0; j < 2; j++)
   1016 		      {
   1017 			const struct sysdep_string *sysdep_string =
   1018 			  (const struct sysdep_string *)
   1019 			  ((char *) data
   1020 			   + W (domain->must_swap,
   1021 				j == 0
   1022 				? orig_sysdep_tab[i]
   1023 				: trans_sysdep_tab[i]));
   1024 			size_t need = 0;
   1025 			const struct segment_pair *p = sysdep_string->segments;
   1026 
   1027 			if (W (domain->must_swap, p->sysdepref) != SEGMENTS_END)
   1028 			  for (p = sysdep_string->segments;; p++)
   1029 			    {
   1030 			      nls_uint32 sysdepref;
   1031 
   1032 			      need += W (domain->must_swap, p->segsize);
   1033 
   1034 			      sysdepref = W (domain->must_swap, p->sysdepref);
   1035 			      if (sysdepref == SEGMENTS_END)
   1036 				break;
   1037 
   1038 			      if (sysdepref >= n_sysdep_segments)
   1039 				{
   1040 				  /* Invalid.  */
   1041 				  freea (sysdep_segment_values);
   1042 				  goto invalid;
   1043 				}
   1044 
   1045 			      if (sysdep_segment_values[sysdepref] == NULL)
   1046 				{
   1047 				  /* This particular string pair is invalid.  */
   1048 				  valid = 0;
   1049 				  break;
   1050 				}
   1051 
   1052 			      need += strlen (sysdep_segment_values[sysdepref]);
   1053 			    }
   1054 
   1055 			needs[j] = need;
   1056 			if (!valid)
   1057 			  break;
   1058 		      }
   1059 
   1060 		    if (valid)
   1061 		      {
   1062 			n_inmem_sysdep_strings++;
   1063 			memneed += needs[0] + needs[1];
   1064 		      }
   1065 		  }
   1066 		memneed += 2 * n_inmem_sysdep_strings
   1067 			   * sizeof (struct sysdep_string_desc);
   1068 
   1069 		if (n_inmem_sysdep_strings > 0)
   1070 		  {
   1071 		    unsigned int k;
   1072 
   1073 		    /* Allocate additional memory.  */
   1074 		    mem = (char *) malloc (memneed);
   1075 		    if (mem == NULL)
   1076 		      goto invalid;
   1077 
   1078 		    domain->malloced = mem;
   1079 		    inmem_orig_sysdep_tab = (struct sysdep_string_desc *) mem;
   1080 		    mem += n_inmem_sysdep_strings
   1081 			   * sizeof (struct sysdep_string_desc);
   1082 		    inmem_trans_sysdep_tab = (struct sysdep_string_desc *) mem;
   1083 		    mem += n_inmem_sysdep_strings
   1084 			   * sizeof (struct sysdep_string_desc);
   1085 		    inmem_hash_tab = (nls_uint32 *) mem;
   1086 		    mem += domain->hash_size * sizeof (nls_uint32);
   1087 
   1088 		    /* Compute the system dependent strings.  */
   1089 		    k = 0;
   1090 		    for (i = 0; i < n_sysdep_strings; i++)
   1091 		      {
   1092 			int valid = 1;
   1093 
   1094 			for (j = 0; j < 2; j++)
   1095 			  {
   1096 			    const struct sysdep_string *sysdep_string =
   1097 			      (const struct sysdep_string *)
   1098 			      ((char *) data
   1099 			       + W (domain->must_swap,
   1100 				    j == 0
   1101 				    ? orig_sysdep_tab[i]
   1102 				    : trans_sysdep_tab[i]));
   1103 			    const struct segment_pair *p =
   1104 			      sysdep_string->segments;
   1105 
   1106 			    if (W (domain->must_swap, p->sysdepref)
   1107 				!= SEGMENTS_END)
   1108 			      for (p = sysdep_string->segments;; p++)
   1109 				{
   1110 				  nls_uint32 sysdepref;
   1111 
   1112 				  sysdepref =
   1113 				    W (domain->must_swap, p->sysdepref);
   1114 				  if (sysdepref == SEGMENTS_END)
   1115 				    break;
   1116 
   1117 				  if (sysdep_segment_values[sysdepref] == NULL)
   1118 				    {
   1119 				      /* This particular string pair is
   1120 					 invalid.  */
   1121 				      valid = 0;
   1122 				      break;
   1123 				    }
   1124 				}
   1125 
   1126 			    if (!valid)
   1127 			      break;
   1128 			  }
   1129 
   1130 			if (valid)
   1131 			  {
   1132 			    for (j = 0; j < 2; j++)
   1133 			      {
   1134 				const struct sysdep_string *sysdep_string =
   1135 				  (const struct sysdep_string *)
   1136 				  ((char *) data
   1137 				   + W (domain->must_swap,
   1138 					j == 0
   1139 					? orig_sysdep_tab[i]
   1140 					: trans_sysdep_tab[i]));
   1141 				const char *static_segments =
   1142 				  (char *) data
   1143 				  + W (domain->must_swap, sysdep_string->offset);
   1144 				const struct segment_pair *p =
   1145 				  sysdep_string->segments;
   1146 
   1147 				/* Concatenate the segments, and fill
   1148 				   inmem_orig_sysdep_tab[k] (for j == 0) and
   1149 				   inmem_trans_sysdep_tab[k] (for j == 1).  */
   1150 
   1151 				struct sysdep_string_desc *inmem_tab_entry =
   1152 				  (j == 0
   1153 				   ? inmem_orig_sysdep_tab
   1154 				   : inmem_trans_sysdep_tab)
   1155 				  + k;
   1156 
   1157 				if (W (domain->must_swap, p->sysdepref)
   1158 				    == SEGMENTS_END)
   1159 				  {
   1160 				    /* Only one static segment.  */
   1161 				    inmem_tab_entry->length =
   1162 				      W (domain->must_swap, p->segsize);
   1163 				    inmem_tab_entry->pointer = static_segments;
   1164 				  }
   1165 				else
   1166 				  {
   1167 				    inmem_tab_entry->pointer = mem;
   1168 
   1169 				    for (p = sysdep_string->segments;; p++)
   1170 				      {
   1171 					nls_uint32 segsize =
   1172 					  W (domain->must_swap, p->segsize);
   1173 					nls_uint32 sysdepref =
   1174 					  W (domain->must_swap, p->sysdepref);
   1175 					size_t n;
   1176 
   1177 					if (segsize > 0)
   1178 					  {
   1179 					    memcpy (mem, static_segments, segsize);
   1180 					    mem += segsize;
   1181 					    static_segments += segsize;
   1182 					  }
   1183 
   1184 					if (sysdepref == SEGMENTS_END)
   1185 					  break;
   1186 
   1187 					n = strlen (sysdep_segment_values[sysdepref]);
   1188 					memcpy (mem, sysdep_segment_values[sysdepref], n);
   1189 					mem += n;
   1190 				      }
   1191 
   1192 				    inmem_tab_entry->length =
   1193 				      mem - inmem_tab_entry->pointer;
   1194 				  }
   1195 			      }
   1196 
   1197 			    k++;
   1198 			  }
   1199 		      }
   1200 		    if (k != n_inmem_sysdep_strings)
   1201 		      abort ();
   1202 
   1203 		    /* Compute the augmented hash table.  */
   1204 		    for (i = 0; i < domain->hash_size; i++)
   1205 		      inmem_hash_tab[i] =
   1206 			W (domain->must_swap_hash_tab, domain->hash_tab[i]);
   1207 		    for (i = 0; i < n_inmem_sysdep_strings; i++)
   1208 		      {
   1209 			const char *msgid = inmem_orig_sysdep_tab[i].pointer;
   1210 			nls_uint32 hash_val = __hash_string (msgid);
   1211 			nls_uint32 idx = hash_val % domain->hash_size;
   1212 			nls_uint32 incr =
   1213 			  1 + (hash_val % (domain->hash_size - 2));
   1214 
   1215 			for (;;)
   1216 			  {
   1217 			    if (inmem_hash_tab[idx] == 0)
   1218 			      {
   1219 				/* Hash table entry is empty.  Use it.  */
   1220 				inmem_hash_tab[idx] = 1 + domain->nstrings + i;
   1221 				break;
   1222 			      }
   1223 
   1224 			    if (idx >= domain->hash_size - incr)
   1225 			      idx -= domain->hash_size - incr;
   1226 			    else
   1227 			      idx += incr;
   1228 			  }
   1229 		      }
   1230 
   1231 		    domain->n_sysdep_strings = n_inmem_sysdep_strings;
   1232 		    domain->orig_sysdep_tab = inmem_orig_sysdep_tab;
   1233 		    domain->trans_sysdep_tab = inmem_trans_sysdep_tab;
   1234 
   1235 		    domain->hash_tab = inmem_hash_tab;
   1236 		    domain->must_swap_hash_tab = 0;
   1237 		  }
   1238 		else
   1239 		  {
   1240 		    domain->n_sysdep_strings = 0;
   1241 		    domain->orig_sysdep_tab = NULL;
   1242 		    domain->trans_sysdep_tab = NULL;
   1243 		  }
   1244 
   1245 		freea (sysdep_segment_values);
   1246 	      }
   1247 	    else
   1248 	      {
   1249 		domain->n_sysdep_strings = 0;
   1250 		domain->orig_sysdep_tab = NULL;
   1251 		domain->trans_sysdep_tab = NULL;
   1252 	      }
   1253 	  }
   1254 	  break;
   1255 	}
   1256       break;
   1257     default:
   1258       /* This is an invalid revision.  */
   1259     invalid:
   1260       /* This is an invalid .mo file.  */
   1261       if (domain->malloced)
   1262 	free (domain->malloced);
   1263 #ifdef HAVE_MMAP
   1264       if (use_mmap)
   1265 	munmap ((caddr_t) data, size);
   1266       else
   1267 #endif
   1268 	free (data);
   1269       free (domain);
   1270       domain_file->data = NULL;
   1271       goto out;
   1272     }
   1273 
   1274   /* No caches of converted translations so far.  */
   1275   domain->conversions = NULL;
   1276   domain->nconversions = 0;
   1277 
   1278   /* Get the header entry and look for a plural specification.  */
   1279 #ifdef IN_LIBGLOCALE
   1280   nullentry =
   1281     _nl_find_msg (domain_file, domainbinding, NULL, "", &nullentrylen);
   1282 #else
   1283   nullentry = _nl_find_msg (domain_file, domainbinding, "", 0, &nullentrylen);
   1284 #endif
   1285   EXTRACT_PLURAL_EXPRESSION (nullentry, &domain->plural, &domain->nplurals);
   1286 
   1287  out:
   1288   if (fd != -1)
   1289     close (fd);
   1290 
   1291   domain_file->decided = 1;
   1292 
   1293  done:
   1294   __libc_lock_unlock_recursive (lock);
   1295 }
   1296 
   1297 
   1298 #ifdef _LIBC
   1299 void
   1300 internal_function __libc_freeres_fn_section
   1301 _nl_unload_domain (struct loaded_domain *domain)
   1302 {
   1303   size_t i;
   1304 
   1305   if (domain->plural != &__gettext_germanic_plural)
   1306     __gettext_free_exp (domain->plural);
   1307 
   1308   for (i = 0; i < domain->nconversions; i++)
   1309     {
   1310       struct converted_domain *convd = &domain->conversions[i];
   1311 
   1312       free (convd->encoding);
   1313       if (convd->conv_tab != NULL && convd->conv_tab != (char **) -1)
   1314 	free (convd->conv_tab);
   1315       if (convd->conv != (__gconv_t) -1)
   1316 	__gconv_close (convd->conv);
   1317     }
   1318   if (domain->conversions != NULL)
   1319     free (domain->conversions);
   1320 
   1321   if (domain->malloced)
   1322     free (domain->malloced);
   1323 
   1324 # ifdef _POSIX_MAPPED_FILES
   1325   if (domain->use_mmap)
   1326     munmap ((caddr_t) domain->data, domain->mmap_size);
   1327   else
   1328 # endif	/* _POSIX_MAPPED_FILES */
   1329     free ((void *) domain->data);
   1330 
   1331   free (domain);
   1332 }
   1333 #endif
   1334