Back to index

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