Back to index

tetex-bin  3.0
loadmsgcat.c
Go to the documentation of this file.
00001 /* Load needed message catalogs.
00002    Copyright (C) 1995-1999, 2000-2004 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 # 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 /* We need a sign, whether a new catalog was loaded, which can be associated
00495    with all translations.  This is important if the translations are
00496    cached by one of GCC's features.  */
00497 int _nl_msg_cat_cntr;
00498 
00499 
00500 /* Expand a system dependent string segment.  Return NULL if unsupported.  */
00501 static const char *
00502 get_sysdep_segment_value (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   /* Test for a glibc specific printf() format directive flag.  */
00752   if (name[0] == 'I' && name[1] == '\0')
00753     {
00754 #if defined _LIBC || __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2)
00755       /* The 'I' flag, in numeric format directives, replaces ASCII digits
00756         with the 'outdigits' defined in the LC_CTYPE locale facet.  This is
00757         used for Farsi (Persian) and maybe Arabic.  */
00758       return "I";
00759 #else
00760       return "";
00761 #endif
00762     }
00763   /* Other system dependent strings are not valid.  */
00764   return NULL;
00765 }
00766 
00767 /* Initialize the codeset dependent parts of an opened message catalog.
00768    Return the header entry.  */
00769 const char *
00770 internal_function
00771 _nl_init_domain_conv (struct loaded_l10nfile *domain_file,
00772                     struct loaded_domain *domain,
00773                     struct binding *domainbinding)
00774 {
00775   /* Find out about the character set the file is encoded with.
00776      This can be found (in textual form) in the entry "".  If this
00777      entry does not exist or if this does not contain the `charset='
00778      information, we will assume the charset matches the one the
00779      current locale and we don't have to perform any conversion.  */
00780   char *nullentry;
00781   size_t nullentrylen;
00782 
00783   /* Preinitialize fields, to avoid recursion during _nl_find_msg.  */
00784   domain->codeset_cntr =
00785     (domainbinding != NULL ? domainbinding->codeset_cntr : 0);
00786 #ifdef _LIBC
00787   domain->conv = (__gconv_t) -1;
00788 #else
00789 # if HAVE_ICONV
00790   domain->conv = (iconv_t) -1;
00791 # endif
00792 #endif
00793   domain->conv_tab = NULL;
00794 
00795   /* Get the header entry.  */
00796   nullentry = _nl_find_msg (domain_file, domainbinding, "", &nullentrylen);
00797 
00798   if (nullentry != NULL)
00799     {
00800 #if defined _LIBC || HAVE_ICONV
00801       const char *charsetstr;
00802 
00803       charsetstr = strstr (nullentry, "charset=");
00804       if (charsetstr != NULL)
00805        {
00806          size_t len;
00807          char *charset;
00808          const char *outcharset;
00809 
00810          charsetstr += strlen ("charset=");
00811          len = strcspn (charsetstr, " \t\n");
00812 
00813          charset = (char *) alloca (len + 1);
00814 # if defined _LIBC || HAVE_MEMPCPY
00815          *((char *) mempcpy (charset, charsetstr, len)) = '\0';
00816 # else
00817          memcpy (charset, charsetstr, len);
00818          charset[len] = '\0';
00819 # endif
00820 
00821          /* The output charset should normally be determined by the
00822             locale.  But sometimes the locale is not used or not correctly
00823             set up, so we provide a possibility for the user to override
00824             this.  Moreover, the value specified through
00825             bind_textdomain_codeset overrides both.  */
00826          if (domainbinding != NULL && domainbinding->codeset != NULL)
00827            outcharset = domainbinding->codeset;
00828          else
00829            {
00830              outcharset = getenv ("OUTPUT_CHARSET");
00831              if (outcharset == NULL || outcharset[0] == '\0')
00832               {
00833 # ifdef _LIBC
00834                 outcharset = _NL_CURRENT (LC_CTYPE, CODESET);
00835 # else
00836 #  if HAVE_ICONV
00837                 extern const char *locale_charset (void);
00838                 outcharset = locale_charset ();
00839 #  endif
00840 # endif
00841               }
00842            }
00843 
00844 # ifdef _LIBC
00845          /* We always want to use transliteration.  */
00846          outcharset = norm_add_slashes (outcharset, "TRANSLIT");
00847          charset = norm_add_slashes (charset, NULL);
00848          if (__gconv_open (outcharset, charset, &domain->conv,
00849                          GCONV_AVOID_NOCONV)
00850              != __GCONV_OK)
00851            domain->conv = (__gconv_t) -1;
00852 # else
00853 #  if HAVE_ICONV
00854          /* When using GNU libc >= 2.2 or GNU libiconv >= 1.5,
00855             we want to use transliteration.  */
00856 #   if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2) || __GLIBC__ > 2 \
00857        || _LIBICONV_VERSION >= 0x0105
00858          if (strchr (outcharset, '/') == NULL)
00859            {
00860              char *tmp;
00861 
00862              len = strlen (outcharset);
00863              tmp = (char *) alloca (len + 10 + 1);
00864              memcpy (tmp, outcharset, len);
00865              memcpy (tmp + len, "//TRANSLIT", 10 + 1);
00866              outcharset = tmp;
00867 
00868              domain->conv = iconv_open (outcharset, charset);
00869 
00870              freea (outcharset);
00871            }
00872          else
00873 #   endif
00874            domain->conv = iconv_open (outcharset, charset);
00875 #  endif
00876 # endif
00877 
00878          freea (charset);
00879        }
00880 #endif /* _LIBC || HAVE_ICONV */
00881     }
00882 
00883   return nullentry;
00884 }
00885 
00886 /* Frees the codeset dependent parts of an opened message catalog.  */
00887 void
00888 internal_function
00889 _nl_free_domain_conv (struct loaded_domain *domain)
00890 {
00891   if (domain->conv_tab != NULL && domain->conv_tab != (char **) -1)
00892     free (domain->conv_tab);
00893 
00894 #ifdef _LIBC
00895   if (domain->conv != (__gconv_t) -1)
00896     __gconv_close (domain->conv);
00897 #else
00898 # if HAVE_ICONV
00899   if (domain->conv != (iconv_t) -1)
00900     iconv_close (domain->conv);
00901 # endif
00902 #endif
00903 }
00904 
00905 /* Load the message catalogs specified by FILENAME.  If it is no valid
00906    message catalog do nothing.  */
00907 void
00908 internal_function
00909 _nl_load_domain (struct loaded_l10nfile *domain_file,
00910                struct binding *domainbinding)
00911 {
00912   int fd;
00913   size_t size;
00914 #ifdef _LIBC
00915   struct stat64 st;
00916 #else
00917   struct stat st;
00918 #endif
00919   struct mo_file_header *data = (struct mo_file_header *) -1;
00920   int use_mmap = 0;
00921   struct loaded_domain *domain;
00922   int revision;
00923   const char *nullentry;
00924 
00925   domain_file->decided = 1;
00926   domain_file->data = NULL;
00927 
00928   /* Note that it would be useless to store domainbinding in domain_file
00929      because domainbinding might be == NULL now but != NULL later (after
00930      a call to bind_textdomain_codeset).  */
00931 
00932   /* If the record does not represent a valid locale the FILENAME
00933      might be NULL.  This can happen when according to the given
00934      specification the locale file name is different for XPG and CEN
00935      syntax.  */
00936   if (domain_file->filename == NULL)
00937     return;
00938 
00939   /* Try to open the addressed file.  */
00940   fd = open (domain_file->filename, O_RDONLY | O_BINARY);
00941   if (fd == -1)
00942     return;
00943 
00944   /* We must know about the size of the file.  */
00945   if (
00946 #ifdef _LIBC
00947       __builtin_expect (fstat64 (fd, &st) != 0, 0)
00948 #else
00949       __builtin_expect (fstat (fd, &st) != 0, 0)
00950 #endif
00951       || __builtin_expect ((size = (size_t) st.st_size) != st.st_size, 0)
00952       || __builtin_expect (size < sizeof (struct mo_file_header), 0))
00953     {
00954       /* Something went wrong.  */
00955       close (fd);
00956       return;
00957     }
00958 
00959 #ifdef HAVE_MMAP
00960   /* Now we are ready to load the file.  If mmap() is available we try
00961      this first.  If not available or it failed we try to load it.  */
00962   data = (struct mo_file_header *) mmap (NULL, size, PROT_READ,
00963                                     MAP_PRIVATE, fd, 0);
00964 
00965   if (__builtin_expect (data != (struct mo_file_header *) -1, 1))
00966     {
00967       /* mmap() call was successful.  */
00968       close (fd);
00969       use_mmap = 1;
00970     }
00971 #endif
00972 
00973   /* If the data is not yet available (i.e. mmap'ed) we try to load
00974      it manually.  */
00975   if (data == (struct mo_file_header *) -1)
00976     {
00977       size_t to_read;
00978       char *read_ptr;
00979 
00980       data = (struct mo_file_header *) malloc (size);
00981       if (data == NULL)
00982        return;
00983 
00984       to_read = size;
00985       read_ptr = (char *) data;
00986       do
00987        {
00988          long int nb = (long int) read (fd, read_ptr, to_read);
00989          if (nb <= 0)
00990            {
00991 #ifdef EINTR
00992              if (nb == -1 && errno == EINTR)
00993               continue;
00994 #endif
00995              close (fd);
00996              return;
00997            }
00998          read_ptr += nb;
00999          to_read -= nb;
01000        }
01001       while (to_read > 0);
01002 
01003       close (fd);
01004     }
01005 
01006   /* Using the magic number we can test whether it really is a message
01007      catalog file.  */
01008   if (__builtin_expect (data->magic != _MAGIC && data->magic != _MAGIC_SWAPPED,
01009                      0))
01010     {
01011       /* The magic number is wrong: not a message catalog file.  */
01012 #ifdef HAVE_MMAP
01013       if (use_mmap)
01014        munmap ((caddr_t) data, size);
01015       else
01016 #endif
01017        free (data);
01018       return;
01019     }
01020 
01021   domain = (struct loaded_domain *) malloc (sizeof (struct loaded_domain));
01022   if (domain == NULL)
01023     return;
01024   domain_file->data = domain;
01025 
01026   domain->data = (char *) data;
01027   domain->use_mmap = use_mmap;
01028   domain->mmap_size = size;
01029   domain->must_swap = data->magic != _MAGIC;
01030   domain->malloced = NULL;
01031 
01032   /* Fill in the information about the available tables.  */
01033   revision = W (domain->must_swap, data->revision);
01034   /* We support only the major revisions 0 and 1.  */
01035   switch (revision >> 16)
01036     {
01037     case 0:
01038     case 1:
01039       domain->nstrings = W (domain->must_swap, data->nstrings);
01040       domain->orig_tab = (const struct string_desc *)
01041        ((char *) data + W (domain->must_swap, data->orig_tab_offset));
01042       domain->trans_tab = (const struct string_desc *)
01043        ((char *) data + W (domain->must_swap, data->trans_tab_offset));
01044       domain->hash_size = W (domain->must_swap, data->hash_tab_size);
01045       domain->hash_tab =
01046        (domain->hash_size > 2
01047         ? (const nls_uint32 *)
01048           ((char *) data + W (domain->must_swap, data->hash_tab_offset))
01049         : NULL);
01050       domain->must_swap_hash_tab = domain->must_swap;
01051 
01052       /* Now dispatch on the minor revision.  */
01053       switch (revision & 0xffff)
01054        {
01055        case 0:
01056          domain->n_sysdep_strings = 0;
01057          domain->orig_sysdep_tab = NULL;
01058          domain->trans_sysdep_tab = NULL;
01059          break;
01060        case 1:
01061        default:
01062          {
01063            nls_uint32 n_sysdep_strings;
01064 
01065            if (domain->hash_tab == NULL)
01066              /* This is invalid.  These minor revisions need a hash table.  */
01067              goto invalid;
01068 
01069            n_sysdep_strings =
01070              W (domain->must_swap, data->n_sysdep_strings);
01071            if (n_sysdep_strings > 0)
01072              {
01073               nls_uint32 n_sysdep_segments;
01074               const struct sysdep_segment *sysdep_segments;
01075               const char **sysdep_segment_values;
01076               const nls_uint32 *orig_sysdep_tab;
01077               const nls_uint32 *trans_sysdep_tab;
01078               nls_uint32 n_inmem_sysdep_strings;
01079               size_t memneed;
01080               char *mem;
01081               struct sysdep_string_desc *inmem_orig_sysdep_tab;
01082               struct sysdep_string_desc *inmem_trans_sysdep_tab;
01083               nls_uint32 *inmem_hash_tab;
01084               unsigned int i, j;
01085 
01086               /* Get the values of the system dependent segments.  */
01087               n_sysdep_segments =
01088                 W (domain->must_swap, data->n_sysdep_segments);
01089               sysdep_segments = (const struct sysdep_segment *)
01090                 ((char *) data
01091                  + W (domain->must_swap, data->sysdep_segments_offset));
01092               sysdep_segment_values =
01093                 alloca (n_sysdep_segments * sizeof (const char *));
01094               for (i = 0; i < n_sysdep_segments; i++)
01095                 {
01096                   const char *name =
01097                     (char *) data
01098                     + W (domain->must_swap, sysdep_segments[i].offset);
01099                   nls_uint32 namelen =
01100                     W (domain->must_swap, sysdep_segments[i].length);
01101 
01102                   if (!(namelen > 0 && name[namelen - 1] == '\0'))
01103                     {
01104                      freea (sysdep_segment_values);
01105                      goto invalid;
01106                     }
01107 
01108                   sysdep_segment_values[i] = get_sysdep_segment_value (name);
01109                 }
01110 
01111               orig_sysdep_tab = (const nls_uint32 *)
01112                 ((char *) data
01113                  + W (domain->must_swap, data->orig_sysdep_tab_offset));
01114               trans_sysdep_tab = (const nls_uint32 *)
01115                 ((char *) data
01116                  + W (domain->must_swap, data->trans_sysdep_tab_offset));
01117 
01118               /* Compute the amount of additional memory needed for the
01119                  system dependent strings and the augmented hash table.
01120                  At the same time, also drop string pairs which refer to
01121                  an undefined system dependent segment.  */
01122               n_inmem_sysdep_strings = 0;
01123               memneed = domain->hash_size * sizeof (nls_uint32);
01124               for (i = 0; i < n_sysdep_strings; i++)
01125                 {
01126                   int valid = 1;
01127                   size_t needs[2];
01128 
01129                   for (j = 0; j < 2; j++)
01130                     {
01131                      const struct sysdep_string *sysdep_string =
01132                        (const struct sysdep_string *)
01133                        ((char *) data
01134                         + W (domain->must_swap,
01135                             j == 0
01136                             ? orig_sysdep_tab[i]
01137                             : trans_sysdep_tab[i]));
01138                      size_t need = 0;
01139                      const struct segment_pair *p = sysdep_string->segments;
01140 
01141                      if (W (domain->must_swap, p->sysdepref) != SEGMENTS_END)
01142                        for (p = sysdep_string->segments;; p++)
01143                          {
01144                            nls_uint32 sysdepref;
01145 
01146                            need += W (domain->must_swap, p->segsize);
01147 
01148                            sysdepref = W (domain->must_swap, p->sysdepref);
01149                            if (sysdepref == SEGMENTS_END)
01150                             break;
01151 
01152                            if (sysdepref >= n_sysdep_segments)
01153                             {
01154                               /* Invalid.  */
01155                               freea (sysdep_segment_values);
01156                               goto invalid;
01157                             }
01158 
01159                            if (sysdep_segment_values[sysdepref] == NULL)
01160                             {
01161                               /* This particular string pair is invalid.  */
01162                               valid = 0;
01163                               break;
01164                             }
01165 
01166                            need += strlen (sysdep_segment_values[sysdepref]);
01167                          }
01168 
01169                      needs[j] = need;
01170                      if (!valid)
01171                        break;
01172                     }
01173 
01174                   if (valid)
01175                     {
01176                      n_inmem_sysdep_strings++;
01177                      memneed += needs[0] + needs[1];
01178                     }
01179                 }
01180               memneed += 2 * n_inmem_sysdep_strings
01181                         * sizeof (struct sysdep_string_desc);
01182 
01183               if (n_inmem_sysdep_strings > 0)
01184                 {
01185                   unsigned int k;
01186 
01187                   /* Allocate additional memory.  */
01188                   mem = (char *) malloc (memneed);
01189                   if (mem == NULL)
01190                     goto invalid;
01191 
01192                   domain->malloced = mem;
01193                   inmem_orig_sysdep_tab = (struct sysdep_string_desc *) mem;
01194                   mem += n_inmem_sysdep_strings
01195                         * sizeof (struct sysdep_string_desc);
01196                   inmem_trans_sysdep_tab = (struct sysdep_string_desc *) mem;
01197                   mem += n_inmem_sysdep_strings
01198                         * sizeof (struct sysdep_string_desc);
01199                   inmem_hash_tab = (nls_uint32 *) mem;
01200                   mem += domain->hash_size * sizeof (nls_uint32);
01201 
01202                   /* Compute the system dependent strings.  */
01203                   k = 0;
01204                   for (i = 0; i < n_sysdep_strings; i++)
01205                     {
01206                      int valid = 1;
01207 
01208                      for (j = 0; j < 2; j++)
01209                        {
01210                          const struct sysdep_string *sysdep_string =
01211                            (const struct sysdep_string *)
01212                            ((char *) data
01213                             + W (domain->must_swap,
01214                                 j == 0
01215                                 ? orig_sysdep_tab[i]
01216                                 : trans_sysdep_tab[i]));
01217                          const struct segment_pair *p =
01218                            sysdep_string->segments;
01219 
01220                          if (W (domain->must_swap, p->sysdepref)
01221                             != SEGMENTS_END)
01222                            for (p = sysdep_string->segments;; p++)
01223                             {
01224                               nls_uint32 sysdepref;
01225 
01226                               sysdepref =
01227                                 W (domain->must_swap, p->sysdepref);
01228                               if (sysdepref == SEGMENTS_END)
01229                                 break;
01230 
01231                               if (sysdep_segment_values[sysdepref] == NULL)
01232                                 {
01233                                   /* This particular string pair is
01234                                     invalid.  */
01235                                   valid = 0;
01236                                   break;
01237                                 }
01238                             }
01239 
01240                          if (!valid)
01241                            break;
01242                        }
01243 
01244                      if (valid)
01245                        {
01246                          for (j = 0; j < 2; j++)
01247                            {
01248                             const struct sysdep_string *sysdep_string =
01249                               (const struct sysdep_string *)
01250                               ((char *) data
01251                                + W (domain->must_swap,
01252                                    j == 0
01253                                    ? orig_sysdep_tab[i]
01254                                    : trans_sysdep_tab[i]));
01255                             const char *static_segments =
01256                               (char *) data
01257                               + W (domain->must_swap, sysdep_string->offset);
01258                             const struct segment_pair *p =
01259                               sysdep_string->segments;
01260 
01261                             /* Concatenate the segments, and fill
01262                                inmem_orig_sysdep_tab[k] (for j == 0) and
01263                                inmem_trans_sysdep_tab[k] (for j == 1).  */
01264 
01265                             struct sysdep_string_desc *inmem_tab_entry =
01266                               (j == 0
01267                                ? inmem_orig_sysdep_tab
01268                                : inmem_trans_sysdep_tab)
01269                               + k;
01270 
01271                             if (W (domain->must_swap, p->sysdepref)
01272                                 == SEGMENTS_END)
01273                               {
01274                                 /* Only one static segment.  */
01275                                 inmem_tab_entry->length =
01276                                   W (domain->must_swap, p->segsize);
01277                                 inmem_tab_entry->pointer = static_segments;
01278                               }
01279                             else
01280                               {
01281                                 inmem_tab_entry->pointer = mem;
01282 
01283                                 for (p = sysdep_string->segments;; p++)
01284                                   {
01285                                    nls_uint32 segsize =
01286                                      W (domain->must_swap, p->segsize);
01287                                    nls_uint32 sysdepref =
01288                                      W (domain->must_swap, p->sysdepref);
01289                                    size_t n;
01290 
01291                                    if (segsize > 0)
01292                                      {
01293                                        memcpy (mem, static_segments, segsize);
01294                                        mem += segsize;
01295                                        static_segments += segsize;
01296                                      }
01297 
01298                                    if (sysdepref == SEGMENTS_END)
01299                                      break;
01300 
01301                                    n = strlen (sysdep_segment_values[sysdepref]);
01302                                    memcpy (mem, sysdep_segment_values[sysdepref], n);
01303                                    mem += n;
01304                                   }
01305 
01306                                 inmem_tab_entry->length =
01307                                   mem - inmem_tab_entry->pointer;
01308                               }
01309                            }
01310 
01311                          k++;
01312                        }
01313                     }
01314                   if (k != n_inmem_sysdep_strings)
01315                     abort ();
01316 
01317                   /* Compute the augmented hash table.  */
01318                   for (i = 0; i < domain->hash_size; i++)
01319                     inmem_hash_tab[i] =
01320                      W (domain->must_swap_hash_tab, domain->hash_tab[i]);
01321                   for (i = 0; i < n_inmem_sysdep_strings; i++)
01322                     {
01323                      const char *msgid = inmem_orig_sysdep_tab[i].pointer;
01324                      nls_uint32 hash_val = hash_string (msgid);
01325                      nls_uint32 idx = hash_val % domain->hash_size;
01326                      nls_uint32 incr =
01327                        1 + (hash_val % (domain->hash_size - 2));
01328 
01329                      for (;;)
01330                        {
01331                          if (inmem_hash_tab[idx] == 0)
01332                            {
01333                             /* Hash table entry is empty.  Use it.  */
01334                             inmem_hash_tab[idx] = 1 + domain->nstrings + i;
01335                             break;
01336                            }
01337 
01338                          if (idx >= domain->hash_size - incr)
01339                            idx -= domain->hash_size - incr;
01340                          else
01341                            idx += incr;
01342                        }
01343                     }
01344 
01345                   domain->n_sysdep_strings = n_inmem_sysdep_strings;
01346                   domain->orig_sysdep_tab = inmem_orig_sysdep_tab;
01347                   domain->trans_sysdep_tab = inmem_trans_sysdep_tab;
01348 
01349                   domain->hash_tab = inmem_hash_tab;
01350                   domain->must_swap_hash_tab = 0;
01351                 }
01352               else
01353                 {
01354                   domain->n_sysdep_strings = 0;
01355                   domain->orig_sysdep_tab = NULL;
01356                   domain->trans_sysdep_tab = NULL;
01357                 }
01358 
01359               freea (sysdep_segment_values);
01360              }
01361            else
01362              {
01363               domain->n_sysdep_strings = 0;
01364               domain->orig_sysdep_tab = NULL;
01365               domain->trans_sysdep_tab = NULL;
01366              }
01367          }
01368          break;
01369        }
01370       break;
01371     default:
01372       /* This is an invalid revision.  */
01373     invalid:
01374       /* This is an invalid .mo file.  */
01375       if (domain->malloced)
01376        free (domain->malloced);
01377 #ifdef HAVE_MMAP
01378       if (use_mmap)
01379        munmap ((caddr_t) data, size);
01380       else
01381 #endif
01382        free (data);
01383       free (domain);
01384       domain_file->data = NULL;
01385       return;
01386     }
01387 
01388   /* Now initialize the character set converter from the character set
01389      the file is encoded with (found in the header entry) to the domain's
01390      specified character set or the locale's character set.  */
01391   nullentry = _nl_init_domain_conv (domain_file, domain, domainbinding);
01392 
01393   /* Also look for a plural specification.  */
01394   EXTRACT_PLURAL_EXPRESSION (nullentry, &domain->plural, &domain->nplurals);
01395 }
01396 
01397 
01398 #ifdef _LIBC
01399 void
01400 internal_function
01401 _nl_unload_domain (struct loaded_domain *domain)
01402 {
01403   if (domain->plural != &__gettext_germanic_plural)
01404     __gettext_free_exp (domain->plural);
01405 
01406   _nl_free_domain_conv (domain);
01407 
01408   if (domain->malloced)
01409     free (domain->malloced);
01410 
01411 # ifdef _POSIX_MAPPED_FILES
01412   if (domain->use_mmap)
01413     munmap ((caddr_t) domain->data, domain->mmap_size);
01414   else
01415 # endif       /* _POSIX_MAPPED_FILES */
01416     free ((void *) domain->data);
01417 
01418   free (domain);
01419 }
01420 #endif