1/* $NetBSD: loadmsgcat.c,v 1.1.1.1 2016/01/14 00:11:28 christos Exp $ */ 2 3/* Load needed message catalogs. 4 Copyright (C) 1995-1999, 2000-2004 Free Software Foundation, Inc. 5 6 This program is free software; you can redistribute it and/or modify it 7 under the terms of the GNU Library General Public License as published 8 by the Free Software Foundation; either version 2, or (at your option) 9 any later version. 10 11 This program is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 Library General Public License for more details. 15 16 You should have received a copy of the GNU Library General Public 17 License along with this program; if not, write to the Free Software 18 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 19 USA. */ 20 21/* Tell glibc's <string.h> to provide a prototype for mempcpy(). 22 This must come before <config.h> because <config.h> may include 23 <features.h>, and once <features.h> has been included, it's too late. */ 24#ifndef _GNU_SOURCE 25# define _GNU_SOURCE 1 26#endif 27 28#ifdef HAVE_CONFIG_H 29# include <config.h> 30#endif 31 32#include <ctype.h> 33#include <errno.h> 34#include <fcntl.h> 35#include <sys/types.h> 36#include <sys/stat.h> 37 38#ifdef __GNUC__ 39# undef alloca 40# define alloca __builtin_alloca 41# define HAVE_ALLOCA 1 42#else 43# ifdef _MSC_VER 44# include <malloc.h> 45# define alloca _alloca 46# else 47# if defined HAVE_ALLOCA_H || defined _LIBC 48# include <alloca.h> 49# else 50# ifdef _AIX 51 #pragma alloca 52# else 53# ifndef alloca 54char *alloca (); 55# endif 56# endif 57# endif 58# endif 59#endif 60 61#include <stdlib.h> 62#include <string.h> 63 64#if defined HAVE_UNISTD_H || defined _LIBC 65# include <unistd.h> 66#endif 67 68#ifdef _LIBC 69# include <langinfo.h> 70# include <locale.h> 71#endif 72 73#if (defined HAVE_MMAP && defined HAVE_MUNMAP && !defined DISALLOW_MMAP) \ 74 || (defined _LIBC && defined _POSIX_MAPPED_FILES) 75# include <sys/mman.h> 76# undef HAVE_MMAP 77# define HAVE_MMAP 1 78#else 79# undef HAVE_MMAP 80#endif 81 82#if defined HAVE_STDINT_H_WITH_UINTMAX || defined _LIBC 83# include <stdint.h> 84#endif 85#if defined HAVE_INTTYPES_H || defined _LIBC 86# include <inttypes.h> 87#endif 88 89#include "gmo.h" 90#include "gettextP.h" 91#include "hash-string.h" 92#include "plural-exp.h" 93 94#ifdef _LIBC 95# include "../locale/localeinfo.h" 96#endif 97 98/* Provide fallback values for macros that ought to be defined in <inttypes.h>. 99 Note that our fallback values need not be literal strings, because we don't 100 use them with preprocessor string concatenation. */ 101#if !defined PRId8 || PRI_MACROS_BROKEN 102# undef PRId8 103# define PRId8 "d" 104#endif 105#if !defined PRIi8 || PRI_MACROS_BROKEN 106# undef PRIi8 107# define PRIi8 "i" 108#endif 109#if !defined PRIo8 || PRI_MACROS_BROKEN 110# undef PRIo8 111# define PRIo8 "o" 112#endif 113#if !defined PRIu8 || PRI_MACROS_BROKEN 114# undef PRIu8 115# define PRIu8 "u" 116#endif 117#if !defined PRIx8 || PRI_MACROS_BROKEN 118# undef PRIx8 119# define PRIx8 "x" 120#endif 121#if !defined PRIX8 || PRI_MACROS_BROKEN 122# undef PRIX8 123# define PRIX8 "X" 124#endif 125#if !defined PRId16 || PRI_MACROS_BROKEN 126# undef PRId16 127# define PRId16 "d" 128#endif 129#if !defined PRIi16 || PRI_MACROS_BROKEN 130# undef PRIi16 131# define PRIi16 "i" 132#endif 133#if !defined PRIo16 || PRI_MACROS_BROKEN 134# undef PRIo16 135# define PRIo16 "o" 136#endif 137#if !defined PRIu16 || PRI_MACROS_BROKEN 138# undef PRIu16 139# define PRIu16 "u" 140#endif 141#if !defined PRIx16 || PRI_MACROS_BROKEN 142# undef PRIx16 143# define PRIx16 "x" 144#endif 145#if !defined PRIX16 || PRI_MACROS_BROKEN 146# undef PRIX16 147# define PRIX16 "X" 148#endif 149#if !defined PRId32 || PRI_MACROS_BROKEN 150# undef PRId32 151# define PRId32 "d" 152#endif 153#if !defined PRIi32 || PRI_MACROS_BROKEN 154# undef PRIi32 155# define PRIi32 "i" 156#endif 157#if !defined PRIo32 || PRI_MACROS_BROKEN 158# undef PRIo32 159# define PRIo32 "o" 160#endif 161#if !defined PRIu32 || PRI_MACROS_BROKEN 162# undef PRIu32 163# define PRIu32 "u" 164#endif 165#if !defined PRIx32 || PRI_MACROS_BROKEN 166# undef PRIx32 167# define PRIx32 "x" 168#endif 169#if !defined PRIX32 || PRI_MACROS_BROKEN 170# undef PRIX32 171# define PRIX32 "X" 172#endif 173#if !defined PRId64 || PRI_MACROS_BROKEN 174# undef PRId64 175# define PRId64 (sizeof (long) == 8 ? "ld" : "lld") 176#endif 177#if !defined PRIi64 || PRI_MACROS_BROKEN 178# undef PRIi64 179# define PRIi64 (sizeof (long) == 8 ? "li" : "lli") 180#endif 181#if !defined PRIo64 || PRI_MACROS_BROKEN 182# undef PRIo64 183# define PRIo64 (sizeof (long) == 8 ? "lo" : "llo") 184#endif 185#if !defined PRIu64 || PRI_MACROS_BROKEN 186# undef PRIu64 187# define PRIu64 (sizeof (long) == 8 ? "lu" : "llu") 188#endif 189#if !defined PRIx64 || PRI_MACROS_BROKEN 190# undef PRIx64 191# define PRIx64 (sizeof (long) == 8 ? "lx" : "llx") 192#endif 193#if !defined PRIX64 || PRI_MACROS_BROKEN 194# undef PRIX64 195# define PRIX64 (sizeof (long) == 8 ? "lX" : "llX") 196#endif 197#if !defined PRIdLEAST8 || PRI_MACROS_BROKEN 198# undef PRIdLEAST8 199# define PRIdLEAST8 "d" 200#endif 201#if !defined PRIiLEAST8 || PRI_MACROS_BROKEN 202# undef PRIiLEAST8 203# define PRIiLEAST8 "i" 204#endif 205#if !defined PRIoLEAST8 || PRI_MACROS_BROKEN 206# undef PRIoLEAST8 207# define PRIoLEAST8 "o" 208#endif 209#if !defined PRIuLEAST8 || PRI_MACROS_BROKEN 210# undef PRIuLEAST8 211# define PRIuLEAST8 "u" 212#endif 213#if !defined PRIxLEAST8 || PRI_MACROS_BROKEN 214# undef PRIxLEAST8 215# define PRIxLEAST8 "x" 216#endif 217#if !defined PRIXLEAST8 || PRI_MACROS_BROKEN 218# undef PRIXLEAST8 219# define PRIXLEAST8 "X" 220#endif 221#if !defined PRIdLEAST16 || PRI_MACROS_BROKEN 222# undef PRIdLEAST16 223# define PRIdLEAST16 "d" 224#endif 225#if !defined PRIiLEAST16 || PRI_MACROS_BROKEN 226# undef PRIiLEAST16 227# define PRIiLEAST16 "i" 228#endif 229#if !defined PRIoLEAST16 || PRI_MACROS_BROKEN 230# undef PRIoLEAST16 231# define PRIoLEAST16 "o" 232#endif 233#if !defined PRIuLEAST16 || PRI_MACROS_BROKEN 234# undef PRIuLEAST16 235# define PRIuLEAST16 "u" 236#endif 237#if !defined PRIxLEAST16 || PRI_MACROS_BROKEN 238# undef PRIxLEAST16 239# define PRIxLEAST16 "x" 240#endif 241#if !defined PRIXLEAST16 || PRI_MACROS_BROKEN 242# undef PRIXLEAST16 243# define PRIXLEAST16 "X" 244#endif 245#if !defined PRIdLEAST32 || PRI_MACROS_BROKEN 246# undef PRIdLEAST32 247# define PRIdLEAST32 "d" 248#endif 249#if !defined PRIiLEAST32 || PRI_MACROS_BROKEN 250# undef PRIiLEAST32 251# define PRIiLEAST32 "i" 252#endif 253#if !defined PRIoLEAST32 || PRI_MACROS_BROKEN 254# undef PRIoLEAST32 255# define PRIoLEAST32 "o" 256#endif 257#if !defined PRIuLEAST32 || PRI_MACROS_BROKEN 258# undef PRIuLEAST32 259# define PRIuLEAST32 "u" 260#endif 261#if !defined PRIxLEAST32 || PRI_MACROS_BROKEN 262# undef PRIxLEAST32 263# define PRIxLEAST32 "x" 264#endif 265#if !defined PRIXLEAST32 || PRI_MACROS_BROKEN 266# undef PRIXLEAST32 267# define PRIXLEAST32 "X" 268#endif 269#if !defined PRIdLEAST64 || PRI_MACROS_BROKEN 270# undef PRIdLEAST64 271# define PRIdLEAST64 PRId64 272#endif 273#if !defined PRIiLEAST64 || PRI_MACROS_BROKEN 274# undef PRIiLEAST64 275# define PRIiLEAST64 PRIi64 276#endif 277#if !defined PRIoLEAST64 || PRI_MACROS_BROKEN 278# undef PRIoLEAST64 279# define PRIoLEAST64 PRIo64 280#endif 281#if !defined PRIuLEAST64 || PRI_MACROS_BROKEN 282# undef PRIuLEAST64 283# define PRIuLEAST64 PRIu64 284#endif 285#if !defined PRIxLEAST64 || PRI_MACROS_BROKEN 286# undef PRIxLEAST64 287# define PRIxLEAST64 PRIx64 288#endif 289#if !defined PRIXLEAST64 || PRI_MACROS_BROKEN 290# undef PRIXLEAST64 291# define PRIXLEAST64 PRIX64 292#endif 293#if !defined PRIdFAST8 || PRI_MACROS_BROKEN 294# undef PRIdFAST8 295# define PRIdFAST8 "d" 296#endif 297#if !defined PRIiFAST8 || PRI_MACROS_BROKEN 298# undef PRIiFAST8 299# define PRIiFAST8 "i" 300#endif 301#if !defined PRIoFAST8 || PRI_MACROS_BROKEN 302# undef PRIoFAST8 303# define PRIoFAST8 "o" 304#endif 305#if !defined PRIuFAST8 || PRI_MACROS_BROKEN 306# undef PRIuFAST8 307# define PRIuFAST8 "u" 308#endif 309#if !defined PRIxFAST8 || PRI_MACROS_BROKEN 310# undef PRIxFAST8 311# define PRIxFAST8 "x" 312#endif 313#if !defined PRIXFAST8 || PRI_MACROS_BROKEN 314# undef PRIXFAST8 315# define PRIXFAST8 "X" 316#endif 317#if !defined PRIdFAST16 || PRI_MACROS_BROKEN 318# undef PRIdFAST16 319# define PRIdFAST16 "d" 320#endif 321#if !defined PRIiFAST16 || PRI_MACROS_BROKEN 322# undef PRIiFAST16 323# define PRIiFAST16 "i" 324#endif 325#if !defined PRIoFAST16 || PRI_MACROS_BROKEN 326# undef PRIoFAST16 327# define PRIoFAST16 "o" 328#endif 329#if !defined PRIuFAST16 || PRI_MACROS_BROKEN 330# undef PRIuFAST16 331# define PRIuFAST16 "u" 332#endif 333#if !defined PRIxFAST16 || PRI_MACROS_BROKEN 334# undef PRIxFAST16 335# define PRIxFAST16 "x" 336#endif 337#if !defined PRIXFAST16 || PRI_MACROS_BROKEN 338# undef PRIXFAST16 339# define PRIXFAST16 "X" 340#endif 341#if !defined PRIdFAST32 || PRI_MACROS_BROKEN 342# undef PRIdFAST32 343# define PRIdFAST32 "d" 344#endif 345#if !defined PRIiFAST32 || PRI_MACROS_BROKEN 346# undef PRIiFAST32 347# define PRIiFAST32 "i" 348#endif 349#if !defined PRIoFAST32 || PRI_MACROS_BROKEN 350# undef PRIoFAST32 351# define PRIoFAST32 "o" 352#endif 353#if !defined PRIuFAST32 || PRI_MACROS_BROKEN 354# undef PRIuFAST32 355# define PRIuFAST32 "u" 356#endif 357#if !defined PRIxFAST32 || PRI_MACROS_BROKEN 358# undef PRIxFAST32 359# define PRIxFAST32 "x" 360#endif 361#if !defined PRIXFAST32 || PRI_MACROS_BROKEN 362# undef PRIXFAST32 363# define PRIXFAST32 "X" 364#endif 365#if !defined PRIdFAST64 || PRI_MACROS_BROKEN 366# undef PRIdFAST64 367# define PRIdFAST64 PRId64 368#endif 369#if !defined PRIiFAST64 || PRI_MACROS_BROKEN 370# undef PRIiFAST64 371# define PRIiFAST64 PRIi64 372#endif 373#if !defined PRIoFAST64 || PRI_MACROS_BROKEN 374# undef PRIoFAST64 375# define PRIoFAST64 PRIo64 376#endif 377#if !defined PRIuFAST64 || PRI_MACROS_BROKEN 378# undef PRIuFAST64 379# define PRIuFAST64 PRIu64 380#endif 381#if !defined PRIxFAST64 || PRI_MACROS_BROKEN 382# undef PRIxFAST64 383# define PRIxFAST64 PRIx64 384#endif 385#if !defined PRIXFAST64 || PRI_MACROS_BROKEN 386# undef PRIXFAST64 387# define PRIXFAST64 PRIX64 388#endif 389#if !defined PRIdMAX || PRI_MACROS_BROKEN 390# undef PRIdMAX 391# define PRIdMAX (sizeof (uintmax_t) == sizeof (long) ? "ld" : "lld") 392#endif 393#if !defined PRIiMAX || PRI_MACROS_BROKEN 394# undef PRIiMAX 395# define PRIiMAX (sizeof (uintmax_t) == sizeof (long) ? "li" : "lli") 396#endif 397#if !defined PRIoMAX || PRI_MACROS_BROKEN 398# undef PRIoMAX 399# define PRIoMAX (sizeof (uintmax_t) == sizeof (long) ? "lo" : "llo") 400#endif 401#if !defined PRIuMAX || PRI_MACROS_BROKEN 402# undef PRIuMAX 403# define PRIuMAX (sizeof (uintmax_t) == sizeof (long) ? "lu" : "llu") 404#endif 405#if !defined PRIxMAX || PRI_MACROS_BROKEN 406# undef PRIxMAX 407# define PRIxMAX (sizeof (uintmax_t) == sizeof (long) ? "lx" : "llx") 408#endif 409#if !defined PRIXMAX || PRI_MACROS_BROKEN 410# undef PRIXMAX 411# define PRIXMAX (sizeof (uintmax_t) == sizeof (long) ? "lX" : "llX") 412#endif 413#if !defined PRIdPTR || PRI_MACROS_BROKEN 414# undef PRIdPTR 415# define PRIdPTR \ 416 (sizeof (void *) == sizeof (long) ? "ld" : \ 417 sizeof (void *) == sizeof (int) ? "d" : \ 418 "lld") 419#endif 420#if !defined PRIiPTR || PRI_MACROS_BROKEN 421# undef PRIiPTR 422# define PRIiPTR \ 423 (sizeof (void *) == sizeof (long) ? "li" : \ 424 sizeof (void *) == sizeof (int) ? "i" : \ 425 "lli") 426#endif 427#if !defined PRIoPTR || PRI_MACROS_BROKEN 428# undef PRIoPTR 429# define PRIoPTR \ 430 (sizeof (void *) == sizeof (long) ? "lo" : \ 431 sizeof (void *) == sizeof (int) ? "o" : \ 432 "llo") 433#endif 434#if !defined PRIuPTR || PRI_MACROS_BROKEN 435# undef PRIuPTR 436# define PRIuPTR \ 437 (sizeof (void *) == sizeof (long) ? "lu" : \ 438 sizeof (void *) == sizeof (int) ? "u" : \ 439 "llu") 440#endif 441#if !defined PRIxPTR || PRI_MACROS_BROKEN 442# undef PRIxPTR 443# define PRIxPTR \ 444 (sizeof (void *) == sizeof (long) ? "lx" : \ 445 sizeof (void *) == sizeof (int) ? "x" : \ 446 "llx") 447#endif 448#if !defined PRIXPTR || PRI_MACROS_BROKEN 449# undef PRIXPTR 450# define PRIXPTR \ 451 (sizeof (void *) == sizeof (long) ? "lX" : \ 452 sizeof (void *) == sizeof (int) ? "X" : \ 453 "llX") 454#endif 455 456/* @@ end of prolog @@ */ 457 458#ifdef _LIBC 459/* Rename the non ISO C functions. This is required by the standard 460 because some ISO C functions will require linking with this object 461 file and the name space must not be polluted. */ 462# define open __open 463# define close __close 464# define read __read 465# define mmap __mmap 466# define munmap __munmap 467#endif 468 469/* For those losing systems which don't have `alloca' we have to add 470 some additional code emulating it. */ 471#ifdef HAVE_ALLOCA 472# define freea(p) /* nothing */ 473#else 474# define alloca(n) malloc (n) 475# define freea(p) free (p) 476#endif 477 478/* For systems that distinguish between text and binary I/O. 479 O_BINARY is usually declared in <fcntl.h>. */ 480#if !defined O_BINARY && defined _O_BINARY 481 /* For MSC-compatible compilers. */ 482# define O_BINARY _O_BINARY 483# define O_TEXT _O_TEXT 484#endif 485#ifdef __BEOS__ 486 /* BeOS 5 has O_BINARY and O_TEXT, but they have no effect. */ 487# undef O_BINARY 488# undef O_TEXT 489#endif 490/* On reasonable systems, binary I/O is the default. */ 491#ifndef O_BINARY 492# define O_BINARY 0 493#endif 494 495 496/* We need a sign, whether a new catalog was loaded, which can be associated 497 with all translations. This is important if the translations are 498 cached by one of GCC's features. */ 499int _nl_msg_cat_cntr; 500 501 502/* Expand a system dependent string segment. Return NULL if unsupported. */ 503static const char * 504get_sysdep_segment_value (const char *name) 505{ 506 /* Test for an ISO C 99 section 7.8.1 format string directive. 507 Syntax: 508 P R I { d | i | o | u | x | X } 509 { { | LEAST | FAST } { 8 | 16 | 32 | 64 } | MAX | PTR } */ 510 /* We don't use a table of 14 times 6 'const char *' strings here, because 511 data relocations cost startup time. */ 512 if (name[0] == 'P' && name[1] == 'R' && name[2] == 'I') 513 { 514 if (name[3] == 'd' || name[3] == 'i' || name[3] == 'o' || name[3] == 'u' 515 || name[3] == 'x' || name[3] == 'X') 516 { 517 if (name[4] == '8' && name[5] == '\0') 518 { 519 if (name[3] == 'd') 520 return PRId8; 521 if (name[3] == 'i') 522 return PRIi8; 523 if (name[3] == 'o') 524 return PRIo8; 525 if (name[3] == 'u') 526 return PRIu8; 527 if (name[3] == 'x') 528 return PRIx8; 529 if (name[3] == 'X') 530 return PRIX8; 531 abort (); 532 } 533 if (name[4] == '1' && name[5] == '6' && name[6] == '\0') 534 { 535 if (name[3] == 'd') 536 return PRId16; 537 if (name[3] == 'i') 538 return PRIi16; 539 if (name[3] == 'o') 540 return PRIo16; 541 if (name[3] == 'u') 542 return PRIu16; 543 if (name[3] == 'x') 544 return PRIx16; 545 if (name[3] == 'X') 546 return PRIX16; 547 abort (); 548 } 549 if (name[4] == '3' && name[5] == '2' && name[6] == '\0') 550 { 551 if (name[3] == 'd') 552 return PRId32; 553 if (name[3] == 'i') 554 return PRIi32; 555 if (name[3] == 'o') 556 return PRIo32; 557 if (name[3] == 'u') 558 return PRIu32; 559 if (name[3] == 'x') 560 return PRIx32; 561 if (name[3] == 'X') 562 return PRIX32; 563 abort (); 564 } 565 if (name[4] == '6' && name[5] == '4' && name[6] == '\0') 566 { 567 if (name[3] == 'd') 568 return PRId64; 569 if (name[3] == 'i') 570 return PRIi64; 571 if (name[3] == 'o') 572 return PRIo64; 573 if (name[3] == 'u') 574 return PRIu64; 575 if (name[3] == 'x') 576 return PRIx64; 577 if (name[3] == 'X') 578 return PRIX64; 579 abort (); 580 } 581 if (name[4] == 'L' && name[5] == 'E' && name[6] == 'A' 582 && name[7] == 'S' && name[8] == 'T') 583 { 584 if (name[9] == '8' && name[10] == '\0') 585 { 586 if (name[3] == 'd') 587 return PRIdLEAST8; 588 if (name[3] == 'i') 589 return PRIiLEAST8; 590 if (name[3] == 'o') 591 return PRIoLEAST8; 592 if (name[3] == 'u') 593 return PRIuLEAST8; 594 if (name[3] == 'x') 595 return PRIxLEAST8; 596 if (name[3] == 'X') 597 return PRIXLEAST8; 598 abort (); 599 } 600 if (name[9] == '1' && name[10] == '6' && name[11] == '\0') 601 { 602 if (name[3] == 'd') 603 return PRIdLEAST16; 604 if (name[3] == 'i') 605 return PRIiLEAST16; 606 if (name[3] == 'o') 607 return PRIoLEAST16; 608 if (name[3] == 'u') 609 return PRIuLEAST16; 610 if (name[3] == 'x') 611 return PRIxLEAST16; 612 if (name[3] == 'X') 613 return PRIXLEAST16; 614 abort (); 615 } 616 if (name[9] == '3' && name[10] == '2' && name[11] == '\0') 617 { 618 if (name[3] == 'd') 619 return PRIdLEAST32; 620 if (name[3] == 'i') 621 return PRIiLEAST32; 622 if (name[3] == 'o') 623 return PRIoLEAST32; 624 if (name[3] == 'u') 625 return PRIuLEAST32; 626 if (name[3] == 'x') 627 return PRIxLEAST32; 628 if (name[3] == 'X') 629 return PRIXLEAST32; 630 abort (); 631 } 632 if (name[9] == '6' && name[10] == '4' && name[11] == '\0') 633 { 634 if (name[3] == 'd') 635 return PRIdLEAST64; 636 if (name[3] == 'i') 637 return PRIiLEAST64; 638 if (name[3] == 'o') 639 return PRIoLEAST64; 640 if (name[3] == 'u') 641 return PRIuLEAST64; 642 if (name[3] == 'x') 643 return PRIxLEAST64; 644 if (name[3] == 'X') 645 return PRIXLEAST64; 646 abort (); 647 } 648 } 649 if (name[4] == 'F' && name[5] == 'A' && name[6] == 'S' 650 && name[7] == 'T') 651 { 652 if (name[8] == '8' && name[9] == '\0') 653 { 654 if (name[3] == 'd') 655 return PRIdFAST8; 656 if (name[3] == 'i') 657 return PRIiFAST8; 658 if (name[3] == 'o') 659 return PRIoFAST8; 660 if (name[3] == 'u') 661 return PRIuFAST8; 662 if (name[3] == 'x') 663 return PRIxFAST8; 664 if (name[3] == 'X') 665 return PRIXFAST8; 666 abort (); 667 } 668 if (name[8] == '1' && name[9] == '6' && name[10] == '\0') 669 { 670 if (name[3] == 'd') 671 return PRIdFAST16; 672 if (name[3] == 'i') 673 return PRIiFAST16; 674 if (name[3] == 'o') 675 return PRIoFAST16; 676 if (name[3] == 'u') 677 return PRIuFAST16; 678 if (name[3] == 'x') 679 return PRIxFAST16; 680 if (name[3] == 'X') 681 return PRIXFAST16; 682 abort (); 683 } 684 if (name[8] == '3' && name[9] == '2' && name[10] == '\0') 685 { 686 if (name[3] == 'd') 687 return PRIdFAST32; 688 if (name[3] == 'i') 689 return PRIiFAST32; 690 if (name[3] == 'o') 691 return PRIoFAST32; 692 if (name[3] == 'u') 693 return PRIuFAST32; 694 if (name[3] == 'x') 695 return PRIxFAST32; 696 if (name[3] == 'X') 697 return PRIXFAST32; 698 abort (); 699 } 700 if (name[8] == '6' && name[9] == '4' && name[10] == '\0') 701 { 702 if (name[3] == 'd') 703 return PRIdFAST64; 704 if (name[3] == 'i') 705 return PRIiFAST64; 706 if (name[3] == 'o') 707 return PRIoFAST64; 708 if (name[3] == 'u') 709 return PRIuFAST64; 710 if (name[3] == 'x') 711 return PRIxFAST64; 712 if (name[3] == 'X') 713 return PRIXFAST64; 714 abort (); 715 } 716 } 717 if (name[4] == 'M' && name[5] == 'A' && name[6] == 'X' 718 && name[7] == '\0') 719 { 720 if (name[3] == 'd') 721 return PRIdMAX; 722 if (name[3] == 'i') 723 return PRIiMAX; 724 if (name[3] == 'o') 725 return PRIoMAX; 726 if (name[3] == 'u') 727 return PRIuMAX; 728 if (name[3] == 'x') 729 return PRIxMAX; 730 if (name[3] == 'X') 731 return PRIXMAX; 732 abort (); 733 } 734 if (name[4] == 'P' && name[5] == 'T' && name[6] == 'R' 735 && name[7] == '\0') 736 { 737 if (name[3] == 'd') 738 return PRIdPTR; 739 if (name[3] == 'i') 740 return PRIiPTR; 741 if (name[3] == 'o') 742 return PRIoPTR; 743 if (name[3] == 'u') 744 return PRIuPTR; 745 if (name[3] == 'x') 746 return PRIxPTR; 747 if (name[3] == 'X') 748 return PRIXPTR; 749 abort (); 750 } 751 } 752 } 753 /* Test for a glibc specific printf() format directive flag. */ 754 if (name[0] == 'I' && name[1] == '\0') 755 { 756#if defined _LIBC || __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2) 757 /* The 'I' flag, in numeric format directives, replaces ASCII digits 758 with the 'outdigits' defined in the LC_CTYPE locale facet. This is 759 used for Farsi (Persian) and maybe Arabic. */ 760 return "I"; 761#else 762 return ""; 763#endif 764 } 765 /* Other system dependent strings are not valid. */ 766 return NULL; 767} 768 769/* Initialize the codeset dependent parts of an opened message catalog. 770 Return the header entry. */ 771const char * 772internal_function 773_nl_init_domain_conv (struct loaded_l10nfile *domain_file, 774 struct loaded_domain *domain, 775 struct binding *domainbinding) 776{ 777 /* Find out about the character set the file is encoded with. 778 This can be found (in textual form) in the entry "". If this 779 entry does not exist or if this does not contain the `charset=' 780 information, we will assume the charset matches the one the 781 current locale and we don't have to perform any conversion. */ 782 char *nullentry; 783 size_t nullentrylen; 784 785 /* Preinitialize fields, to avoid recursion during _nl_find_msg. */ 786 domain->codeset_cntr = 787 (domainbinding != NULL ? domainbinding->codeset_cntr : 0); 788#ifdef _LIBC 789 domain->conv = (__gconv_t) -1; 790#else 791# if HAVE_ICONV 792 domain->conv = (iconv_t) -1; 793# endif 794#endif 795 domain->conv_tab = NULL; 796 797 /* Get the header entry. */ 798 nullentry = _nl_find_msg (domain_file, domainbinding, "", &nullentrylen); 799 800 if (nullentry != NULL) 801 { 802#if defined _LIBC || HAVE_ICONV 803 const char *charsetstr; 804 805 charsetstr = strstr (nullentry, "charset="); 806 if (charsetstr != NULL) 807 { 808 size_t len; 809 char *charset; 810 const char *outcharset; 811 812 charsetstr += strlen ("charset="); 813 len = strcspn (charsetstr, " \t\n"); 814 815 charset = (char *) alloca (len + 1); 816# if defined _LIBC || HAVE_MEMPCPY 817 *((char *) mempcpy (charset, charsetstr, len)) = '\0'; 818# else 819 memcpy (charset, charsetstr, len); 820 charset[len] = '\0'; 821# endif 822 823 /* The output charset should normally be determined by the 824 locale. But sometimes the locale is not used or not correctly 825 set up, so we provide a possibility for the user to override 826 this. Moreover, the value specified through 827 bind_textdomain_codeset overrides both. */ 828 if (domainbinding != NULL && domainbinding->codeset != NULL) 829 outcharset = domainbinding->codeset; 830 else 831 { 832 outcharset = getenv ("OUTPUT_CHARSET"); 833 if (outcharset == NULL || outcharset[0] == '\0') 834 { 835# ifdef _LIBC 836 outcharset = _NL_CURRENT (LC_CTYPE, CODESET); 837# else 838# if HAVE_ICONV 839 extern const char *locale_charset (void); 840 outcharset = locale_charset (); 841# endif 842# endif 843 } 844 } 845 846# ifdef _LIBC 847 /* We always want to use transliteration. */ 848 outcharset = norm_add_slashes (outcharset, "TRANSLIT"); 849 charset = norm_add_slashes (charset, NULL); 850 if (__gconv_open (outcharset, charset, &domain->conv, 851 GCONV_AVOID_NOCONV) 852 != __GCONV_OK) 853 domain->conv = (__gconv_t) -1; 854# else 855# if HAVE_ICONV 856 /* When using GNU libc >= 2.2 or GNU libiconv >= 1.5, 857 we want to use transliteration. */ 858# if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2) || __GLIBC__ > 2 \ 859 || _LIBICONV_VERSION >= 0x0105 860 if (strchr (outcharset, '/') == NULL) 861 { 862 char *tmp; 863 864 len = strlen (outcharset); 865 tmp = (char *) alloca (len + 10 + 1); 866 memcpy (tmp, outcharset, len); 867 memcpy (tmp + len, "//TRANSLIT", 10 + 1); 868 outcharset = tmp; 869 870 domain->conv = iconv_open (outcharset, charset); 871 872 freea (outcharset); 873 } 874 else 875# endif 876 domain->conv = iconv_open (outcharset, charset); 877# endif 878# endif 879 880 freea (charset); 881 } 882#endif /* _LIBC || HAVE_ICONV */ 883 } 884 885 return nullentry; 886} 887 888/* Frees the codeset dependent parts of an opened message catalog. */ 889void 890internal_function 891_nl_free_domain_conv (struct loaded_domain *domain) 892{ 893 if (domain->conv_tab != NULL && domain->conv_tab != (char **) -1) 894 free (domain->conv_tab); 895 896#ifdef _LIBC 897 if (domain->conv != (__gconv_t) -1) 898 __gconv_close (domain->conv); 899#else 900# if HAVE_ICONV 901 if (domain->conv != (iconv_t) -1) 902 iconv_close (domain->conv); 903# endif 904#endif 905} 906 907/* Load the message catalogs specified by FILENAME. If it is no valid 908 message catalog do nothing. */ 909void 910internal_function 911_nl_load_domain (struct loaded_l10nfile *domain_file, 912 struct binding *domainbinding) 913{ 914 int fd; 915 size_t size; 916#ifdef _LIBC 917 struct stat64 st; 918#else 919 struct stat st; 920#endif 921 struct mo_file_header *data = (struct mo_file_header *) -1; 922 int use_mmap = 0; 923 struct loaded_domain *domain; 924 int revision; 925 const char *nullentry; 926 927 domain_file->decided = 1; 928 domain_file->data = NULL; 929 930 /* Note that it would be useless to store domainbinding in domain_file 931 because domainbinding might be == NULL now but != NULL later (after 932 a call to bind_textdomain_codeset). */ 933 934 /* If the record does not represent a valid locale the FILENAME 935 might be NULL. This can happen when according to the given 936 specification the locale file name is different for XPG and CEN 937 syntax. */ 938 if (domain_file->filename == NULL) 939 return; 940 941 /* Try to open the addressed file. */ 942 fd = open (domain_file->filename, O_RDONLY | O_BINARY); 943 if (fd == -1) 944 return; 945 946 /* We must know about the size of the file. */ 947 if ( 948#ifdef _LIBC 949 __builtin_expect (fstat64 (fd, &st) != 0, 0) 950#else 951 __builtin_expect (fstat (fd, &st) != 0, 0) 952#endif 953 || __builtin_expect ((size = (size_t) st.st_size) != st.st_size, 0) 954 || __builtin_expect (size < sizeof (struct mo_file_header), 0)) 955 { 956 /* Something went wrong. */ 957 close (fd); 958 return; 959 } 960 961#ifdef HAVE_MMAP 962 /* Now we are ready to load the file. If mmap() is available we try 963 this first. If not available or it failed we try to load it. */ 964 data = (struct mo_file_header *) mmap (NULL, size, PROT_READ, 965 MAP_PRIVATE, fd, 0); 966 967 if (__builtin_expect (data != (struct mo_file_header *) -1, 1)) 968 { 969 /* mmap() call was successful. */ 970 close (fd); 971 use_mmap = 1; 972 } 973#endif 974 975 /* If the data is not yet available (i.e. mmap'ed) we try to load 976 it manually. */ 977 if (data == (struct mo_file_header *) -1) 978 { 979 size_t to_read; 980 char *read_ptr; 981 982 data = (struct mo_file_header *) malloc (size); 983 if (data == NULL) 984 return; 985 986 to_read = size; 987 read_ptr = (char *) data; 988 do 989 { 990 long int nb = (long int) read (fd, read_ptr, to_read); 991 if (nb <= 0) 992 { 993#ifdef EINTR 994 if (nb == -1 && errno == EINTR) 995 continue; 996#endif 997 close (fd); 998 return; 999 } 1000 read_ptr += nb; 1001 to_read -= nb; 1002 } 1003 while (to_read > 0); 1004 1005 close (fd); 1006 } 1007 1008 /* Using the magic number we can test whether it really is a message 1009 catalog file. */ 1010 if (__builtin_expect (data->magic != _MAGIC && data->magic != _MAGIC_SWAPPED, 1011 0)) 1012 { 1013 /* The magic number is wrong: not a message catalog file. */ 1014#ifdef HAVE_MMAP 1015 if (use_mmap) 1016 munmap ((caddr_t) data, size); 1017 else 1018#endif 1019 free (data); 1020 return; 1021 } 1022 1023 domain = (struct loaded_domain *) malloc (sizeof (struct loaded_domain)); 1024 if (domain == NULL) 1025 return; 1026 domain_file->data = domain; 1027 1028 domain->data = (char *) data; 1029 domain->use_mmap = use_mmap; 1030 domain->mmap_size = size; 1031 domain->must_swap = data->magic != _MAGIC; 1032 domain->malloced = NULL; 1033 1034 /* Fill in the information about the available tables. */ 1035 revision = W (domain->must_swap, data->revision); 1036 /* We support only the major revisions 0 and 1. */ 1037 switch (revision >> 16) 1038 { 1039 case 0: 1040 case 1: 1041 domain->nstrings = W (domain->must_swap, data->nstrings); 1042 domain->orig_tab = (const struct string_desc *) 1043 ((char *) data + W (domain->must_swap, data->orig_tab_offset)); 1044 domain->trans_tab = (const struct string_desc *) 1045 ((char *) data + W (domain->must_swap, data->trans_tab_offset)); 1046 domain->hash_size = W (domain->must_swap, data->hash_tab_size); 1047 domain->hash_tab = 1048 (domain->hash_size > 2 1049 ? (const nls_uint32 *) 1050 ((char *) data + W (domain->must_swap, data->hash_tab_offset)) 1051 : NULL); 1052 domain->must_swap_hash_tab = domain->must_swap; 1053 1054 /* Now dispatch on the minor revision. */ 1055 switch (revision & 0xffff) 1056 { 1057 case 0: 1058 domain->n_sysdep_strings = 0; 1059 domain->orig_sysdep_tab = NULL; 1060 domain->trans_sysdep_tab = NULL; 1061 break; 1062 case 1: 1063 default: 1064 { 1065 nls_uint32 n_sysdep_strings; 1066 1067 if (domain->hash_tab == NULL) 1068 /* This is invalid. These minor revisions need a hash table. */ 1069 goto invalid; 1070 1071 n_sysdep_strings = 1072 W (domain->must_swap, data->n_sysdep_strings); 1073 if (n_sysdep_strings > 0) 1074 { 1075 nls_uint32 n_sysdep_segments; 1076 const struct sysdep_segment *sysdep_segments; 1077 const char **sysdep_segment_values; 1078 const nls_uint32 *orig_sysdep_tab; 1079 const nls_uint32 *trans_sysdep_tab; 1080 nls_uint32 n_inmem_sysdep_strings; 1081 size_t memneed; 1082 char *mem; 1083 struct sysdep_string_desc *inmem_orig_sysdep_tab; 1084 struct sysdep_string_desc *inmem_trans_sysdep_tab; 1085 nls_uint32 *inmem_hash_tab; 1086 unsigned int i, j; 1087 1088 /* Get the values of the system dependent segments. */ 1089 n_sysdep_segments = 1090 W (domain->must_swap, data->n_sysdep_segments); 1091 sysdep_segments = (const struct sysdep_segment *) 1092 ((char *) data 1093 + W (domain->must_swap, data->sysdep_segments_offset)); 1094 sysdep_segment_values = 1095 alloca (n_sysdep_segments * sizeof (const char *)); 1096 for (i = 0; i < n_sysdep_segments; i++) 1097 { 1098 const char *name = 1099 (char *) data 1100 + W (domain->must_swap, sysdep_segments[i].offset); 1101 nls_uint32 namelen = 1102 W (domain->must_swap, sysdep_segments[i].length); 1103 1104 if (!(namelen > 0 && name[namelen - 1] == '\0')) 1105 { 1106 freea (sysdep_segment_values); 1107 goto invalid; 1108 } 1109 1110 sysdep_segment_values[i] = get_sysdep_segment_value (name); 1111 } 1112 1113 orig_sysdep_tab = (const nls_uint32 *) 1114 ((char *) data 1115 + W (domain->must_swap, data->orig_sysdep_tab_offset)); 1116 trans_sysdep_tab = (const nls_uint32 *) 1117 ((char *) data 1118 + W (domain->must_swap, data->trans_sysdep_tab_offset)); 1119 1120 /* Compute the amount of additional memory needed for the 1121 system dependent strings and the augmented hash table. 1122 At the same time, also drop string pairs which refer to 1123 an undefined system dependent segment. */ 1124 n_inmem_sysdep_strings = 0; 1125 memneed = domain->hash_size * sizeof (nls_uint32); 1126 for (i = 0; i < n_sysdep_strings; i++) 1127 { 1128 int valid = 1; 1129 size_t needs[2]; 1130 1131 for (j = 0; j < 2; j++) 1132 { 1133 const struct sysdep_string *sysdep_string = 1134 (const struct sysdep_string *) 1135 ((char *) data 1136 + W (domain->must_swap, 1137 j == 0 1138 ? orig_sysdep_tab[i] 1139 : trans_sysdep_tab[i])); 1140 size_t need = 0; 1141 const struct segment_pair *p = sysdep_string->segments; 1142 1143 if (W (domain->must_swap, p->sysdepref) != SEGMENTS_END) 1144 for (p = sysdep_string->segments;; p++) 1145 { 1146 nls_uint32 sysdepref; 1147 1148 need += W (domain->must_swap, p->segsize); 1149 1150 sysdepref = W (domain->must_swap, p->sysdepref); 1151 if (sysdepref == SEGMENTS_END) 1152 break; 1153 1154 if (sysdepref >= n_sysdep_segments) 1155 { 1156 /* Invalid. */ 1157 freea (sysdep_segment_values); 1158 goto invalid; 1159 } 1160 1161 if (sysdep_segment_values[sysdepref] == NULL) 1162 { 1163 /* This particular string pair is invalid. */ 1164 valid = 0; 1165 break; 1166 } 1167 1168 need += strlen (sysdep_segment_values[sysdepref]); 1169 } 1170 1171 needs[j] = need; 1172 if (!valid) 1173 break; 1174 } 1175 1176 if (valid) 1177 { 1178 n_inmem_sysdep_strings++; 1179 memneed += needs[0] + needs[1]; 1180 } 1181 } 1182 memneed += 2 * n_inmem_sysdep_strings 1183 * sizeof (struct sysdep_string_desc); 1184 1185 if (n_inmem_sysdep_strings > 0) 1186 { 1187 unsigned int k; 1188 1189 /* Allocate additional memory. */ 1190 mem = (char *) malloc (memneed); 1191 if (mem == NULL) 1192 goto invalid; 1193 1194 domain->malloced = mem; 1195 inmem_orig_sysdep_tab = (struct sysdep_string_desc *) mem; 1196 mem += n_inmem_sysdep_strings 1197 * sizeof (struct sysdep_string_desc); 1198 inmem_trans_sysdep_tab = (struct sysdep_string_desc *) mem; 1199 mem += n_inmem_sysdep_strings 1200 * sizeof (struct sysdep_string_desc); 1201 inmem_hash_tab = (nls_uint32 *) mem; 1202 mem += domain->hash_size * sizeof (nls_uint32); 1203 1204 /* Compute the system dependent strings. */ 1205 k = 0; 1206 for (i = 0; i < n_sysdep_strings; i++) 1207 { 1208 int valid = 1; 1209 1210 for (j = 0; j < 2; j++) 1211 { 1212 const struct sysdep_string *sysdep_string = 1213 (const struct sysdep_string *) 1214 ((char *) data 1215 + W (domain->must_swap, 1216 j == 0 1217 ? orig_sysdep_tab[i] 1218 : trans_sysdep_tab[i])); 1219 const struct segment_pair *p = 1220 sysdep_string->segments; 1221 1222 if (W (domain->must_swap, p->sysdepref) 1223 != SEGMENTS_END) 1224 for (p = sysdep_string->segments;; p++) 1225 { 1226 nls_uint32 sysdepref; 1227 1228 sysdepref = 1229 W (domain->must_swap, p->sysdepref); 1230 if (sysdepref == SEGMENTS_END) 1231 break; 1232 1233 if (sysdep_segment_values[sysdepref] == NULL) 1234 { 1235 /* This particular string pair is 1236 invalid. */ 1237 valid = 0; 1238 break; 1239 } 1240 } 1241 1242 if (!valid) 1243 break; 1244 } 1245 1246 if (valid) 1247 { 1248 for (j = 0; j < 2; j++) 1249 { 1250 const struct sysdep_string *sysdep_string = 1251 (const struct sysdep_string *) 1252 ((char *) data 1253 + W (domain->must_swap, 1254 j == 0 1255 ? orig_sysdep_tab[i] 1256 : trans_sysdep_tab[i])); 1257 const char *static_segments = 1258 (char *) data 1259 + W (domain->must_swap, sysdep_string->offset); 1260 const struct segment_pair *p = 1261 sysdep_string->segments; 1262 1263 /* Concatenate the segments, and fill 1264 inmem_orig_sysdep_tab[k] (for j == 0) and 1265 inmem_trans_sysdep_tab[k] (for j == 1). */ 1266 1267 struct sysdep_string_desc *inmem_tab_entry = 1268 (j == 0 1269 ? inmem_orig_sysdep_tab 1270 : inmem_trans_sysdep_tab) 1271 + k; 1272 1273 if (W (domain->must_swap, p->sysdepref) 1274 == SEGMENTS_END) 1275 { 1276 /* Only one static segment. */ 1277 inmem_tab_entry->length = 1278 W (domain->must_swap, p->segsize); 1279 inmem_tab_entry->pointer = static_segments; 1280 } 1281 else 1282 { 1283 inmem_tab_entry->pointer = mem; 1284 1285 for (p = sysdep_string->segments;; p++) 1286 { 1287 nls_uint32 segsize = 1288 W (domain->must_swap, p->segsize); 1289 nls_uint32 sysdepref = 1290 W (domain->must_swap, p->sysdepref); 1291 size_t n; 1292 1293 if (segsize > 0) 1294 { 1295 memcpy (mem, static_segments, segsize); 1296 mem += segsize; 1297 static_segments += segsize; 1298 } 1299 1300 if (sysdepref == SEGMENTS_END) 1301 break; 1302 1303 n = strlen (sysdep_segment_values[sysdepref]); 1304 memcpy (mem, sysdep_segment_values[sysdepref], n); 1305 mem += n; 1306 } 1307 1308 inmem_tab_entry->length = 1309 mem - inmem_tab_entry->pointer; 1310 } 1311 } 1312 1313 k++; 1314 } 1315 } 1316 if (k != n_inmem_sysdep_strings) 1317 abort (); 1318 1319 /* Compute the augmented hash table. */ 1320 for (i = 0; i < domain->hash_size; i++) 1321 inmem_hash_tab[i] = 1322 W (domain->must_swap_hash_tab, domain->hash_tab[i]); 1323 for (i = 0; i < n_inmem_sysdep_strings; i++) 1324 { 1325 const char *msgid = inmem_orig_sysdep_tab[i].pointer; 1326 nls_uint32 hash_val = hash_string (msgid); 1327 nls_uint32 idx = hash_val % domain->hash_size; 1328 nls_uint32 incr = 1329 1 + (hash_val % (domain->hash_size - 2)); 1330 1331 for (;;) 1332 { 1333 if (inmem_hash_tab[idx] == 0) 1334 { 1335 /* Hash table entry is empty. Use it. */ 1336 inmem_hash_tab[idx] = 1 + domain->nstrings + i; 1337 break; 1338 } 1339 1340 if (idx >= domain->hash_size - incr) 1341 idx -= domain->hash_size - incr; 1342 else 1343 idx += incr; 1344 } 1345 } 1346 1347 domain->n_sysdep_strings = n_inmem_sysdep_strings; 1348 domain->orig_sysdep_tab = inmem_orig_sysdep_tab; 1349 domain->trans_sysdep_tab = inmem_trans_sysdep_tab; 1350 1351 domain->hash_tab = inmem_hash_tab; 1352 domain->must_swap_hash_tab = 0; 1353 } 1354 else 1355 { 1356 domain->n_sysdep_strings = 0; 1357 domain->orig_sysdep_tab = NULL; 1358 domain->trans_sysdep_tab = NULL; 1359 } 1360 1361 freea (sysdep_segment_values); 1362 } 1363 else 1364 { 1365 domain->n_sysdep_strings = 0; 1366 domain->orig_sysdep_tab = NULL; 1367 domain->trans_sysdep_tab = NULL; 1368 } 1369 } 1370 break; 1371 } 1372 break; 1373 default: 1374 /* This is an invalid revision. */ 1375 invalid: 1376 /* This is an invalid .mo file. */ 1377 if (domain->malloced) 1378 free (domain->malloced); 1379#ifdef HAVE_MMAP 1380 if (use_mmap) 1381 munmap ((caddr_t) data, size); 1382 else 1383#endif 1384 free (data); 1385 free (domain); 1386 domain_file->data = NULL; 1387 return; 1388 } 1389 1390 /* Now initialize the character set converter from the character set 1391 the file is encoded with (found in the header entry) to the domain's 1392 specified character set or the locale's character set. */ 1393 nullentry = _nl_init_domain_conv (domain_file, domain, domainbinding); 1394 1395 /* Also look for a plural specification. */ 1396 EXTRACT_PLURAL_EXPRESSION (nullentry, &domain->plural, &domain->nplurals); 1397} 1398 1399 1400#ifdef _LIBC 1401void 1402internal_function 1403_nl_unload_domain (struct loaded_domain *domain) 1404{ 1405 if (domain->plural != &__gettext_germanic_plural) 1406 __gettext_free_exp (domain->plural); 1407 1408 _nl_free_domain_conv (domain); 1409 1410 if (domain->malloced) 1411 free (domain->malloced); 1412 1413# ifdef _POSIX_MAPPED_FILES 1414 if (domain->use_mmap) 1415 munmap ((caddr_t) domain->data, domain->mmap_size); 1416 else 1417# endif /* _POSIX_MAPPED_FILES */ 1418 free ((void *) domain->data); 1419 1420 free (domain); 1421} 1422#endif 1423