Back to index

courier  0.68.2
loadmsgcat.c
Go to the documentation of this file.
00001 /* Load needed message catalogs.
00002    Copyright (C) 1995-1999, 2000-2008 Free Software Foundation, Inc.
00003 
00004    This program is free software; you can redistribute it and/or modify it
00005    under the terms of the GNU Library General Public License as published
00006    by the Free Software Foundation; either version 2, or (at your option)
00007    any later version.
00008 
00009    This program is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY; without even the implied warranty of
00011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012    Library General Public License for more details.
00013 
00014    You should have received a copy of the GNU Library General Public
00015    License along with this program; if not, write to the Free Software
00016    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
00017    USA.  */
00018 
00019 /* Tell glibc's <string.h> to provide a prototype for mempcpy().
00020    This must come before <config.h> because <config.h> may include
00021    <features.h>, and once <features.h> has been included, it's too late.  */
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 # undef  alloca
00038 # define alloca __builtin_alloca
00039 # define HAVE_ALLOCA 1
00040 #else
00041 # ifdef _MSC_VER
00042 #  include <malloc.h>
00043 #  define alloca _alloca
00044 # else
00045 #  if defined HAVE_ALLOCA_H || defined _LIBC
00046 #   include <alloca.h>
00047 #  else
00048 #   ifdef _AIX
00049  #pragma alloca
00050 #   else
00051 #    ifndef alloca
00052 char *alloca ();
00053 #    endif
00054 #   endif
00055 #  endif
00056 # endif
00057 #endif
00058 
00059 #include <stdlib.h>
00060 #include <string.h>
00061 
00062 #if defined HAVE_UNISTD_H || defined _LIBC
00063 # include <unistd.h>
00064 #endif
00065 
00066 #ifdef _LIBC
00067 # include <langinfo.h>
00068 # include <locale.h>
00069 #endif
00070 
00071 #if (defined HAVE_MMAP && defined HAVE_MUNMAP && !defined DISALLOW_MMAP) \
00072     || (defined _LIBC && defined _POSIX_MAPPED_FILES)
00073 # include <sys/mman.h>
00074 # undef HAVE_MMAP
00075 # define HAVE_MMAP   1
00076 #else
00077 # undef HAVE_MMAP
00078 #endif
00079 
00080 #if defined HAVE_STDINT_H_WITH_UINTMAX || defined _LIBC
00081 # include <stdint.h>
00082 #endif
00083 #if defined HAVE_INTTYPES_H || defined _LIBC
00084 # include <inttypes.h>
00085 #endif
00086 
00087 #include "gmo.h"
00088 #include "gettextP.h"
00089 #include "hash-string.h"
00090 #include "plural-exp.h"
00091 
00092 #ifdef _LIBC
00093 # include "../locale/localeinfo.h"
00094 # include <not-cancel.h>
00095 #endif
00096 
00097 /* Handle multi-threaded applications.  */
00098 #ifdef _LIBC
00099 # include <bits/libc-lock.h>
00100 #else
00101 # include "lock.h"
00102 #endif
00103 
00104 /* Provide fallback values for macros that ought to be defined in <inttypes.h>.
00105    Note that our fallback values need not be literal strings, because we don't
00106    use them with preprocessor string concatenation.  */
00107 #if !defined PRId8 || PRI_MACROS_BROKEN
00108 # undef PRId8
00109 # define PRId8 "d"
00110 #endif
00111 #if !defined PRIi8 || PRI_MACROS_BROKEN
00112 # undef PRIi8
00113 # define PRIi8 "i"
00114 #endif
00115 #if !defined PRIo8 || PRI_MACROS_BROKEN
00116 # undef PRIo8
00117 # define PRIo8 "o"
00118 #endif
00119 #if !defined PRIu8 || PRI_MACROS_BROKEN
00120 # undef PRIu8
00121 # define PRIu8 "u"
00122 #endif
00123 #if !defined PRIx8 || PRI_MACROS_BROKEN
00124 # undef PRIx8
00125 # define PRIx8 "x"
00126 #endif
00127 #if !defined PRIX8 || PRI_MACROS_BROKEN
00128 # undef PRIX8
00129 # define PRIX8 "X"
00130 #endif
00131 #if !defined PRId16 || PRI_MACROS_BROKEN
00132 # undef PRId16
00133 # define PRId16 "d"
00134 #endif
00135 #if !defined PRIi16 || PRI_MACROS_BROKEN
00136 # undef PRIi16
00137 # define PRIi16 "i"
00138 #endif
00139 #if !defined PRIo16 || PRI_MACROS_BROKEN
00140 # undef PRIo16
00141 # define PRIo16 "o"
00142 #endif
00143 #if !defined PRIu16 || PRI_MACROS_BROKEN
00144 # undef PRIu16
00145 # define PRIu16 "u"
00146 #endif
00147 #if !defined PRIx16 || PRI_MACROS_BROKEN
00148 # undef PRIx16
00149 # define PRIx16 "x"
00150 #endif
00151 #if !defined PRIX16 || PRI_MACROS_BROKEN
00152 # undef PRIX16
00153 # define PRIX16 "X"
00154 #endif
00155 #if !defined PRId32 || PRI_MACROS_BROKEN
00156 # undef PRId32
00157 # define PRId32 "d"
00158 #endif
00159 #if !defined PRIi32 || PRI_MACROS_BROKEN
00160 # undef PRIi32
00161 # define PRIi32 "i"
00162 #endif
00163 #if !defined PRIo32 || PRI_MACROS_BROKEN
00164 # undef PRIo32
00165 # define PRIo32 "o"
00166 #endif
00167 #if !defined PRIu32 || PRI_MACROS_BROKEN
00168 # undef PRIu32
00169 # define PRIu32 "u"
00170 #endif
00171 #if !defined PRIx32 || PRI_MACROS_BROKEN
00172 # undef PRIx32
00173 # define PRIx32 "x"
00174 #endif
00175 #if !defined PRIX32 || PRI_MACROS_BROKEN
00176 # undef PRIX32
00177 # define PRIX32 "X"
00178 #endif
00179 #if !defined PRId64 || PRI_MACROS_BROKEN
00180 # undef PRId64
00181 # define PRId64 (sizeof (long) == 8 ? "ld" : "lld")
00182 #endif
00183 #if !defined PRIi64 || PRI_MACROS_BROKEN
00184 # undef PRIi64
00185 # define PRIi64 (sizeof (long) == 8 ? "li" : "lli")
00186 #endif
00187 #if !defined PRIo64 || PRI_MACROS_BROKEN
00188 # undef PRIo64
00189 # define PRIo64 (sizeof (long) == 8 ? "lo" : "llo")
00190 #endif
00191 #if !defined PRIu64 || PRI_MACROS_BROKEN
00192 # undef PRIu64
00193 # define PRIu64 (sizeof (long) == 8 ? "lu" : "llu")
00194 #endif
00195 #if !defined PRIx64 || PRI_MACROS_BROKEN
00196 # undef PRIx64
00197 # define PRIx64 (sizeof (long) == 8 ? "lx" : "llx")
00198 #endif
00199 #if !defined PRIX64 || PRI_MACROS_BROKEN
00200 # undef PRIX64
00201 # define PRIX64 (sizeof (long) == 8 ? "lX" : "llX")
00202 #endif
00203 #if !defined PRIdLEAST8 || PRI_MACROS_BROKEN
00204 # undef PRIdLEAST8
00205 # define PRIdLEAST8 "d"
00206 #endif
00207 #if !defined PRIiLEAST8 || PRI_MACROS_BROKEN
00208 # undef PRIiLEAST8
00209 # define PRIiLEAST8 "i"
00210 #endif
00211 #if !defined PRIoLEAST8 || PRI_MACROS_BROKEN
00212 # undef PRIoLEAST8
00213 # define PRIoLEAST8 "o"
00214 #endif
00215 #if !defined PRIuLEAST8 || PRI_MACROS_BROKEN
00216 # undef PRIuLEAST8
00217 # define PRIuLEAST8 "u"
00218 #endif
00219 #if !defined PRIxLEAST8 || PRI_MACROS_BROKEN
00220 # undef PRIxLEAST8
00221 # define PRIxLEAST8 "x"
00222 #endif
00223 #if !defined PRIXLEAST8 || PRI_MACROS_BROKEN
00224 # undef PRIXLEAST8
00225 # define PRIXLEAST8 "X"
00226 #endif
00227 #if !defined PRIdLEAST16 || PRI_MACROS_BROKEN
00228 # undef PRIdLEAST16
00229 # define PRIdLEAST16 "d"
00230 #endif
00231 #if !defined PRIiLEAST16 || PRI_MACROS_BROKEN
00232 # undef PRIiLEAST16
00233 # define PRIiLEAST16 "i"
00234 #endif
00235 #if !defined PRIoLEAST16 || PRI_MACROS_BROKEN
00236 # undef PRIoLEAST16
00237 # define PRIoLEAST16 "o"
00238 #endif
00239 #if !defined PRIuLEAST16 || PRI_MACROS_BROKEN
00240 # undef PRIuLEAST16
00241 # define PRIuLEAST16 "u"
00242 #endif
00243 #if !defined PRIxLEAST16 || PRI_MACROS_BROKEN
00244 # undef PRIxLEAST16
00245 # define PRIxLEAST16 "x"
00246 #endif
00247 #if !defined PRIXLEAST16 || PRI_MACROS_BROKEN
00248 # undef PRIXLEAST16
00249 # define PRIXLEAST16 "X"
00250 #endif
00251 #if !defined PRIdLEAST32 || PRI_MACROS_BROKEN
00252 # undef PRIdLEAST32
00253 # define PRIdLEAST32 "d"
00254 #endif
00255 #if !defined PRIiLEAST32 || PRI_MACROS_BROKEN
00256 # undef PRIiLEAST32
00257 # define PRIiLEAST32 "i"
00258 #endif
00259 #if !defined PRIoLEAST32 || PRI_MACROS_BROKEN
00260 # undef PRIoLEAST32
00261 # define PRIoLEAST32 "o"
00262 #endif
00263 #if !defined PRIuLEAST32 || PRI_MACROS_BROKEN
00264 # undef PRIuLEAST32
00265 # define PRIuLEAST32 "u"
00266 #endif
00267 #if !defined PRIxLEAST32 || PRI_MACROS_BROKEN
00268 # undef PRIxLEAST32
00269 # define PRIxLEAST32 "x"
00270 #endif
00271 #if !defined PRIXLEAST32 || PRI_MACROS_BROKEN
00272 # undef PRIXLEAST32
00273 # define PRIXLEAST32 "X"
00274 #endif
00275 #if !defined PRIdLEAST64 || PRI_MACROS_BROKEN
00276 # undef PRIdLEAST64
00277 # define PRIdLEAST64 PRId64
00278 #endif
00279 #if !defined PRIiLEAST64 || PRI_MACROS_BROKEN
00280 # undef PRIiLEAST64
00281 # define PRIiLEAST64 PRIi64
00282 #endif
00283 #if !defined PRIoLEAST64 || PRI_MACROS_BROKEN
00284 # undef PRIoLEAST64
00285 # define PRIoLEAST64 PRIo64
00286 #endif
00287 #if !defined PRIuLEAST64 || PRI_MACROS_BROKEN
00288 # undef PRIuLEAST64
00289 # define PRIuLEAST64 PRIu64
00290 #endif
00291 #if !defined PRIxLEAST64 || PRI_MACROS_BROKEN
00292 # undef PRIxLEAST64
00293 # define PRIxLEAST64 PRIx64
00294 #endif
00295 #if !defined PRIXLEAST64 || PRI_MACROS_BROKEN
00296 # undef PRIXLEAST64
00297 # define PRIXLEAST64 PRIX64
00298 #endif
00299 #if !defined PRIdFAST8 || PRI_MACROS_BROKEN
00300 # undef PRIdFAST8
00301 # define PRIdFAST8 "d"
00302 #endif
00303 #if !defined PRIiFAST8 || PRI_MACROS_BROKEN
00304 # undef PRIiFAST8
00305 # define PRIiFAST8 "i"
00306 #endif
00307 #if !defined PRIoFAST8 || PRI_MACROS_BROKEN
00308 # undef PRIoFAST8
00309 # define PRIoFAST8 "o"
00310 #endif
00311 #if !defined PRIuFAST8 || PRI_MACROS_BROKEN
00312 # undef PRIuFAST8
00313 # define PRIuFAST8 "u"
00314 #endif
00315 #if !defined PRIxFAST8 || PRI_MACROS_BROKEN
00316 # undef PRIxFAST8
00317 # define PRIxFAST8 "x"
00318 #endif
00319 #if !defined PRIXFAST8 || PRI_MACROS_BROKEN
00320 # undef PRIXFAST8
00321 # define PRIXFAST8 "X"
00322 #endif
00323 #if !defined PRIdFAST16 || PRI_MACROS_BROKEN
00324 # undef PRIdFAST16
00325 # define PRIdFAST16 "d"
00326 #endif
00327 #if !defined PRIiFAST16 || PRI_MACROS_BROKEN
00328 # undef PRIiFAST16
00329 # define PRIiFAST16 "i"
00330 #endif
00331 #if !defined PRIoFAST16 || PRI_MACROS_BROKEN
00332 # undef PRIoFAST16
00333 # define PRIoFAST16 "o"
00334 #endif
00335 #if !defined PRIuFAST16 || PRI_MACROS_BROKEN
00336 # undef PRIuFAST16
00337 # define PRIuFAST16 "u"
00338 #endif
00339 #if !defined PRIxFAST16 || PRI_MACROS_BROKEN
00340 # undef PRIxFAST16
00341 # define PRIxFAST16 "x"
00342 #endif
00343 #if !defined PRIXFAST16 || PRI_MACROS_BROKEN
00344 # undef PRIXFAST16
00345 # define PRIXFAST16 "X"
00346 #endif
00347 #if !defined PRIdFAST32 || PRI_MACROS_BROKEN
00348 # undef PRIdFAST32
00349 # define PRIdFAST32 "d"
00350 #endif
00351 #if !defined PRIiFAST32 || PRI_MACROS_BROKEN
00352 # undef PRIiFAST32
00353 # define PRIiFAST32 "i"
00354 #endif
00355 #if !defined PRIoFAST32 || PRI_MACROS_BROKEN
00356 # undef PRIoFAST32
00357 # define PRIoFAST32 "o"
00358 #endif
00359 #if !defined PRIuFAST32 || PRI_MACROS_BROKEN
00360 # undef PRIuFAST32
00361 # define PRIuFAST32 "u"
00362 #endif
00363 #if !defined PRIxFAST32 || PRI_MACROS_BROKEN
00364 # undef PRIxFAST32
00365 # define PRIxFAST32 "x"
00366 #endif
00367 #if !defined PRIXFAST32 || PRI_MACROS_BROKEN
00368 # undef PRIXFAST32
00369 # define PRIXFAST32 "X"
00370 #endif
00371 #if !defined PRIdFAST64 || PRI_MACROS_BROKEN
00372 # undef PRIdFAST64
00373 # define PRIdFAST64 PRId64
00374 #endif
00375 #if !defined PRIiFAST64 || PRI_MACROS_BROKEN
00376 # undef PRIiFAST64
00377 # define PRIiFAST64 PRIi64
00378 #endif
00379 #if !defined PRIoFAST64 || PRI_MACROS_BROKEN
00380 # undef PRIoFAST64
00381 # define PRIoFAST64 PRIo64
00382 #endif
00383 #if !defined PRIuFAST64 || PRI_MACROS_BROKEN
00384 # undef PRIuFAST64
00385 # define PRIuFAST64 PRIu64
00386 #endif
00387 #if !defined PRIxFAST64 || PRI_MACROS_BROKEN
00388 # undef PRIxFAST64
00389 # define PRIxFAST64 PRIx64
00390 #endif
00391 #if !defined PRIXFAST64 || PRI_MACROS_BROKEN
00392 # undef PRIXFAST64
00393 # define PRIXFAST64 PRIX64
00394 #endif
00395 #if !defined PRIdMAX || PRI_MACROS_BROKEN
00396 # undef PRIdMAX
00397 # define PRIdMAX (sizeof (uintmax_t) == sizeof (long) ? "ld" : "lld")
00398 #endif
00399 #if !defined PRIiMAX || PRI_MACROS_BROKEN
00400 # undef PRIiMAX
00401 # define PRIiMAX (sizeof (uintmax_t) == sizeof (long) ? "li" : "lli")
00402 #endif
00403 #if !defined PRIoMAX || PRI_MACROS_BROKEN
00404 # undef PRIoMAX
00405 # define PRIoMAX (sizeof (uintmax_t) == sizeof (long) ? "lo" : "llo")
00406 #endif
00407 #if !defined PRIuMAX || PRI_MACROS_BROKEN
00408 # undef PRIuMAX
00409 # define PRIuMAX (sizeof (uintmax_t) == sizeof (long) ? "lu" : "llu")
00410 #endif
00411 #if !defined PRIxMAX || PRI_MACROS_BROKEN
00412 # undef PRIxMAX
00413 # define PRIxMAX (sizeof (uintmax_t) == sizeof (long) ? "lx" : "llx")
00414 #endif
00415 #if !defined PRIXMAX || PRI_MACROS_BROKEN
00416 # undef PRIXMAX
00417 # define PRIXMAX (sizeof (uintmax_t) == sizeof (long) ? "lX" : "llX")
00418 #endif
00419 #if !defined PRIdPTR || PRI_MACROS_BROKEN
00420 # undef PRIdPTR
00421 # define PRIdPTR \
00422   (sizeof (void *) == sizeof (long) ? "ld" : \
00423    sizeof (void *) == sizeof (int) ? "d" : \
00424    "lld")
00425 #endif
00426 #if !defined PRIiPTR || PRI_MACROS_BROKEN
00427 # undef PRIiPTR
00428 # define PRIiPTR \
00429   (sizeof (void *) == sizeof (long) ? "li" : \
00430    sizeof (void *) == sizeof (int) ? "i" : \
00431    "lli")
00432 #endif
00433 #if !defined PRIoPTR || PRI_MACROS_BROKEN
00434 # undef PRIoPTR
00435 # define PRIoPTR \
00436   (sizeof (void *) == sizeof (long) ? "lo" : \
00437    sizeof (void *) == sizeof (int) ? "o" : \
00438    "llo")
00439 #endif
00440 #if !defined PRIuPTR || PRI_MACROS_BROKEN
00441 # undef PRIuPTR
00442 # define PRIuPTR \
00443   (sizeof (void *) == sizeof (long) ? "lu" : \
00444    sizeof (void *) == sizeof (int) ? "u" : \
00445    "llu")
00446 #endif
00447 #if !defined PRIxPTR || PRI_MACROS_BROKEN
00448 # undef PRIxPTR
00449 # define PRIxPTR \
00450   (sizeof (void *) == sizeof (long) ? "lx" : \
00451    sizeof (void *) == sizeof (int) ? "x" : \
00452    "llx")
00453 #endif
00454 #if !defined PRIXPTR || PRI_MACROS_BROKEN
00455 # undef PRIXPTR
00456 # define PRIXPTR \
00457   (sizeof (void *) == sizeof (long) ? "lX" : \
00458    sizeof (void *) == sizeof (int) ? "X" : \
00459    "llX")
00460 #endif
00461 
00462 /* @@ end of prolog @@ */
00463 
00464 #ifdef _LIBC
00465 /* Rename the non ISO C functions.  This is required by the standard
00466    because some ISO C functions will require linking with this object
00467    file and the name space must not be polluted.  */
00468 # define open(name, flags)  open_not_cancel_2 (name, flags)
00469 # define close(fd)          close_not_cancel_no_status (fd)
00470 # define read(fd, buf, n)   read_not_cancel (fd, buf, n)
00471 # define mmap(addr, len, prot, flags, fd, offset) \
00472   __mmap (addr, len, prot, flags, fd, offset)
00473 # define munmap(addr, len)  __munmap (addr, len)
00474 #endif
00475 
00476 /* For those losing systems which don't have `alloca' we have to add
00477    some additional code emulating it.  */
00478 #ifdef HAVE_ALLOCA
00479 # define freea(p) /* nothing */
00480 #else
00481 # define alloca(n) malloc (n)
00482 # define freea(p) free (p)
00483 #endif
00484 
00485 /* For systems that distinguish between text and binary I/O.
00486    O_BINARY is usually declared in <fcntl.h>. */
00487 #if !defined O_BINARY && defined _O_BINARY
00488   /* For MSC-compatible compilers.  */
00489 # define O_BINARY _O_BINARY
00490 # define O_TEXT _O_TEXT
00491 #endif
00492 #ifdef __BEOS__
00493   /* BeOS 5 has O_BINARY and O_TEXT, but they have no effect.  */
00494 # undef O_BINARY
00495 # undef O_TEXT
00496 #endif
00497 /* On reasonable systems, binary I/O is the default.  */
00498 #ifndef O_BINARY
00499 # define O_BINARY 0
00500 #endif
00501 
00502 
00503 /* We need a sign, whether a new catalog was loaded, which can be associated
00504    with all translations.  This is important if the translations are
00505    cached by one of GCC's features.  */
00506 int _nl_msg_cat_cntr;
00507 
00508 
00509 /* Expand a system dependent string segment.  Return NULL if unsupported.  */
00510 static const char *
00511 get_sysdep_segment_value (const char *name)
00512 {
00513   /* Test for an ISO C 99 section 7.8.1 format string directive.
00514      Syntax:
00515      P R I { d | i | o | u | x | X }
00516      { { | LEAST | FAST } { 8 | 16 | 32 | 64 } | MAX | PTR }  */
00517   /* We don't use a table of 14 times 6 'const char *' strings here, because
00518      data relocations cost startup time.  */
00519   if (name[0] == 'P' && name[1] == 'R' && name[2] == 'I')
00520     {
00521       if (name[3] == 'd' || name[3] == 'i' || name[3] == 'o' || name[3] == 'u'
00522          || name[3] == 'x' || name[3] == 'X')
00523        {
00524          if (name[4] == '8' && name[5] == '\0')
00525            {
00526              if (name[3] == 'd')
00527               return PRId8;
00528              if (name[3] == 'i')
00529               return PRIi8;
00530              if (name[3] == 'o')
00531               return PRIo8;
00532              if (name[3] == 'u')
00533               return PRIu8;
00534              if (name[3] == 'x')
00535               return PRIx8;
00536              if (name[3] == 'X')
00537               return PRIX8;
00538              abort ();
00539            }
00540          if (name[4] == '1' && name[5] == '6' && name[6] == '\0')
00541            {
00542              if (name[3] == 'd')
00543               return PRId16;
00544              if (name[3] == 'i')
00545               return PRIi16;
00546              if (name[3] == 'o')
00547               return PRIo16;
00548              if (name[3] == 'u')
00549               return PRIu16;
00550              if (name[3] == 'x')
00551               return PRIx16;
00552              if (name[3] == 'X')
00553               return PRIX16;
00554              abort ();
00555            }
00556          if (name[4] == '3' && name[5] == '2' && name[6] == '\0')
00557            {
00558              if (name[3] == 'd')
00559               return PRId32;
00560              if (name[3] == 'i')
00561               return PRIi32;
00562              if (name[3] == 'o')
00563               return PRIo32;
00564              if (name[3] == 'u')
00565               return PRIu32;
00566              if (name[3] == 'x')
00567               return PRIx32;
00568              if (name[3] == 'X')
00569               return PRIX32;
00570              abort ();
00571            }
00572          if (name[4] == '6' && name[5] == '4' && name[6] == '\0')
00573            {
00574              if (name[3] == 'd')
00575               return PRId64;
00576              if (name[3] == 'i')
00577               return PRIi64;
00578              if (name[3] == 'o')
00579               return PRIo64;
00580              if (name[3] == 'u')
00581               return PRIu64;
00582              if (name[3] == 'x')
00583               return PRIx64;
00584              if (name[3] == 'X')
00585               return PRIX64;
00586              abort ();
00587            }
00588          if (name[4] == 'L' && name[5] == 'E' && name[6] == 'A'
00589              && name[7] == 'S' && name[8] == 'T')
00590            {
00591              if (name[9] == '8' && name[10] == '\0')
00592               {
00593                 if (name[3] == 'd')
00594                   return PRIdLEAST8;
00595                 if (name[3] == 'i')
00596                   return PRIiLEAST8;
00597                 if (name[3] == 'o')
00598                   return PRIoLEAST8;
00599                 if (name[3] == 'u')
00600                   return PRIuLEAST8;
00601                 if (name[3] == 'x')
00602                   return PRIxLEAST8;
00603                 if (name[3] == 'X')
00604                   return PRIXLEAST8;
00605                 abort ();
00606               }
00607              if (name[9] == '1' && name[10] == '6' && name[11] == '\0')
00608               {
00609                 if (name[3] == 'd')
00610                   return PRIdLEAST16;
00611                 if (name[3] == 'i')
00612                   return PRIiLEAST16;
00613                 if (name[3] == 'o')
00614                   return PRIoLEAST16;
00615                 if (name[3] == 'u')
00616                   return PRIuLEAST16;
00617                 if (name[3] == 'x')
00618                   return PRIxLEAST16;
00619                 if (name[3] == 'X')
00620                   return PRIXLEAST16;
00621                 abort ();
00622               }
00623              if (name[9] == '3' && name[10] == '2' && name[11] == '\0')
00624               {
00625                 if (name[3] == 'd')
00626                   return PRIdLEAST32;
00627                 if (name[3] == 'i')
00628                   return PRIiLEAST32;
00629                 if (name[3] == 'o')
00630                   return PRIoLEAST32;
00631                 if (name[3] == 'u')
00632                   return PRIuLEAST32;
00633                 if (name[3] == 'x')
00634                   return PRIxLEAST32;
00635                 if (name[3] == 'X')
00636                   return PRIXLEAST32;
00637                 abort ();
00638               }
00639              if (name[9] == '6' && name[10] == '4' && name[11] == '\0')
00640               {
00641                 if (name[3] == 'd')
00642                   return PRIdLEAST64;
00643                 if (name[3] == 'i')
00644                   return PRIiLEAST64;
00645                 if (name[3] == 'o')
00646                   return PRIoLEAST64;
00647                 if (name[3] == 'u')
00648                   return PRIuLEAST64;
00649                 if (name[3] == 'x')
00650                   return PRIxLEAST64;
00651                 if (name[3] == 'X')
00652                   return PRIXLEAST64;
00653                 abort ();
00654               }
00655            }
00656          if (name[4] == 'F' && name[5] == 'A' && name[6] == 'S'
00657              && name[7] == 'T')
00658            {
00659              if (name[8] == '8' && name[9] == '\0')
00660               {
00661                 if (name[3] == 'd')
00662                   return PRIdFAST8;
00663                 if (name[3] == 'i')
00664                   return PRIiFAST8;
00665                 if (name[3] == 'o')
00666                   return PRIoFAST8;
00667                 if (name[3] == 'u')
00668                   return PRIuFAST8;
00669                 if (name[3] == 'x')
00670                   return PRIxFAST8;
00671                 if (name[3] == 'X')
00672                   return PRIXFAST8;
00673                 abort ();
00674               }
00675              if (name[8] == '1' && name[9] == '6' && name[10] == '\0')
00676               {
00677                 if (name[3] == 'd')
00678                   return PRIdFAST16;
00679                 if (name[3] == 'i')
00680                   return PRIiFAST16;
00681                 if (name[3] == 'o')
00682                   return PRIoFAST16;
00683                 if (name[3] == 'u')
00684                   return PRIuFAST16;
00685                 if (name[3] == 'x')
00686                   return PRIxFAST16;
00687                 if (name[3] == 'X')
00688                   return PRIXFAST16;
00689                 abort ();
00690               }
00691              if (name[8] == '3' && name[9] == '2' && name[10] == '\0')
00692               {
00693                 if (name[3] == 'd')
00694                   return PRIdFAST32;
00695                 if (name[3] == 'i')
00696                   return PRIiFAST32;
00697                 if (name[3] == 'o')
00698                   return PRIoFAST32;
00699                 if (name[3] == 'u')
00700                   return PRIuFAST32;
00701                 if (name[3] == 'x')
00702                   return PRIxFAST32;
00703                 if (name[3] == 'X')
00704                   return PRIXFAST32;
00705                 abort ();
00706               }
00707              if (name[8] == '6' && name[9] == '4' && name[10] == '\0')
00708               {
00709                 if (name[3] == 'd')
00710                   return PRIdFAST64;
00711                 if (name[3] == 'i')
00712                   return PRIiFAST64;
00713                 if (name[3] == 'o')
00714                   return PRIoFAST64;
00715                 if (name[3] == 'u')
00716                   return PRIuFAST64;
00717                 if (name[3] == 'x')
00718                   return PRIxFAST64;
00719                 if (name[3] == 'X')
00720                   return PRIXFAST64;
00721                 abort ();
00722               }
00723            }
00724          if (name[4] == 'M' && name[5] == 'A' && name[6] == 'X'
00725              && name[7] == '\0')
00726            {
00727              if (name[3] == 'd')
00728               return PRIdMAX;
00729              if (name[3] == 'i')
00730               return PRIiMAX;
00731              if (name[3] == 'o')
00732               return PRIoMAX;
00733              if (name[3] == 'u')
00734               return PRIuMAX;
00735              if (name[3] == 'x')
00736               return PRIxMAX;
00737              if (name[3] == 'X')
00738               return PRIXMAX;
00739              abort ();
00740            }
00741          if (name[4] == 'P' && name[5] == 'T' && name[6] == 'R'
00742              && name[7] == '\0')
00743            {
00744              if (name[3] == 'd')
00745               return PRIdPTR;
00746              if (name[3] == 'i')
00747               return PRIiPTR;
00748              if (name[3] == 'o')
00749               return PRIoPTR;
00750              if (name[3] == 'u')
00751               return PRIuPTR;
00752              if (name[3] == 'x')
00753               return PRIxPTR;
00754              if (name[3] == 'X')
00755               return PRIXPTR;
00756              abort ();
00757            }
00758        }
00759     }
00760   /* Test for a glibc specific printf() format directive flag.  */
00761   if (name[0] == 'I' && name[1] == '\0')
00762     {
00763 #if defined _LIBC || __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2)
00764       /* The 'I' flag, in numeric format directives, replaces ASCII digits
00765         with the 'outdigits' defined in the LC_CTYPE locale facet.  This is
00766         used for Farsi (Persian) and maybe Arabic.  */
00767       return "I";
00768 #else
00769       return "";
00770 #endif
00771     }
00772   /* Other system dependent strings are not valid.  */
00773   return NULL;
00774 }
00775 
00776 /* Load the message catalogs specified by FILENAME.  If it is no valid
00777    message catalog do nothing.  */
00778 void
00779 internal_function
00780 _nl_load_domain (struct loaded_l10nfile *domain_file,
00781                struct binding *domainbinding)
00782 {
00783   __libc_lock_define_initialized_recursive (static, lock)
00784   int fd = -1;
00785   size_t size;
00786 #ifdef _LIBC
00787   struct stat64 st;
00788 #else
00789   struct stat st;
00790 #endif
00791   struct mo_file_header *data = (struct mo_file_header *) -1;
00792   int use_mmap = 0;
00793   struct loaded_domain *domain;
00794   int revision;
00795   const char *nullentry;
00796   size_t nullentrylen;
00797 
00798   __libc_lock_lock_recursive (lock);
00799   if (domain_file->decided != 0)
00800     {
00801       /* There are two possibilities:
00802 
00803         + this is the same thread calling again during this initialization
00804           via _nl_find_msg.  We have initialized everything this call needs.
00805 
00806         + this is another thread which tried to initialize this object.
00807           Not necessary anymore since if the lock is available this
00808           is finished.
00809       */
00810       goto done;
00811     }
00812 
00813   domain_file->decided = -1;
00814   domain_file->data = NULL;
00815 
00816   /* Note that it would be useless to store domainbinding in domain_file
00817      because domainbinding might be == NULL now but != NULL later (after
00818      a call to bind_textdomain_codeset).  */
00819 
00820   /* If the record does not represent a valid locale the FILENAME
00821      might be NULL.  This can happen when according to the given
00822      specification the locale file name is different for XPG and CEN
00823      syntax.  */
00824   if (domain_file->filename == NULL)
00825     goto out;
00826 
00827   /* Try to open the addressed file.  */
00828   fd = open (domain_file->filename, O_RDONLY | O_BINARY);
00829   if (fd == -1)
00830     goto out;
00831 
00832   /* We must know about the size of the file.  */
00833   if (
00834 #ifdef _LIBC
00835       __builtin_expect (fstat64 (fd, &st) != 0, 0)
00836 #else
00837       __builtin_expect (fstat (fd, &st) != 0, 0)
00838 #endif
00839       || __builtin_expect ((size = (size_t) st.st_size) != st.st_size, 0)
00840       || __builtin_expect (size < sizeof (struct mo_file_header), 0))
00841     /* Something went wrong.  */
00842     goto out;
00843 
00844 #ifdef HAVE_MMAP
00845   /* Now we are ready to load the file.  If mmap() is available we try
00846      this first.  If not available or it failed we try to load it.  */
00847   data = (struct mo_file_header *) mmap (NULL, size, PROT_READ,
00848                                     MAP_PRIVATE, fd, 0);
00849 
00850   if (__builtin_expect (data != (struct mo_file_header *) -1, 1))
00851     {
00852       /* mmap() call was successful.  */
00853       close (fd);
00854       fd = -1;
00855       use_mmap = 1;
00856     }
00857 #endif
00858 
00859   /* If the data is not yet available (i.e. mmap'ed) we try to load
00860      it manually.  */
00861   if (data == (struct mo_file_header *) -1)
00862     {
00863       size_t to_read;
00864       char *read_ptr;
00865 
00866       data = (struct mo_file_header *) malloc (size);
00867       if (data == NULL)
00868        goto out;
00869 
00870       to_read = size;
00871       read_ptr = (char *) data;
00872       do
00873        {
00874          long int nb = (long int) read (fd, read_ptr, to_read);
00875          if (nb <= 0)
00876            {
00877 #ifdef EINTR
00878              if (nb == -1 && errno == EINTR)
00879               continue;
00880 #endif
00881              goto out;
00882            }
00883          read_ptr += nb;
00884          to_read -= nb;
00885        }
00886       while (to_read > 0);
00887 
00888       close (fd);
00889       fd = -1;
00890     }
00891 
00892   /* Using the magic number we can test whether it really is a message
00893      catalog file.  */
00894   if (__builtin_expect (data->magic != _MAGIC && data->magic != _MAGIC_SWAPPED,
00895                      0))
00896     {
00897       /* The magic number is wrong: not a message catalog file.  */
00898 #ifdef HAVE_MMAP
00899       if (use_mmap)
00900        munmap ((caddr_t) data, size);
00901       else
00902 #endif
00903        free (data);
00904       goto out;
00905     }
00906 
00907   domain = (struct loaded_domain *) malloc (sizeof (struct loaded_domain));
00908   if (domain == NULL)
00909     goto out;
00910   domain_file->data = domain;
00911 
00912   domain->data = (char *) data;
00913   domain->use_mmap = use_mmap;
00914   domain->mmap_size = size;
00915   domain->must_swap = data->magic != _MAGIC;
00916   domain->malloced = NULL;
00917 
00918   /* Fill in the information about the available tables.  */
00919   revision = W (domain->must_swap, data->revision);
00920   /* We support only the major revisions 0 and 1.  */
00921   switch (revision >> 16)
00922     {
00923     case 0:
00924     case 1:
00925       domain->nstrings = W (domain->must_swap, data->nstrings);
00926       domain->orig_tab = (const struct string_desc *)
00927        ((char *) data + W (domain->must_swap, data->orig_tab_offset));
00928       domain->trans_tab = (const struct string_desc *)
00929        ((char *) data + W (domain->must_swap, data->trans_tab_offset));
00930       domain->hash_size = W (domain->must_swap, data->hash_tab_size);
00931       domain->hash_tab =
00932        (domain->hash_size > 2
00933         ? (const nls_uint32 *)
00934           ((char *) data + W (domain->must_swap, data->hash_tab_offset))
00935         : NULL);
00936       domain->must_swap_hash_tab = domain->must_swap;
00937 
00938       /* Now dispatch on the minor revision.  */
00939       switch (revision & 0xffff)
00940        {
00941        case 0:
00942          domain->n_sysdep_strings = 0;
00943          domain->orig_sysdep_tab = NULL;
00944          domain->trans_sysdep_tab = NULL;
00945          break;
00946        case 1:
00947        default:
00948          {
00949            nls_uint32 n_sysdep_strings;
00950 
00951            if (domain->hash_tab == NULL)
00952              /* This is invalid.  These minor revisions need a hash table.  */
00953              goto invalid;
00954 
00955            n_sysdep_strings =
00956              W (domain->must_swap, data->n_sysdep_strings);
00957            if (n_sysdep_strings > 0)
00958              {
00959               nls_uint32 n_sysdep_segments;
00960               const struct sysdep_segment *sysdep_segments;
00961               const char **sysdep_segment_values;
00962               const nls_uint32 *orig_sysdep_tab;
00963               const nls_uint32 *trans_sysdep_tab;
00964               nls_uint32 n_inmem_sysdep_strings;
00965               size_t memneed;
00966               char *mem;
00967               struct sysdep_string_desc *inmem_orig_sysdep_tab;
00968               struct sysdep_string_desc *inmem_trans_sysdep_tab;
00969               nls_uint32 *inmem_hash_tab;
00970               unsigned int i, j;
00971 
00972               /* Get the values of the system dependent segments.  */
00973               n_sysdep_segments =
00974                 W (domain->must_swap, data->n_sysdep_segments);
00975               sysdep_segments = (const struct sysdep_segment *)
00976                 ((char *) data
00977                  + W (domain->must_swap, data->sysdep_segments_offset));
00978               sysdep_segment_values =
00979                 (const char **)
00980                 alloca (n_sysdep_segments * sizeof (const char *));
00981               for (i = 0; i < n_sysdep_segments; i++)
00982                 {
00983                   const char *name =
00984                     (char *) data
00985                     + W (domain->must_swap, sysdep_segments[i].offset);
00986                   nls_uint32 namelen =
00987                     W (domain->must_swap, sysdep_segments[i].length);
00988 
00989                   if (!(namelen > 0 && name[namelen - 1] == '\0'))
00990                     {
00991                      freea (sysdep_segment_values);
00992                      goto invalid;
00993                     }
00994 
00995                   sysdep_segment_values[i] = get_sysdep_segment_value (name);
00996                 }
00997 
00998               orig_sysdep_tab = (const nls_uint32 *)
00999                 ((char *) data
01000                  + W (domain->must_swap, data->orig_sysdep_tab_offset));
01001               trans_sysdep_tab = (const nls_uint32 *)
01002                 ((char *) data
01003                  + W (domain->must_swap, data->trans_sysdep_tab_offset));
01004 
01005               /* Compute the amount of additional memory needed for the
01006                  system dependent strings and the augmented hash table.
01007                  At the same time, also drop string pairs which refer to
01008                  an undefined system dependent segment.  */
01009               n_inmem_sysdep_strings = 0;
01010               memneed = domain->hash_size * sizeof (nls_uint32);
01011               for (i = 0; i < n_sysdep_strings; i++)
01012                 {
01013                   int valid = 1;
01014                   size_t needs[2];
01015 
01016                   for (j = 0; j < 2; j++)
01017                     {
01018                      const struct sysdep_string *sysdep_string =
01019                        (const struct sysdep_string *)
01020                        ((char *) data
01021                         + W (domain->must_swap,
01022                             j == 0
01023                             ? orig_sysdep_tab[i]
01024                             : trans_sysdep_tab[i]));
01025                      size_t need = 0;
01026                      const struct segment_pair *p = sysdep_string->segments;
01027 
01028                      if (W (domain->must_swap, p->sysdepref) != SEGMENTS_END)
01029                        for (p = sysdep_string->segments;; p++)
01030                          {
01031                            nls_uint32 sysdepref;
01032 
01033                            need += W (domain->must_swap, p->segsize);
01034 
01035                            sysdepref = W (domain->must_swap, p->sysdepref);
01036                            if (sysdepref == SEGMENTS_END)
01037                             break;
01038 
01039                            if (sysdepref >= n_sysdep_segments)
01040                             {
01041                               /* Invalid.  */
01042                               freea (sysdep_segment_values);
01043                               goto invalid;
01044                             }
01045 
01046                            if (sysdep_segment_values[sysdepref] == NULL)
01047                             {
01048                               /* This particular string pair is invalid.  */
01049                               valid = 0;
01050                               break;
01051                             }
01052 
01053                            need += strlen (sysdep_segment_values[sysdepref]);
01054                          }
01055 
01056                      needs[j] = need;
01057                      if (!valid)
01058                        break;
01059                     }
01060 
01061                   if (valid)
01062                     {
01063                      n_inmem_sysdep_strings++;
01064                      memneed += needs[0] + needs[1];
01065                     }
01066                 }
01067               memneed += 2 * n_inmem_sysdep_strings
01068                         * sizeof (struct sysdep_string_desc);
01069 
01070               if (n_inmem_sysdep_strings > 0)
01071                 {
01072                   unsigned int k;
01073 
01074                   /* Allocate additional memory.  */
01075                   mem = (char *) malloc (memneed);
01076                   if (mem == NULL)
01077                     goto invalid;
01078 
01079                   domain->malloced = mem;
01080                   inmem_orig_sysdep_tab = (struct sysdep_string_desc *) mem;
01081                   mem += n_inmem_sysdep_strings
01082                         * sizeof (struct sysdep_string_desc);
01083                   inmem_trans_sysdep_tab = (struct sysdep_string_desc *) mem;
01084                   mem += n_inmem_sysdep_strings
01085                         * sizeof (struct sysdep_string_desc);
01086                   inmem_hash_tab = (nls_uint32 *) mem;
01087                   mem += domain->hash_size * sizeof (nls_uint32);
01088 
01089                   /* Compute the system dependent strings.  */
01090                   k = 0;
01091                   for (i = 0; i < n_sysdep_strings; i++)
01092                     {
01093                      int valid = 1;
01094 
01095                      for (j = 0; j < 2; j++)
01096                        {
01097                          const struct sysdep_string *sysdep_string =
01098                            (const struct sysdep_string *)
01099                            ((char *) data
01100                             + W (domain->must_swap,
01101                                 j == 0
01102                                 ? orig_sysdep_tab[i]
01103                                 : trans_sysdep_tab[i]));
01104                          const struct segment_pair *p =
01105                            sysdep_string->segments;
01106 
01107                          if (W (domain->must_swap, p->sysdepref)
01108                             != SEGMENTS_END)
01109                            for (p = sysdep_string->segments;; p++)
01110                             {
01111                               nls_uint32 sysdepref;
01112 
01113                               sysdepref =
01114                                 W (domain->must_swap, p->sysdepref);
01115                               if (sysdepref == SEGMENTS_END)
01116                                 break;
01117 
01118                               if (sysdep_segment_values[sysdepref] == NULL)
01119                                 {
01120                                   /* This particular string pair is
01121                                     invalid.  */
01122                                   valid = 0;
01123                                   break;
01124                                 }
01125                             }
01126 
01127                          if (!valid)
01128                            break;
01129                        }
01130 
01131                      if (valid)
01132                        {
01133                          for (j = 0; j < 2; j++)
01134                            {
01135                             const struct sysdep_string *sysdep_string =
01136                               (const struct sysdep_string *)
01137                               ((char *) data
01138                                + W (domain->must_swap,
01139                                    j == 0
01140                                    ? orig_sysdep_tab[i]
01141                                    : trans_sysdep_tab[i]));
01142                             const char *static_segments =
01143                               (char *) data
01144                               + W (domain->must_swap, sysdep_string->offset);
01145                             const struct segment_pair *p =
01146                               sysdep_string->segments;
01147 
01148                             /* Concatenate the segments, and fill
01149                                inmem_orig_sysdep_tab[k] (for j == 0) and
01150                                inmem_trans_sysdep_tab[k] (for j == 1).  */
01151 
01152                             struct sysdep_string_desc *inmem_tab_entry =
01153                               (j == 0
01154                                ? inmem_orig_sysdep_tab
01155                                : inmem_trans_sysdep_tab)
01156                               + k;
01157 
01158                             if (W (domain->must_swap, p->sysdepref)
01159                                 == SEGMENTS_END)
01160                               {
01161                                 /* Only one static segment.  */
01162                                 inmem_tab_entry->length =
01163                                   W (domain->must_swap, p->segsize);
01164                                 inmem_tab_entry->pointer = static_segments;
01165                               }
01166                             else
01167                               {
01168                                 inmem_tab_entry->pointer = mem;
01169 
01170                                 for (p = sysdep_string->segments;; p++)
01171                                   {
01172                                    nls_uint32 segsize =
01173                                      W (domain->must_swap, p->segsize);
01174                                    nls_uint32 sysdepref =
01175                                      W (domain->must_swap, p->sysdepref);
01176                                    size_t n;
01177 
01178                                    if (segsize > 0)
01179                                      {
01180                                        memcpy (mem, static_segments, segsize);
01181                                        mem += segsize;
01182                                        static_segments += segsize;
01183                                      }
01184 
01185                                    if (sysdepref == SEGMENTS_END)
01186                                      break;
01187 
01188                                    n = strlen (sysdep_segment_values[sysdepref]);
01189                                    memcpy (mem, sysdep_segment_values[sysdepref], n);
01190                                    mem += n;
01191                                   }
01192 
01193                                 inmem_tab_entry->length =
01194                                   mem - inmem_tab_entry->pointer;
01195                               }
01196                            }
01197 
01198                          k++;
01199                        }
01200                     }
01201                   if (k != n_inmem_sysdep_strings)
01202                     abort ();
01203 
01204                   /* Compute the augmented hash table.  */
01205                   for (i = 0; i < domain->hash_size; i++)
01206                     inmem_hash_tab[i] =
01207                      W (domain->must_swap_hash_tab, domain->hash_tab[i]);
01208                   for (i = 0; i < n_inmem_sysdep_strings; i++)
01209                     {
01210                      const char *msgid = inmem_orig_sysdep_tab[i].pointer;
01211                      nls_uint32 hash_val = __hash_string (msgid);
01212                      nls_uint32 idx = hash_val % domain->hash_size;
01213                      nls_uint32 incr =
01214                        1 + (hash_val % (domain->hash_size - 2));
01215 
01216                      for (;;)
01217                        {
01218                          if (inmem_hash_tab[idx] == 0)
01219                            {
01220                             /* Hash table entry is empty.  Use it.  */
01221                             inmem_hash_tab[idx] = 1 + domain->nstrings + i;
01222                             break;
01223                            }
01224 
01225                          if (idx >= domain->hash_size - incr)
01226                            idx -= domain->hash_size - incr;
01227                          else
01228                            idx += incr;
01229                        }
01230                     }
01231 
01232                   domain->n_sysdep_strings = n_inmem_sysdep_strings;
01233                   domain->orig_sysdep_tab = inmem_orig_sysdep_tab;
01234                   domain->trans_sysdep_tab = inmem_trans_sysdep_tab;
01235 
01236                   domain->hash_tab = inmem_hash_tab;
01237                   domain->must_swap_hash_tab = 0;
01238                 }
01239               else
01240                 {
01241                   domain->n_sysdep_strings = 0;
01242                   domain->orig_sysdep_tab = NULL;
01243                   domain->trans_sysdep_tab = NULL;
01244                 }
01245 
01246               freea (sysdep_segment_values);
01247              }
01248            else
01249              {
01250               domain->n_sysdep_strings = 0;
01251               domain->orig_sysdep_tab = NULL;
01252               domain->trans_sysdep_tab = NULL;
01253              }
01254          }
01255          break;
01256        }
01257       break;
01258     default:
01259       /* This is an invalid revision.  */
01260     invalid:
01261       /* This is an invalid .mo file.  */
01262       free (domain->malloced);
01263 #ifdef HAVE_MMAP
01264       if (use_mmap)
01265        munmap ((caddr_t) data, size);
01266       else
01267 #endif
01268        free (data);
01269       free (domain);
01270       domain_file->data = NULL;
01271       goto out;
01272     }
01273 
01274   /* No caches of converted translations so far.  */
01275   domain->conversions = NULL;
01276   domain->nconversions = 0;
01277   gl_rwlock_init (domain->conversions_lock);
01278 
01279   /* Get the header entry and look for a plural specification.  */
01280 #ifdef IN_LIBGLOCALE
01281   nullentry =
01282     _nl_find_msg (domain_file, domainbinding, NULL, "", &nullentrylen);
01283 #else
01284   nullentry = _nl_find_msg (domain_file, domainbinding, "", 0, &nullentrylen);
01285 #endif
01286   EXTRACT_PLURAL_EXPRESSION (nullentry, &domain->plural, &domain->nplurals);
01287 
01288  out:
01289   if (fd != -1)
01290     close (fd);
01291 
01292   domain_file->decided = 1;
01293 
01294  done:
01295   __libc_lock_unlock_recursive (lock);
01296 }
01297 
01298 
01299 #ifdef _LIBC
01300 void
01301 internal_function __libc_freeres_fn_section
01302 _nl_unload_domain (struct loaded_domain *domain)
01303 {
01304   size_t i;
01305 
01306   if (domain->plural != &__gettext_germanic_plural)
01307     __gettext_free_exp ((struct expression *) domain->plural);
01308 
01309   for (i = 0; i < domain->nconversions; i++)
01310     {
01311       struct converted_domain *convd = &domain->conversions[i];
01312 
01313       free (convd->encoding);
01314       if (convd->conv_tab != NULL && convd->conv_tab != (char **) -1)
01315        free (convd->conv_tab);
01316       if (convd->conv != (__gconv_t) -1)
01317        __gconv_close (convd->conv);
01318     }
01319   free (domain->conversions);
01320   __libc_rwlock_fini (domain->conversions_lock);
01321 
01322   free (domain->malloced);
01323 
01324 # ifdef _POSIX_MAPPED_FILES
01325   if (domain->use_mmap)
01326     munmap ((caddr_t) domain->data, domain->mmap_size);
01327   else
01328 # endif       /* _POSIX_MAPPED_FILES */
01329     free ((void *) domain->data);
01330 
01331   free (domain);
01332 }
01333 #endif