1/* dcigettext.c - Implementation of the internal dcigettext function. */ 2 3/* Copyright (C) 1995-1999, 2000-2003, 2006-2009 Free Software Foundation, Inc. 4 5 This file is part of GNU Bash. 6 7 Bash is free software: you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation, either version 3 of the License, or 10 (at your option) any later version. 11 12 Bash is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with Bash. If not, see <http://www.gnu.org/licenses/>. 19*/ 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 <sys/types.h> 33 34#ifdef __GNUC__ 35# define alloca __builtin_alloca 36# define HAVE_ALLOCA 1 37#else 38# ifdef _MSC_VER 39# include <malloc.h> 40# define alloca _alloca 41# else 42# if defined HAVE_ALLOCA_H || defined _LIBC 43# include <alloca.h> 44# else 45# ifdef _AIX 46 #pragma alloca 47# else 48# ifndef alloca 49char *alloca (); 50# endif 51# endif 52# endif 53# endif 54#endif 55 56#include <errno.h> 57#ifndef errno 58extern int errno; 59#endif 60#ifndef __set_errno 61# define __set_errno(val) errno = (val) 62#endif 63 64#include <stddef.h> 65#include <stdlib.h> 66#include <string.h> 67 68#if defined HAVE_UNISTD_H || defined _LIBC 69# include <unistd.h> 70#endif 71 72#include <locale.h> 73 74#ifdef _LIBC 75 /* Guess whether integer division by zero raises signal SIGFPE. 76 Set to 1 only if you know for sure. In case of doubt, set to 0. */ 77# if defined __alpha__ || defined __arm__ || defined __i386__ \ 78 || defined __m68k__ || defined __s390__ 79# define INTDIV0_RAISES_SIGFPE 1 80# else 81# define INTDIV0_RAISES_SIGFPE 0 82# endif 83#endif 84#if !INTDIV0_RAISES_SIGFPE 85# include <signal.h> 86#endif 87 88#if defined HAVE_SYS_PARAM_H || defined _LIBC 89# include <sys/param.h> 90#endif 91 92#include "gettextP.h" 93#include "plural-exp.h" 94#ifdef _LIBC 95# include <libintl.h> 96#else 97# include "libgnuintl.h" 98#endif 99#include "hash-string.h" 100 101/* Thread safetyness. */ 102#ifdef _LIBC 103# include <bits/libc-lock.h> 104#else 105/* Provide dummy implementation if this is outside glibc. */ 106# define __libc_lock_define_initialized(CLASS, NAME) 107# define __libc_lock_lock(NAME) 108# define __libc_lock_unlock(NAME) 109# define __libc_rwlock_define_initialized(CLASS, NAME) 110# define __libc_rwlock_rdlock(NAME) 111# define __libc_rwlock_unlock(NAME) 112#endif 113 114/* Alignment of types. */ 115#if defined __GNUC__ && __GNUC__ >= 2 116# define alignof(TYPE) __alignof__ (TYPE) 117#else 118# define alignof(TYPE) \ 119 ((int) &((struct { char dummy1; TYPE dummy2; } *) 0)->dummy2) 120#endif 121 122/* The internal variables in the standalone libintl.a must have different 123 names than the internal variables in GNU libc, otherwise programs 124 using libintl.a cannot be linked statically. */ 125#if !defined _LIBC 126# define _nl_default_default_domain libintl_nl_default_default_domain 127# define _nl_current_default_domain libintl_nl_current_default_domain 128# define _nl_default_dirname libintl_nl_default_dirname 129# define _nl_domain_bindings libintl_nl_domain_bindings 130#endif 131 132/* Some compilers, like SunOS4 cc, don't have offsetof in <stddef.h>. */ 133#ifndef offsetof 134# define offsetof(type,ident) ((size_t)&(((type*)0)->ident)) 135#endif 136 137/* @@ end of prolog @@ */ 138 139#if defined (SHELL) && !defined (HAVE_GETCWD) 140# define HAVE_GETCWD 141#endif 142 143#ifdef _LIBC 144/* Rename the non ANSI C functions. This is required by the standard 145 because some ANSI C functions will require linking with this object 146 file and the name space must not be polluted. */ 147# define getcwd __getcwd 148# ifndef stpcpy 149# define stpcpy __stpcpy 150# endif 151# define tfind __tfind 152#else 153# if !defined HAVE_GETCWD 154char *getwd (); 155# define getcwd(buf, max) getwd (buf) 156# else 157char *getcwd (); 158# endif 159# ifndef HAVE_STPCPY 160static char *stpcpy PARAMS ((char *dest, const char *src)); 161# endif 162# ifndef HAVE_MEMPCPY 163static void *mempcpy PARAMS ((void *dest, const void *src, size_t n)); 164# endif 165#endif 166 167/* Amount to increase buffer size by in each try. */ 168#define PATH_INCR 32 169 170/* The following is from pathmax.h. */ 171/* Non-POSIX BSD systems might have gcc's limits.h, which doesn't define 172 PATH_MAX but might cause redefinition warnings when sys/param.h is 173 later included (as on MORE/BSD 4.3). */ 174#if defined _POSIX_VERSION || (defined HAVE_LIMITS_H && !defined __GNUC__) 175# include <limits.h> 176#endif 177 178#ifndef _POSIX_PATH_MAX 179# define _POSIX_PATH_MAX 255 180#endif 181 182#if !defined PATH_MAX && defined _PC_PATH_MAX 183# define PATH_MAX (pathconf ("/", _PC_PATH_MAX) < 1 ? 1024 : pathconf ("/", _PC_PATH_MAX)) 184#endif 185 186/* Don't include sys/param.h if it already has been. */ 187#if defined HAVE_SYS_PARAM_H && !defined PATH_MAX && !defined MAXPATHLEN 188# include <sys/param.h> 189#endif 190 191#if !defined PATH_MAX && defined MAXPATHLEN 192# define PATH_MAX MAXPATHLEN 193#endif 194 195#ifndef PATH_MAX 196# define PATH_MAX _POSIX_PATH_MAX 197#endif 198 199/* Pathname support. 200 ISSLASH(C) tests whether C is a directory separator character. 201 IS_ABSOLUTE_PATH(P) tests whether P is an absolute path. If it is not, 202 it may be concatenated to a directory pathname. 203 IS_PATH_WITH_DIR(P) tests whether P contains a directory specification. 204 */ 205#if defined _WIN32 || defined __WIN32__ || defined __EMX__ || defined __DJGPP__ 206 /* Win32, OS/2, DOS */ 207# define ISSLASH(C) ((C) == '/' || (C) == '\\') 208# define HAS_DEVICE(P) \ 209 ((((P)[0] >= 'A' && (P)[0] <= 'Z') || ((P)[0] >= 'a' && (P)[0] <= 'z')) \ 210 && (P)[1] == ':') 211# define IS_ABSOLUTE_PATH(P) (ISSLASH ((P)[0]) || HAS_DEVICE (P)) 212# define IS_PATH_WITH_DIR(P) \ 213 (strchr (P, '/') != NULL || strchr (P, '\\') != NULL || HAS_DEVICE (P)) 214#else 215 /* Unix */ 216# define ISSLASH(C) ((C) == '/') 217# define IS_ABSOLUTE_PATH(P) ISSLASH ((P)[0]) 218# define IS_PATH_WITH_DIR(P) (strchr (P, '/') != NULL) 219#endif 220 221/* This is the type used for the search tree where known translations 222 are stored. */ 223struct known_translation_t 224{ 225 /* Domain in which to search. */ 226 char *domainname; 227 228 /* The category. */ 229 int category; 230 231 /* State of the catalog counter at the point the string was found. */ 232 int counter; 233 234 /* Catalog where the string was found. */ 235 struct loaded_l10nfile *domain; 236 237 /* And finally the translation. */ 238 const char *translation; 239 size_t translation_length; 240 241 /* Pointer to the string in question. */ 242 char msgid[ZERO]; 243}; 244 245/* Root of the search tree with known translations. We can use this 246 only if the system provides the `tsearch' function family. */ 247#if defined HAVE_TSEARCH || defined _LIBC 248# include <search.h> 249 250static void *root; 251 252# ifdef _LIBC 253# define tsearch __tsearch 254# endif 255 256/* Function to compare two entries in the table of known translations. */ 257static int transcmp PARAMS ((const void *p1, const void *p2)); 258static int 259transcmp (p1, p2) 260 const void *p1; 261 const void *p2; 262{ 263 const struct known_translation_t *s1; 264 const struct known_translation_t *s2; 265 int result; 266 267 s1 = (const struct known_translation_t *) p1; 268 s2 = (const struct known_translation_t *) p2; 269 270 result = strcmp (s1->msgid, s2->msgid); 271 if (result == 0) 272 { 273 result = strcmp (s1->domainname, s2->domainname); 274 if (result == 0) 275 /* We compare the category last (though this is the cheapest 276 operation) since it is hopefully always the same (namely 277 LC_MESSAGES). */ 278 result = s1->category - s2->category; 279 } 280 281 return result; 282} 283#endif 284 285#ifndef INTVARDEF 286# define INTVARDEF(name) 287#endif 288#ifndef INTUSE 289# define INTUSE(name) name 290#endif 291 292/* Name of the default domain used for gettext(3) prior any call to 293 textdomain(3). The default value for this is "messages". */ 294const char _nl_default_default_domain[] attribute_hidden = "messages"; 295 296/* Value used as the default domain for gettext(3). */ 297const char *_nl_current_default_domain attribute_hidden 298 = _nl_default_default_domain; 299 300/* Contains the default location of the message catalogs. */ 301#if defined __EMX__ 302extern const char _nl_default_dirname[]; 303#else 304const char _nl_default_dirname[] = LOCALEDIR; 305INTVARDEF (_nl_default_dirname) 306#endif 307 308/* List with bindings of specific domains created by bindtextdomain() 309 calls. */ 310struct binding *_nl_domain_bindings; 311 312/* Prototypes for local functions. */ 313static char *plural_lookup PARAMS ((struct loaded_l10nfile *domain, 314 unsigned long int n, 315 const char *translation, 316 size_t translation_len)) 317 internal_function; 318static const char *guess_category_value PARAMS ((int category, 319 const char *categoryname)) 320 internal_function; 321#ifdef _LIBC 322# include "../locale/localeinfo.h" 323# define category_to_name(category) _nl_category_names[category] 324#else 325static const char *category_to_name PARAMS ((int category)) internal_function; 326#endif 327 328 329/* For those loosing systems which don't have `alloca' we have to add 330 some additional code emulating it. */ 331#ifdef HAVE_ALLOCA 332/* Nothing has to be done. */ 333# define freea(p) /* nothing */ 334# define ADD_BLOCK(list, address) /* nothing */ 335# define FREE_BLOCKS(list) /* nothing */ 336#else 337struct block_list 338{ 339 void *address; 340 struct block_list *next; 341}; 342# define ADD_BLOCK(list, addr) \ 343 do { \ 344 struct block_list *newp = (struct block_list *) malloc (sizeof (*newp)); \ 345 /* If we cannot get a free block we cannot add the new element to \ 346 the list. */ \ 347 if (newp != NULL) { \ 348 newp->address = (addr); \ 349 newp->next = (list); \ 350 (list) = newp; \ 351 } \ 352 } while (0) 353# define FREE_BLOCKS(list) \ 354 do { \ 355 while (list != NULL) { \ 356 struct block_list *old = list; \ 357 list = list->next; \ 358 free (old->address); \ 359 free (old); \ 360 } \ 361 } while (0) 362# undef alloca 363# define alloca(size) (malloc (size)) 364# define freea(p) free (p) 365#endif /* have alloca */ 366 367 368#ifdef _LIBC 369/* List of blocks allocated for translations. */ 370typedef struct transmem_list 371{ 372 struct transmem_list *next; 373 char data[ZERO]; 374} transmem_block_t; 375static struct transmem_list *transmem_list; 376#else 377typedef unsigned char transmem_block_t; 378#endif 379 380 381/* Names for the libintl functions are a problem. They must not clash 382 with existing names and they should follow ANSI C. But this source 383 code is also used in GNU C Library where the names have a __ 384 prefix. So we have to make a difference here. */ 385#ifdef _LIBC 386# define DCIGETTEXT __dcigettext 387#else 388# define DCIGETTEXT libintl_dcigettext 389#endif 390 391/* Lock variable to protect the global data in the gettext implementation. */ 392#ifdef _LIBC 393__libc_rwlock_define_initialized (, _nl_state_lock attribute_hidden) 394#endif 395 396/* Checking whether the binaries runs SUID must be done and glibc provides 397 easier methods therefore we make a difference here. */ 398#ifdef _LIBC 399# define ENABLE_SECURE __libc_enable_secure 400# define DETERMINE_SECURE 401#else 402# ifndef HAVE_GETUID 403# define getuid() 0 404# endif 405# ifndef HAVE_GETGID 406# define getgid() 0 407# endif 408# ifndef HAVE_GETEUID 409# define geteuid() getuid() 410# endif 411# ifndef HAVE_GETEGID 412# define getegid() getgid() 413# endif 414static int enable_secure; 415# define ENABLE_SECURE (enable_secure == 1) 416# define DETERMINE_SECURE \ 417 if (enable_secure == 0) \ 418 { \ 419 if (getuid () != geteuid () || getgid () != getegid ()) \ 420 enable_secure = 1; \ 421 else \ 422 enable_secure = -1; \ 423 } 424#endif 425 426#ifndef HAVE_RAISE 427# define raise(x) kill (getpid (), (x)) 428#endif 429 430/* Get the function to evaluate the plural expression. */ 431#include "eval-plural.h" 432 433/* Look up MSGID in the DOMAINNAME message catalog for the current 434 CATEGORY locale and, if PLURAL is nonzero, search over string 435 depending on the plural form determined by N. */ 436char * 437DCIGETTEXT (domainname, msgid1, msgid2, plural, n, category) 438 const char *domainname; 439 const char *msgid1; 440 const char *msgid2; 441 int plural; 442 unsigned long int n; 443 int category; 444{ 445#ifndef HAVE_ALLOCA 446 struct block_list *block_list = NULL; 447#endif 448 struct loaded_l10nfile *domain; 449 struct binding *binding; 450 const char *categoryname; 451 const char *categoryvalue; 452 char *dirname, *xdomainname; 453 char *single_locale; 454 char *retval; 455 size_t retlen; 456 int saved_errno; 457#if defined HAVE_TSEARCH || defined _LIBC 458 struct known_translation_t *search; 459 struct known_translation_t **foundp = NULL; 460 size_t msgid_len; 461#endif 462 size_t domainname_len; 463 464 /* If no real MSGID is given return NULL. */ 465 if (msgid1 == NULL) 466 return NULL; 467 468#ifdef _LIBC 469 if (category < 0 || category >= __LC_LAST || category == LC_ALL) 470 /* Bogus. */ 471 return (plural == 0 472 ? (char *) msgid1 473 /* Use the Germanic plural rule. */ 474 : n == 1 ? (char *) msgid1 : (char *) msgid2); 475#endif 476 477 __libc_rwlock_rdlock (_nl_state_lock); 478 479 /* If DOMAINNAME is NULL, we are interested in the default domain. If 480 CATEGORY is not LC_MESSAGES this might not make much sense but the 481 definition left this undefined. */ 482 if (domainname == NULL) 483 domainname = _nl_current_default_domain; 484 485 /* OS/2 specific: backward compatibility with older libintl versions */ 486#ifdef LC_MESSAGES_COMPAT 487 if (category == LC_MESSAGES_COMPAT) 488 category = LC_MESSAGES; 489#endif 490 491#if defined HAVE_TSEARCH || defined _LIBC 492 msgid_len = strlen (msgid1) + 1; 493 494 /* Try to find the translation among those which we found at 495 some time. */ 496 search = (struct known_translation_t *) 497 alloca (offsetof (struct known_translation_t, msgid) + msgid_len); 498 memcpy (search->msgid, msgid1, msgid_len); 499 search->domainname = (char *) domainname; 500 search->category = category; 501 502 foundp = (struct known_translation_t **) tfind (search, &root, transcmp); 503 freea (search); 504 if (foundp != NULL && (*foundp)->counter == _nl_msg_cat_cntr) 505 { 506 /* Now deal with plural. */ 507 if (plural) 508 retval = plural_lookup ((*foundp)->domain, n, (*foundp)->translation, 509 (*foundp)->translation_length); 510 else 511 retval = (char *) (*foundp)->translation; 512 513 __libc_rwlock_unlock (_nl_state_lock); 514 return retval; 515 } 516#endif 517 518 /* Preserve the `errno' value. */ 519 saved_errno = errno; 520 521 /* See whether this is a SUID binary or not. */ 522 DETERMINE_SECURE; 523 524 /* First find matching binding. */ 525 for (binding = _nl_domain_bindings; binding != NULL; binding = binding->next) 526 { 527 int compare = strcmp (domainname, binding->domainname); 528 if (compare == 0) 529 /* We found it! */ 530 break; 531 if (compare < 0) 532 { 533 /* It is not in the list. */ 534 binding = NULL; 535 break; 536 } 537 } 538 539 if (binding == NULL) 540 dirname = (char *) INTUSE(_nl_default_dirname); 541 else if (IS_ABSOLUTE_PATH (binding->dirname)) 542 dirname = binding->dirname; 543 else 544 { 545 /* We have a relative path. Make it absolute now. */ 546 size_t dirname_len = strlen (binding->dirname) + 1; 547 size_t path_max; 548 char *ret; 549 550 path_max = (unsigned int) PATH_MAX; 551 path_max += 2; /* The getcwd docs say to do this. */ 552 553 for (;;) 554 { 555 dirname = (char *) alloca (path_max + dirname_len); 556 ADD_BLOCK (block_list, dirname); 557 558 __set_errno (0); 559 ret = getcwd (dirname, path_max); 560 if (ret != NULL || errno != ERANGE) 561 break; 562 563 path_max += path_max / 2; 564 path_max += PATH_INCR; 565 } 566 567 if (ret == NULL) 568 /* We cannot get the current working directory. Don't signal an 569 error but simply return the default string. */ 570 goto return_untranslated; 571 572 stpcpy (stpcpy (strchr (dirname, '\0'), "/"), binding->dirname); 573 } 574 575 /* Now determine the symbolic name of CATEGORY and its value. */ 576 categoryname = category_to_name (category); 577 categoryvalue = guess_category_value (category, categoryname); 578 579 domainname_len = strlen (domainname); 580 xdomainname = (char *) alloca (strlen (categoryname) 581 + domainname_len + 5); 582 ADD_BLOCK (block_list, xdomainname); 583 584 stpcpy (mempcpy (stpcpy (stpcpy (xdomainname, categoryname), "/"), 585 domainname, domainname_len), 586 ".mo"); 587 588 /* Creating working area. */ 589 single_locale = (char *) alloca (strlen (categoryvalue) + 1); 590 ADD_BLOCK (block_list, single_locale); 591 592 593 /* Search for the given string. This is a loop because we perhaps 594 got an ordered list of languages to consider for the translation. */ 595 while (1) 596 { 597 /* Make CATEGORYVALUE point to the next element of the list. */ 598 while (categoryvalue[0] != '\0' && categoryvalue[0] == ':') 599 ++categoryvalue; 600 if (categoryvalue[0] == '\0') 601 { 602 /* The whole contents of CATEGORYVALUE has been searched but 603 no valid entry has been found. We solve this situation 604 by implicitly appending a "C" entry, i.e. no translation 605 will take place. */ 606 single_locale[0] = 'C'; 607 single_locale[1] = '\0'; 608 } 609 else 610 { 611 char *cp = single_locale; 612 while (categoryvalue[0] != '\0' && categoryvalue[0] != ':') 613 *cp++ = *categoryvalue++; 614 *cp = '\0'; 615 616 /* When this is a SUID binary we must not allow accessing files 617 outside the dedicated directories. */ 618 if (ENABLE_SECURE && IS_PATH_WITH_DIR (single_locale)) 619 /* Ingore this entry. */ 620 continue; 621 } 622 623 /* If the current locale value is C (or POSIX) we don't load a 624 domain. Return the MSGID. */ 625 if (strcmp (single_locale, "C") == 0 626 || strcmp (single_locale, "POSIX") == 0) 627 break; 628 629 /* Find structure describing the message catalog matching the 630 DOMAINNAME and CATEGORY. */ 631 domain = _nl_find_domain (dirname, single_locale, xdomainname, binding); 632 633 if (domain != NULL) 634 { 635 retval = _nl_find_msg (domain, binding, msgid1, &retlen); 636 637 if (retval == NULL) 638 { 639 int cnt; 640 641 for (cnt = 0; domain->successor[cnt] != NULL; ++cnt) 642 { 643 retval = _nl_find_msg (domain->successor[cnt], binding, 644 msgid1, &retlen); 645 646 if (retval != NULL) 647 { 648 domain = domain->successor[cnt]; 649 break; 650 } 651 } 652 } 653 654 if (retval != NULL) 655 { 656 /* Found the translation of MSGID1 in domain DOMAIN: 657 starting at RETVAL, RETLEN bytes. */ 658 FREE_BLOCKS (block_list); 659#if defined HAVE_TSEARCH || defined _LIBC 660 if (foundp == NULL) 661 { 662 /* Create a new entry and add it to the search tree. */ 663 struct known_translation_t *newp; 664 665 newp = (struct known_translation_t *) 666 malloc (offsetof (struct known_translation_t, msgid) 667 + msgid_len + domainname_len + 1); 668 if (newp != NULL) 669 { 670 newp->domainname = 671 mempcpy (newp->msgid, msgid1, msgid_len); 672 memcpy (newp->domainname, domainname, domainname_len + 1); 673 newp->category = category; 674 newp->counter = _nl_msg_cat_cntr; 675 newp->domain = domain; 676 newp->translation = retval; 677 newp->translation_length = retlen; 678 679 /* Insert the entry in the search tree. */ 680 foundp = (struct known_translation_t **) 681 tsearch (newp, &root, transcmp); 682 if (foundp == NULL 683 || __builtin_expect (*foundp != newp, 0)) 684 /* The insert failed. */ 685 free (newp); 686 } 687 } 688 else 689 { 690 /* We can update the existing entry. */ 691 (*foundp)->counter = _nl_msg_cat_cntr; 692 (*foundp)->domain = domain; 693 (*foundp)->translation = retval; 694 (*foundp)->translation_length = retlen; 695 } 696#endif 697 __set_errno (saved_errno); 698 699 /* Now deal with plural. */ 700 if (plural) 701 retval = plural_lookup (domain, n, retval, retlen); 702 703 __libc_rwlock_unlock (_nl_state_lock); 704 return retval; 705 } 706 } 707 } 708 709 return_untranslated: 710 /* Return the untranslated MSGID. */ 711 FREE_BLOCKS (block_list); 712 __libc_rwlock_unlock (_nl_state_lock); 713#ifndef _LIBC 714 if (!ENABLE_SECURE) 715 { 716 extern void _nl_log_untranslated PARAMS ((const char *logfilename, 717 const char *domainname, 718 const char *msgid1, 719 const char *msgid2, 720 int plural)); 721 const char *logfilename = getenv ("GETTEXT_LOG_UNTRANSLATED"); 722 723 if (logfilename != NULL && logfilename[0] != '\0') 724 _nl_log_untranslated (logfilename, domainname, msgid1, msgid2, plural); 725 } 726#endif 727 __set_errno (saved_errno); 728 return (plural == 0 729 ? (char *) msgid1 730 /* Use the Germanic plural rule. */ 731 : n == 1 ? (char *) msgid1 : (char *) msgid2); 732} 733 734 735char * 736internal_function 737_nl_find_msg (domain_file, domainbinding, msgid, lengthp) 738 struct loaded_l10nfile *domain_file; 739 struct binding *domainbinding; 740 const char *msgid; 741 size_t *lengthp; 742{ 743 struct loaded_domain *domain; 744 nls_uint32 nstrings; 745 size_t act; 746 char *result; 747 size_t resultlen; 748 749 if (domain_file->decided == 0) 750 _nl_load_domain (domain_file, domainbinding); 751 752 if (domain_file->data == NULL) 753 return NULL; 754 755 domain = (struct loaded_domain *) domain_file->data; 756 757 nstrings = domain->nstrings; 758 759 /* Locate the MSGID and its translation. */ 760 if (domain->hash_tab != NULL) 761 { 762 /* Use the hashing table. */ 763 nls_uint32 len = strlen (msgid); 764 nls_uint32 hash_val = hash_string (msgid); 765 nls_uint32 idx = hash_val % domain->hash_size; 766 nls_uint32 incr = 1 + (hash_val % (domain->hash_size - 2)); 767 768 while (1) 769 { 770 nls_uint32 nstr = 771 W (domain->must_swap_hash_tab, domain->hash_tab[idx]); 772 773 if (nstr == 0) 774 /* Hash table entry is empty. */ 775 return NULL; 776 777 nstr--; 778 779 /* Compare msgid with the original string at index nstr. 780 We compare the lengths with >=, not ==, because plural entries 781 are represented by strings with an embedded NUL. */ 782 if (nstr < nstrings 783 ? W (domain->must_swap, domain->orig_tab[nstr].length) >= len 784 && (strcmp (msgid, 785 domain->data + W (domain->must_swap, 786 domain->orig_tab[nstr].offset)) 787 == 0) 788 : domain->orig_sysdep_tab[nstr - nstrings].length > len 789 && (strcmp (msgid, 790 domain->orig_sysdep_tab[nstr - nstrings].pointer) 791 == 0)) 792 { 793 act = nstr; 794 goto found; 795 } 796 797 if (idx >= domain->hash_size - incr) 798 idx -= domain->hash_size - incr; 799 else 800 idx += incr; 801 } 802 /* NOTREACHED */ 803 } 804 else 805 { 806 /* Try the default method: binary search in the sorted array of 807 messages. */ 808 size_t top, bottom; 809 810 bottom = 0; 811 top = nstrings; 812 while (bottom < top) 813 { 814 int cmp_val; 815 816 act = (bottom + top) / 2; 817 cmp_val = strcmp (msgid, (domain->data 818 + W (domain->must_swap, 819 domain->orig_tab[act].offset))); 820 if (cmp_val < 0) 821 top = act; 822 else if (cmp_val > 0) 823 bottom = act + 1; 824 else 825 goto found; 826 } 827 /* No translation was found. */ 828 return NULL; 829 } 830 831 found: 832 /* The translation was found at index ACT. If we have to convert the 833 string to use a different character set, this is the time. */ 834 if (act < nstrings) 835 { 836 result = (char *) 837 (domain->data + W (domain->must_swap, domain->trans_tab[act].offset)); 838 resultlen = W (domain->must_swap, domain->trans_tab[act].length) + 1; 839 } 840 else 841 { 842 result = (char *) domain->trans_sysdep_tab[act - nstrings].pointer; 843 resultlen = domain->trans_sysdep_tab[act - nstrings].length; 844 } 845 846#if defined _LIBC || HAVE_ICONV 847 if (domain->codeset_cntr 848 != (domainbinding != NULL ? domainbinding->codeset_cntr : 0)) 849 { 850 /* The domain's codeset has changed through bind_textdomain_codeset() 851 since the message catalog was initialized or last accessed. We 852 have to reinitialize the converter. */ 853 _nl_free_domain_conv (domain); 854 _nl_init_domain_conv (domain_file, domain, domainbinding); 855 } 856 857 if ( 858# ifdef _LIBC 859 domain->conv != (__gconv_t) -1 860# else 861# if HAVE_ICONV 862 domain->conv != (iconv_t) -1 863# endif 864# endif 865 ) 866 { 867 /* We are supposed to do a conversion. First allocate an 868 appropriate table with the same structure as the table 869 of translations in the file, where we can put the pointers 870 to the converted strings in. 871 There is a slight complication with plural entries. They 872 are represented by consecutive NUL terminated strings. We 873 handle this case by converting RESULTLEN bytes, including 874 NULs. */ 875 876 if (domain->conv_tab == NULL 877 && ((domain->conv_tab = 878 (char **) calloc (nstrings + domain->n_sysdep_strings, 879 sizeof (char *))) 880 == NULL)) 881 /* Mark that we didn't succeed allocating a table. */ 882 domain->conv_tab = (char **) -1; 883 884 if (__builtin_expect (domain->conv_tab == (char **) -1, 0)) 885 /* Nothing we can do, no more memory. */ 886 goto converted; 887 888 if (domain->conv_tab[act] == NULL) 889 { 890 /* We haven't used this string so far, so it is not 891 translated yet. Do this now. */ 892 /* We use a bit more efficient memory handling. 893 We allocate always larger blocks which get used over 894 time. This is faster than many small allocations. */ 895 __libc_lock_define_initialized (static, lock) 896# define INITIAL_BLOCK_SIZE 4080 897 static unsigned char *freemem; 898 static size_t freemem_size; 899 900 const unsigned char *inbuf; 901 unsigned char *outbuf; 902 int malloc_count; 903# ifndef _LIBC 904 transmem_block_t *transmem_list = NULL; 905# endif 906 907 __libc_lock_lock (lock); 908 909 inbuf = (const unsigned char *) result; 910 outbuf = freemem + sizeof (size_t); 911 912 malloc_count = 0; 913 while (1) 914 { 915 transmem_block_t *newmem; 916# ifdef _LIBC 917 size_t non_reversible; 918 int res; 919 920 if (freemem_size < sizeof (size_t)) 921 goto resize_freemem; 922 923 res = __gconv (domain->conv, 924 &inbuf, inbuf + resultlen, 925 &outbuf, 926 outbuf + freemem_size - sizeof (size_t), 927 &non_reversible); 928 929 if (res == __GCONV_OK || res == __GCONV_EMPTY_INPUT) 930 break; 931 932 if (res != __GCONV_FULL_OUTPUT) 933 { 934 __libc_lock_unlock (lock); 935 goto converted; 936 } 937 938 inbuf = result; 939# else 940# if HAVE_ICONV 941 const char *inptr = (const char *) inbuf; 942 size_t inleft = resultlen; 943 char *outptr = (char *) outbuf; 944 size_t outleft; 945 946 if (freemem_size < sizeof (size_t)) 947 goto resize_freemem; 948 949 outleft = freemem_size - sizeof (size_t); 950 if (iconv (domain->conv, 951 (ICONV_CONST char **) &inptr, &inleft, 952 &outptr, &outleft) 953 != (size_t) (-1)) 954 { 955 outbuf = (unsigned char *) outptr; 956 break; 957 } 958 if (errno != E2BIG) 959 { 960 __libc_lock_unlock (lock); 961 goto converted; 962 } 963# endif 964# endif 965 966 resize_freemem: 967 /* We must allocate a new buffer or resize the old one. */ 968 if (malloc_count > 0) 969 { 970 ++malloc_count; 971 freemem_size = malloc_count * INITIAL_BLOCK_SIZE; 972 newmem = (transmem_block_t *) realloc (transmem_list, 973 freemem_size); 974# ifdef _LIBC 975 if (newmem != NULL) 976 transmem_list = transmem_list->next; 977 else 978 { 979 struct transmem_list *old = transmem_list; 980 981 transmem_list = transmem_list->next; 982 free (old); 983 } 984# endif 985 } 986 else 987 { 988 malloc_count = 1; 989 freemem_size = INITIAL_BLOCK_SIZE; 990 newmem = (transmem_block_t *) malloc (freemem_size); 991 } 992 if (__builtin_expect (newmem == NULL, 0)) 993 { 994 freemem = NULL; 995 freemem_size = 0; 996 __libc_lock_unlock (lock); 997 goto converted; 998 } 999 1000# ifdef _LIBC 1001 /* Add the block to the list of blocks we have to free 1002 at some point. */ 1003 newmem->next = transmem_list; 1004 transmem_list = newmem; 1005 1006 freemem = newmem->data; 1007 freemem_size -= offsetof (struct transmem_list, data); 1008# else 1009 transmem_list = newmem; 1010 freemem = newmem; 1011# endif 1012 1013 outbuf = freemem + sizeof (size_t); 1014 } 1015 1016 /* We have now in our buffer a converted string. Put this 1017 into the table of conversions. */ 1018 *(size_t *) freemem = outbuf - freemem - sizeof (size_t); 1019 domain->conv_tab[act] = (char *) freemem; 1020 /* Shrink freemem, but keep it aligned. */ 1021 freemem_size -= outbuf - freemem; 1022 freemem = outbuf; 1023 freemem += freemem_size & (alignof (size_t) - 1); 1024 freemem_size = freemem_size & ~ (alignof (size_t) - 1); 1025 1026 __libc_lock_unlock (lock); 1027 } 1028 1029 /* Now domain->conv_tab[act] contains the translation of all 1030 the plural variants. */ 1031 result = domain->conv_tab[act] + sizeof (size_t); 1032 resultlen = *(size_t *) domain->conv_tab[act]; 1033 } 1034 1035 converted: 1036 /* The result string is converted. */ 1037 1038#endif /* _LIBC || HAVE_ICONV */ 1039 1040 *lengthp = resultlen; 1041 return result; 1042} 1043 1044 1045/* Look up a plural variant. */ 1046static char * 1047internal_function 1048plural_lookup (domain, n, translation, translation_len) 1049 struct loaded_l10nfile *domain; 1050 unsigned long int n; 1051 const char *translation; 1052 size_t translation_len; 1053{ 1054 struct loaded_domain *domaindata = (struct loaded_domain *) domain->data; 1055 unsigned long int index; 1056 const char *p; 1057 1058 index = plural_eval (domaindata->plural, n); 1059 if (index >= domaindata->nplurals) 1060 /* This should never happen. It means the plural expression and the 1061 given maximum value do not match. */ 1062 index = 0; 1063 1064 /* Skip INDEX strings at TRANSLATION. */ 1065 p = translation; 1066 while (index-- > 0) 1067 { 1068#ifdef _LIBC 1069 p = __rawmemchr (p, '\0'); 1070#else 1071 p = strchr (p, '\0'); 1072#endif 1073 /* And skip over the NUL byte. */ 1074 p++; 1075 1076 if (p >= translation + translation_len) 1077 /* This should never happen. It means the plural expression 1078 evaluated to a value larger than the number of variants 1079 available for MSGID1. */ 1080 return (char *) translation; 1081 } 1082 return (char *) p; 1083} 1084 1085#ifndef _LIBC 1086/* Return string representation of locale CATEGORY. */ 1087static const char * 1088internal_function 1089category_to_name (category) 1090 int category; 1091{ 1092 const char *retval; 1093 1094 switch (category) 1095 { 1096#ifdef LC_COLLATE 1097 case LC_COLLATE: 1098 retval = "LC_COLLATE"; 1099 break; 1100#endif 1101#ifdef LC_CTYPE 1102 case LC_CTYPE: 1103 retval = "LC_CTYPE"; 1104 break; 1105#endif 1106#ifdef LC_MONETARY 1107 case LC_MONETARY: 1108 retval = "LC_MONETARY"; 1109 break; 1110#endif 1111#ifdef LC_NUMERIC 1112 case LC_NUMERIC: 1113 retval = "LC_NUMERIC"; 1114 break; 1115#endif 1116#ifdef LC_TIME 1117 case LC_TIME: 1118 retval = "LC_TIME"; 1119 break; 1120#endif 1121#ifdef LC_MESSAGES 1122 case LC_MESSAGES: 1123 retval = "LC_MESSAGES"; 1124 break; 1125#endif 1126#ifdef LC_RESPONSE 1127 case LC_RESPONSE: 1128 retval = "LC_RESPONSE"; 1129 break; 1130#endif 1131#ifdef LC_ALL 1132 case LC_ALL: 1133 /* This might not make sense but is perhaps better than any other 1134 value. */ 1135 retval = "LC_ALL"; 1136 break; 1137#endif 1138 default: 1139 /* If you have a better idea for a default value let me know. */ 1140 retval = "LC_XXX"; 1141 } 1142 1143 return retval; 1144} 1145#endif 1146 1147/* Guess value of current locale from value of the environment variables. */ 1148static const char * 1149internal_function 1150guess_category_value (category, categoryname) 1151 int category; 1152 const char *categoryname; 1153{ 1154 const char *language; 1155 const char *retval; 1156 1157 /* The highest priority value is the `LANGUAGE' environment 1158 variable. But we don't use the value if the currently selected 1159 locale is the C locale. This is a GNU extension. */ 1160 language = getenv ("LANGUAGE"); 1161 if (language != NULL && language[0] == '\0') 1162 language = NULL; 1163 1164 /* We have to proceed with the POSIX methods of looking to `LC_ALL', 1165 `LC_xxx', and `LANG'. On some systems this can be done by the 1166 `setlocale' function itself. */ 1167#ifdef _LIBC 1168 retval = __current_locale_name (category); 1169#else 1170 retval = _nl_locale_name (category, categoryname); 1171#endif 1172 1173 /* Ignore LANGUAGE if the locale is set to "C" because 1174 1. "C" locale usually uses the ASCII encoding, and most international 1175 messages use non-ASCII characters. These characters get displayed 1176 as question marks (if using glibc's iconv()) or as invalid 8-bit 1177 characters (because other iconv()s refuse to convert most non-ASCII 1178 characters to ASCII). In any case, the output is ugly. 1179 2. The precise output of some programs in the "C" locale is specified 1180 by POSIX and should not depend on environment variables like 1181 "LANGUAGE". We allow such programs to use gettext(). */ 1182 return language != NULL && strcmp (retval, "C") != 0 ? language : retval; 1183} 1184 1185/* @@ begin of epilog @@ */ 1186 1187/* We don't want libintl.a to depend on any other library. So we 1188 avoid the non-standard function stpcpy. In GNU C Library this 1189 function is available, though. Also allow the symbol HAVE_STPCPY 1190 to be defined. */ 1191#if !_LIBC && !HAVE_STPCPY 1192static char * 1193stpcpy (dest, src) 1194 char *dest; 1195 const char *src; 1196{ 1197 while ((*dest++ = *src++) != '\0') 1198 /* Do nothing. */ ; 1199 return dest - 1; 1200} 1201#endif 1202 1203#if !_LIBC && !HAVE_MEMPCPY 1204static void * 1205mempcpy (dest, src, n) 1206 void *dest; 1207 const void *src; 1208 size_t n; 1209{ 1210 return (void *) ((char *) memcpy (dest, src, n) + n); 1211} 1212#endif 1213 1214 1215#ifdef _LIBC 1216/* If we want to free all resources we have to do some work at 1217 program's end. */ 1218libc_freeres_fn (free_mem) 1219{ 1220 void *old; 1221 1222 while (_nl_domain_bindings != NULL) 1223 { 1224 struct binding *oldp = _nl_domain_bindings; 1225 _nl_domain_bindings = _nl_domain_bindings->next; 1226 if (oldp->dirname != INTUSE(_nl_default_dirname)) 1227 /* Yes, this is a pointer comparison. */ 1228 free (oldp->dirname); 1229 free (oldp->codeset); 1230 free (oldp); 1231 } 1232 1233 if (_nl_current_default_domain != _nl_default_default_domain) 1234 /* Yes, again a pointer comparison. */ 1235 free ((char *) _nl_current_default_domain); 1236 1237 /* Remove the search tree with the known translations. */ 1238 __tdestroy (root, free); 1239 root = NULL; 1240 1241 while (transmem_list != NULL) 1242 { 1243 old = transmem_list; 1244 transmem_list = transmem_list->next; 1245 free (old); 1246 } 1247} 1248#endif 1249