Back to index

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