Main Page | Modules | Class Hierarchy | Class List | Directories | File List | Class Members | File Members | Related Pages

loadmsgcat.c

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

Generated on Tue Dec 20 10:14:20 2005 for vlc-0.8.4a by  doxygen 1.4.2