1/* Implementation of the internal dcigettext function. 2 Copyright (C) 1995-1999, 2000-2007 Free Software Foundation, Inc. 3 4 This program is free software; you can redistribute it and/or modify it 5 under the terms of the GNU Library General Public License as published 6 by the Free Software Foundation; either version 2, or (at your option) 7 any later version. 8 9 This program is distributed in the hope that it will be useful, 10 but WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 Library General Public License for more details. 13 14 You should have received a copy of the GNU Library General Public 15 License along with this program; if not, write to the Free Software 16 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 17 USA. */ 18 19/* Tell glibc's <string.h> to provide a prototype for mempcpy(). 20 This must come before <config.h> because <config.h> may include 21 <features.h>, and once <features.h> has been included, it's too late. */ 22#ifndef _GNU_SOURCE 23# define _GNU_SOURCE 1 24#endif 25 26#ifdef HAVE_CONFIG_H 27# include <config.h> 28#endif 29 30/* NL_LOCALE_NAME does not work in glibc-2.4. Ignore it. */ 31#undef HAVE_NL_LOCALE_NAME 32 33#include <sys/types.h> 34 35#ifdef __GNUC__ 36# define alloca __builtin_alloca 37# define HAVE_ALLOCA 1 38#else 39# ifdef _MSC_VER 40# include <malloc.h> 41# define alloca _alloca 42# else 43# if defined HAVE_ALLOCA_H || defined _LIBC 44# include <alloca.h> 45# else 46# ifdef _AIX 47 #pragma alloca 48# else 49# ifndef alloca 50char *alloca (); 51# endif 52# endif 53# endif 54# endif 55#endif 56 57#include <errno.h> 58#ifndef errno 59extern int errno; 60#endif 61#ifndef __set_errno 62# define __set_errno(val) errno = (val) 63#endif 64 65#include <stddef.h> 66#include <stdlib.h> 67#include <string.h> 68 69#if defined HAVE_UNISTD_H || defined _LIBC 70# include <unistd.h> 71#endif 72 73#include <locale.h> 74 75#ifdef _LIBC 76 /* Guess whether integer division by zero raises signal SIGFPE. 77 Set to 1 only if you know for sure. In case of doubt, set to 0. */ 78# if defined __alpha__ || defined __arm__ || defined __i386__ \ 79 || defined __m68k__ || defined __s390__ 80# define INTDIV0_RAISES_SIGFPE 1 81# else 82# define INTDIV0_RAISES_SIGFPE 0 83# endif 84#endif 85#if !INTDIV0_RAISES_SIGFPE 86# include <signal.h> 87#endif 88 89#if defined HAVE_SYS_PARAM_H || defined _LIBC 90# include <sys/param.h> 91#endif 92 93#if !defined _LIBC 94# if HAVE_NL_LOCALE_NAME 95# include <langinfo.h> 96# endif 97# include "localcharset.h" 98#endif 99 100#include "gettextP.h" 101#include "plural-exp.h" 102#ifdef _LIBC 103# include <libintl.h> 104#else 105# ifdef IN_LIBGLOCALE 106# include <libintl.h> 107# endif 108# include "libgnuintl.h" 109#endif 110#include "hash-string.h" 111 112/* Handle multi-threaded applications. */ 113#ifdef _LIBC 114# include <bits/libc-lock.h> 115# define gl_rwlock_define_initialized __libc_rwlock_define_initialized 116# define gl_rwlock_rdlock __libc_rwlock_rdlock 117# define gl_rwlock_wrlock __libc_rwlock_wrlock 118# define gl_rwlock_unlock __libc_rwlock_unlock 119#else 120# include "lock.h" 121#endif 122 123/* Alignment of types. */ 124#if defined __GNUC__ && __GNUC__ >= 2 125# define alignof(TYPE) __alignof__ (TYPE) 126#else 127# define alignof(TYPE) \ 128 ((int) &((struct { char dummy1; TYPE dummy2; } *) 0)->dummy2) 129#endif 130 131/* Some compilers, like SunOS4 cc, don't have offsetof in <stddef.h>. */ 132#ifndef offsetof 133# define offsetof(type,ident) ((size_t)&(((type*)0)->ident)) 134#endif 135 136/* @@ end of prolog @@ */ 137 138#ifdef _LIBC 139/* Rename the non ANSI C functions. This is required by the standard 140 because some ANSI C functions will require linking with this object 141 file and the name space must not be polluted. */ 142# define getcwd __getcwd 143# ifndef stpcpy 144# define stpcpy __stpcpy 145# endif 146# define tfind __tfind 147#else 148# if !defined HAVE_GETCWD 149char *getwd (); 150# define getcwd(buf, max) getwd (buf) 151# else 152# if VMS 153# define getcwd(buf, max) (getcwd) (buf, max, 0) 154# else 155char *getcwd (); 156# endif 157# endif 158# ifndef HAVE_STPCPY 159static char *stpcpy (char *dest, const char *src); 160# endif 161# ifndef HAVE_MEMPCPY 162static void *mempcpy (void *dest, const void *src, size_t n); 163# endif 164#endif 165 166/* Use a replacement if the system does not provide the `tsearch' function 167 family. */ 168#if HAVE_TSEARCH || defined _LIBC 169# include <search.h> 170#else 171# define tsearch libintl_tsearch 172# define tfind libintl_tfind 173# define tdelete libintl_tdelete 174# define twalk libintl_twalk 175# include "tsearch.h" 176#endif 177 178#ifdef _LIBC 179# define tsearch __tsearch 180#endif 181 182/* Amount to increase buffer size by in each try. */ 183#define PATH_INCR 32 184 185/* The following is from pathmax.h. */ 186/* Non-POSIX BSD systems might have gcc's limits.h, which doesn't define 187 PATH_MAX but might cause redefinition warnings when sys/param.h is 188 later included (as on MORE/BSD 4.3). */ 189#if defined _POSIX_VERSION || (defined HAVE_LIMITS_H && !defined __GNUC__) 190# include <limits.h> 191#endif 192 193#ifndef _POSIX_PATH_MAX 194# define _POSIX_PATH_MAX 255 195#endif 196 197#if !defined PATH_MAX && defined _PC_PATH_MAX 198# define PATH_MAX (pathconf ("/", _PC_PATH_MAX) < 1 ? 1024 : pathconf ("/", _PC_PATH_MAX)) 199#endif 200 201/* Don't include sys/param.h if it already has been. */ 202#if defined HAVE_SYS_PARAM_H && !defined PATH_MAX && !defined MAXPATHLEN 203# include <sys/param.h> 204#endif 205 206#if !defined PATH_MAX && defined MAXPATHLEN 207# define PATH_MAX MAXPATHLEN 208#endif 209 210#ifndef PATH_MAX 211# define PATH_MAX _POSIX_PATH_MAX 212#endif 213 214/* Pathname support. 215 ISSLASH(C) tests whether C is a directory separator character. 216 IS_ABSOLUTE_PATH(P) tests whether P is an absolute path. If it is not, 217 it may be concatenated to a directory pathname. 218 IS_PATH_WITH_DIR(P) tests whether P contains a directory specification. 219 */ 220#if defined _WIN32 || defined __WIN32__ || defined __CYGWIN__ || defined __EMX__ || defined __DJGPP__ 221 /* Win32, Cygwin, OS/2, DOS */ 222# define ISSLASH(C) ((C) == '/' || (C) == '\\') 223# define HAS_DEVICE(P) \ 224 ((((P)[0] >= 'A' && (P)[0] <= 'Z') || ((P)[0] >= 'a' && (P)[0] <= 'z')) \ 225 && (P)[1] == ':') 226# define IS_ABSOLUTE_PATH(P) (ISSLASH ((P)[0]) || HAS_DEVICE (P)) 227# define IS_PATH_WITH_DIR(P) \ 228 (strchr (P, '/') != NULL || strchr (P, '\\') != NULL || HAS_DEVICE (P)) 229#else 230 /* Unix */ 231# define ISSLASH(C) ((C) == '/') 232# define IS_ABSOLUTE_PATH(P) ISSLASH ((P)[0]) 233# define IS_PATH_WITH_DIR(P) (strchr (P, '/') != NULL) 234#endif 235 236/* Whether to support different locales in different threads. */ 237#if defined _LIBC || HAVE_NL_LOCALE_NAME || (HAVE_STRUCT___LOCALE_STRUCT___NAMES && defined USE_IN_GETTEXT_TESTS) || defined IN_LIBGLOCALE 238# define HAVE_PER_THREAD_LOCALE 239#endif 240 241/* This is the type used for the search tree where known translations 242 are stored. */ 243struct known_translation_t 244{ 245 /* Domain in which to search. */ 246 const char *domainname; 247 248 /* The category. */ 249 int category; 250 251#ifdef HAVE_PER_THREAD_LOCALE 252 /* Name of the relevant locale category, or "" for the global locale. */ 253 const char *localename; 254#endif 255 256#ifdef IN_LIBGLOCALE 257 /* The character encoding. */ 258 const char *encoding; 259#endif 260 261 /* State of the catalog counter at the point the string was found. */ 262 int counter; 263 264 /* Catalog where the string was found. */ 265 struct loaded_l10nfile *domain; 266 267 /* And finally the translation. */ 268 const char *translation; 269 size_t translation_length; 270 271 /* Pointer to the string in question. */ 272 char msgid[ZERO]; 273}; 274 275gl_rwlock_define_initialized (static, tree_lock) 276 277/* Root of the search tree with known translations. */ 278static void *root; 279 280/* Function to compare two entries in the table of known translations. */ 281static int 282transcmp (const void *p1, const void *p2) 283{ 284 const struct known_translation_t *s1; 285 const struct known_translation_t *s2; 286 int result; 287 288 s1 = (const struct known_translation_t *) p1; 289 s2 = (const struct known_translation_t *) p2; 290 291 result = strcmp (s1->msgid, s2->msgid); 292 if (result == 0) 293 { 294 result = strcmp (s1->domainname, s2->domainname); 295 if (result == 0) 296 { 297#ifdef HAVE_PER_THREAD_LOCALE 298 result = strcmp (s1->localename, s2->localename); 299 if (result == 0) 300#endif 301 { 302#ifdef IN_LIBGLOCALE 303 result = strcmp (s1->encoding, s2->encoding); 304 if (result == 0) 305#endif 306 /* We compare the category last (though this is the cheapest 307 operation) since it is hopefully always the same (namely 308 LC_MESSAGES). */ 309 result = s1->category - s2->category; 310 } 311 } 312 } 313 314 return result; 315} 316 317/* Name of the default domain used for gettext(3) prior any call to 318 textdomain(3). The default value for this is "messages". */ 319const char _nl_default_default_domain[] attribute_hidden = "messages"; 320 321#ifndef IN_LIBGLOCALE 322/* Value used as the default domain for gettext(3). */ 323const char *_nl_current_default_domain attribute_hidden 324 = _nl_default_default_domain; 325#endif 326 327/* Contains the default location of the message catalogs. */ 328#if defined __EMX__ 329extern const char _nl_default_dirname[]; 330#else 331# ifdef _LIBC 332extern const char _nl_default_dirname[]; 333libc_hidden_proto (_nl_default_dirname) 334# endif 335const char _nl_default_dirname[] = LOCALEDIR; 336# ifdef _LIBC 337libc_hidden_data_def (_nl_default_dirname) 338# endif 339#endif 340 341#ifndef IN_LIBGLOCALE 342/* List with bindings of specific domains created by bindtextdomain() 343 calls. */ 344struct binding *_nl_domain_bindings; 345#endif 346 347/* Prototypes for local functions. */ 348static char *plural_lookup (struct loaded_l10nfile *domain, 349 unsigned long int n, 350 const char *translation, size_t translation_len) 351 internal_function; 352 353#ifdef IN_LIBGLOCALE 354static const char *guess_category_value (int category, 355 const char *categoryname, 356 const char *localename) 357 internal_function; 358#else 359static const char *guess_category_value (int category, 360 const char *categoryname) 361 internal_function; 362#endif 363 364#ifdef _LIBC 365# include "../locale/localeinfo.h" 366# define category_to_name(category) \ 367 _nl_category_names.str + _nl_category_name_idxs[category] 368#else 369static const char *category_to_name (int category) internal_function; 370#endif 371#if (defined _LIBC || HAVE_ICONV) && !defined IN_LIBGLOCALE 372static const char *get_output_charset (struct binding *domainbinding) 373 internal_function; 374#endif 375 376 377/* For those loosing systems which don't have `alloca' we have to add 378 some additional code emulating it. */ 379#ifdef HAVE_ALLOCA 380/* Nothing has to be done. */ 381# define freea(p) /* nothing */ 382# define ADD_BLOCK(list, address) /* nothing */ 383# define FREE_BLOCKS(list) /* nothing */ 384#else 385struct block_list 386{ 387 void *address; 388 struct block_list *next; 389}; 390# define ADD_BLOCK(list, addr) \ 391 do { \ 392 struct block_list *newp = (struct block_list *) malloc (sizeof (*newp)); \ 393 /* If we cannot get a free block we cannot add the new element to \ 394 the list. */ \ 395 if (newp != NULL) { \ 396 newp->address = (addr); \ 397 newp->next = (list); \ 398 (list) = newp; \ 399 } \ 400 } while (0) 401# define FREE_BLOCKS(list) \ 402 do { \ 403 while (list != NULL) { \ 404 struct block_list *old = list; \ 405 list = list->next; \ 406 free (old->address); \ 407 free (old); \ 408 } \ 409 } while (0) 410# undef alloca 411# define alloca(size) (malloc (size)) 412# define freea(p) free (p) 413#endif /* have alloca */ 414 415 416#ifdef _LIBC 417/* List of blocks allocated for translations. */ 418typedef struct transmem_list 419{ 420 struct transmem_list *next; 421 char data[ZERO]; 422} transmem_block_t; 423static struct transmem_list *transmem_list; 424#else 425typedef unsigned char transmem_block_t; 426#endif 427 428 429/* Names for the libintl functions are a problem. They must not clash 430 with existing names and they should follow ANSI C. But this source 431 code is also used in GNU C Library where the names have a __ 432 prefix. So we have to make a difference here. */ 433#ifdef _LIBC 434# define DCIGETTEXT __dcigettext 435#else 436# define DCIGETTEXT libintl_dcigettext 437#endif 438 439/* Lock variable to protect the global data in the gettext implementation. */ 440gl_rwlock_define_initialized (, _nl_state_lock attribute_hidden) 441 442/* Checking whether the binaries runs SUID must be done and glibc provides 443 easier methods therefore we make a difference here. */ 444#ifdef _LIBC 445# define ENABLE_SECURE __libc_enable_secure 446# define DETERMINE_SECURE 447#else 448# ifndef HAVE_GETUID 449# define getuid() 0 450# endif 451# ifndef HAVE_GETGID 452# define getgid() 0 453# endif 454# ifndef HAVE_GETEUID 455# define geteuid() getuid() 456# endif 457# ifndef HAVE_GETEGID 458# define getegid() getgid() 459# endif 460static int enable_secure; 461# define ENABLE_SECURE (enable_secure == 1) 462# define DETERMINE_SECURE \ 463 if (enable_secure == 0) \ 464 { \ 465 if (getuid () != geteuid () || getgid () != getegid ()) \ 466 enable_secure = 1; \ 467 else \ 468 enable_secure = -1; \ 469 } 470#endif 471 472/* Get the function to evaluate the plural expression. */ 473#include "eval-plural.h" 474 475/* Look up MSGID in the DOMAINNAME message catalog for the current 476 CATEGORY locale and, if PLURAL is nonzero, search over string 477 depending on the plural form determined by N. */ 478#ifdef IN_LIBGLOCALE 479char * 480gl_dcigettext (const char *domainname, 481 const char *msgid1, const char *msgid2, 482 int plural, unsigned long int n, 483 int category, 484 const char *localename, const char *encoding) 485#else 486char * 487DCIGETTEXT (const char *domainname, const char *msgid1, const char *msgid2, 488 int plural, unsigned long int n, int category) 489#endif 490{ 491#ifndef HAVE_ALLOCA 492 struct block_list *block_list = NULL; 493#endif 494 struct loaded_l10nfile *domain; 495 struct binding *binding; 496 const char *categoryname; 497 const char *categoryvalue; 498 const char *dirname; 499 char *xdomainname; 500 char *single_locale; 501 char *retval; 502 size_t retlen; 503 int saved_errno; 504 struct known_translation_t *search; 505 struct known_translation_t **foundp = NULL; 506 size_t msgid_len; 507#if defined HAVE_PER_THREAD_LOCALE && !defined IN_LIBGLOCALE 508 const char *localename; 509#endif 510 size_t domainname_len; 511 512 /* If no real MSGID is given return NULL. */ 513 if (msgid1 == NULL) 514 return NULL; 515 516#ifdef _LIBC 517 if (category < 0 || category >= __LC_LAST || category == LC_ALL) 518 /* Bogus. */ 519 return (plural == 0 520 ? (char *) msgid1 521 /* Use the Germanic plural rule. */ 522 : n == 1 ? (char *) msgid1 : (char *) msgid2); 523#endif 524 525 /* Preserve the `errno' value. */ 526 saved_errno = errno; 527 528 gl_rwlock_rdlock (_nl_state_lock); 529 530 /* If DOMAINNAME is NULL, we are interested in the default domain. If 531 CATEGORY is not LC_MESSAGES this might not make much sense but the 532 definition left this undefined. */ 533 if (domainname == NULL) 534 domainname = _nl_current_default_domain; 535 536 /* OS/2 specific: backward compatibility with older libintl versions */ 537#ifdef LC_MESSAGES_COMPAT 538 if (category == LC_MESSAGES_COMPAT) 539 category = LC_MESSAGES; 540#endif 541 542 msgid_len = strlen (msgid1) + 1; 543 544 /* Try to find the translation among those which we found at 545 some time. */ 546 search = (struct known_translation_t *) 547 alloca (offsetof (struct known_translation_t, msgid) + msgid_len); 548 memcpy (search->msgid, msgid1, msgid_len); 549 search->domainname = domainname; 550 search->category = category; 551#ifdef HAVE_PER_THREAD_LOCALE 552# ifndef IN_LIBGLOCALE 553# ifdef _LIBC 554 localename = __current_locale_name (category); 555# else 556# if HAVE_NL_LOCALE_NAME 557 /* NL_LOCALE_NAME is public glibc API introduced in glibc-2.4. */ 558 localename = nl_langinfo (NL_LOCALE_NAME (category)); 559# else 560# if HAVE_STRUCT___LOCALE_STRUCT___NAMES && defined USE_IN_GETTEXT_TESTS 561 /* The __names field is not public glibc API and must therefore not be used 562 in code that is installed in public locations. */ 563 { 564 locale_t thread_locale = uselocale (NULL); 565 if (thread_locale != LC_GLOBAL_LOCALE) 566 localename = thread_locale->__names[category]; 567 else 568 localename = ""; 569 } 570# endif 571# endif 572# endif 573# endif 574 search->localename = localename; 575# ifdef IN_LIBGLOCALE 576 search->encoding = encoding; 577# endif 578 579 /* Since tfind/tsearch manage a balanced tree, concurrent tfind and 580 tsearch calls can be fatal. */ 581 gl_rwlock_rdlock (tree_lock); 582 583 foundp = (struct known_translation_t **) tfind (search, &root, transcmp); 584 585 gl_rwlock_unlock (tree_lock); 586 587 freea (search); 588 if (foundp != NULL && (*foundp)->counter == _nl_msg_cat_cntr) 589 { 590 /* Now deal with plural. */ 591 if (plural) 592 retval = plural_lookup ((*foundp)->domain, n, (*foundp)->translation, 593 (*foundp)->translation_length); 594 else 595 retval = (char *) (*foundp)->translation; 596 597 gl_rwlock_unlock (_nl_state_lock); 598 __set_errno (saved_errno); 599 return retval; 600 } 601#endif 602 603 /* See whether this is a SUID binary or not. */ 604 DETERMINE_SECURE; 605 606 /* First find matching binding. */ 607#ifdef IN_LIBGLOCALE 608 /* We can use a trivial binding, since _nl_find_msg will ignore it anyway, 609 and _nl_load_domain and _nl_find_domain just pass it through. */ 610 binding = NULL; 611 dirname = bindtextdomain (domainname, NULL); 612#else 613 for (binding = _nl_domain_bindings; binding != NULL; binding = binding->next) 614 { 615 int compare = strcmp (domainname, binding->domainname); 616 if (compare == 0) 617 /* We found it! */ 618 break; 619 if (compare < 0) 620 { 621 /* It is not in the list. */ 622 binding = NULL; 623 break; 624 } 625 } 626 627 if (binding == NULL) 628 dirname = _nl_default_dirname; 629 else 630 { 631 dirname = binding->dirname; 632#endif 633 if (!IS_ABSOLUTE_PATH (dirname)) 634 { 635 /* We have a relative path. Make it absolute now. */ 636 size_t dirname_len = strlen (dirname) + 1; 637 size_t path_max; 638 char *resolved_dirname; 639 char *ret; 640 641 path_max = (unsigned int) PATH_MAX; 642 path_max += 2; /* The getcwd docs say to do this. */ 643 644 for (;;) 645 { 646 resolved_dirname = (char *) alloca (path_max + dirname_len); 647 ADD_BLOCK (block_list, tmp_dirname); 648 649 __set_errno (0); 650 ret = getcwd (resolved_dirname, path_max); 651 if (ret != NULL || errno != ERANGE) 652 break; 653 654 path_max += path_max / 2; 655 path_max += PATH_INCR; 656 } 657 658 if (ret == NULL) 659 /* We cannot get the current working directory. Don't signal an 660 error but simply return the default string. */ 661 goto return_untranslated; 662 663 stpcpy (stpcpy (strchr (resolved_dirname, '\0'), "/"), dirname); 664 dirname = resolved_dirname; 665 } 666#ifndef IN_LIBGLOCALE 667 } 668#endif 669 670 /* Now determine the symbolic name of CATEGORY and its value. */ 671 categoryname = category_to_name (category); 672#ifdef IN_LIBGLOCALE 673 categoryvalue = guess_category_value (category, categoryname, localename); 674#else 675 categoryvalue = guess_category_value (category, categoryname); 676#endif 677 678 domainname_len = strlen (domainname); 679 xdomainname = (char *) alloca (strlen (categoryname) 680 + domainname_len + 5); 681 ADD_BLOCK (block_list, xdomainname); 682 683 stpcpy ((char *) mempcpy (stpcpy (stpcpy (xdomainname, categoryname), "/"), 684 domainname, domainname_len), 685 ".mo"); 686 687 /* Creating working area. */ 688 single_locale = (char *) alloca (strlen (categoryvalue) + 1); 689 ADD_BLOCK (block_list, single_locale); 690 691 692 /* Search for the given string. This is a loop because we perhaps 693 got an ordered list of languages to consider for the translation. */ 694 while (1) 695 { 696 /* Make CATEGORYVALUE point to the next element of the list. */ 697 while (categoryvalue[0] != '\0' && categoryvalue[0] == ':') 698 ++categoryvalue; 699 if (categoryvalue[0] == '\0') 700 { 701 /* The whole contents of CATEGORYVALUE has been searched but 702 no valid entry has been found. We solve this situation 703 by implicitly appending a "C" entry, i.e. no translation 704 will take place. */ 705 single_locale[0] = 'C'; 706 single_locale[1] = '\0'; 707 } 708 else 709 { 710 char *cp = single_locale; 711 while (categoryvalue[0] != '\0' && categoryvalue[0] != ':') 712 *cp++ = *categoryvalue++; 713 *cp = '\0'; 714 715 /* When this is a SUID binary we must not allow accessing files 716 outside the dedicated directories. */ 717 if (ENABLE_SECURE && IS_PATH_WITH_DIR (single_locale)) 718 /* Ingore this entry. */ 719 continue; 720 } 721 722 /* If the current locale value is C (or POSIX) we don't load a 723 domain. Return the MSGID. */ 724 if (strcmp (single_locale, "C") == 0 725 || strcmp (single_locale, "POSIX") == 0) 726 break; 727 728 /* Find structure describing the message catalog matching the 729 DOMAINNAME and CATEGORY. */ 730 domain = _nl_find_domain (dirname, single_locale, xdomainname, binding); 731 732 if (domain != NULL) 733 { 734#if defined IN_LIBGLOCALE 735 retval = _nl_find_msg (domain, binding, encoding, msgid1, &retlen); 736#else 737 retval = _nl_find_msg (domain, binding, msgid1, 1, &retlen); 738#endif 739 740 if (retval == NULL) 741 { 742 int cnt; 743 744 for (cnt = 0; domain->successor[cnt] != NULL; ++cnt) 745 { 746#if defined IN_LIBGLOCALE 747 retval = _nl_find_msg (domain->successor[cnt], binding, 748 encoding, msgid1, &retlen); 749#else 750 retval = _nl_find_msg (domain->successor[cnt], binding, 751 msgid1, 1, &retlen); 752#endif 753 754 if (retval != NULL) 755 { 756 domain = domain->successor[cnt]; 757 break; 758 } 759 } 760 } 761 762 /* Returning -1 means that some resource problem exists 763 (likely memory) and that the strings could not be 764 converted. Return the original strings. */ 765 if (__builtin_expect (retval == (char *) -1, 0)) 766 break; 767 768 if (retval != NULL) 769 { 770 /* Found the translation of MSGID1 in domain DOMAIN: 771 starting at RETVAL, RETLEN bytes. */ 772 FREE_BLOCKS (block_list); 773 if (foundp == NULL) 774 { 775 /* Create a new entry and add it to the search tree. */ 776 size_t size; 777 struct known_translation_t *newp; 778 779 size = offsetof (struct known_translation_t, msgid) 780 + msgid_len + domainname_len + 1; 781#ifdef HAVE_PER_THREAD_LOCALE 782 size += strlen (localename) + 1; 783#endif 784 newp = (struct known_translation_t *) malloc (size); 785 if (newp != NULL) 786 { 787 char *new_domainname; 788#ifdef HAVE_PER_THREAD_LOCALE 789 char *new_localename; 790#endif 791 792 new_domainname = 793 (char *) mempcpy (newp->msgid, msgid1, msgid_len); 794 memcpy (new_domainname, domainname, domainname_len + 1); 795#ifdef HAVE_PER_THREAD_LOCALE 796 new_localename = new_domainname + domainname_len + 1; 797 strcpy (new_localename, localename); 798#endif 799 newp->domainname = new_domainname; 800 newp->category = category; 801#ifdef HAVE_PER_THREAD_LOCALE 802 newp->localename = new_localename; 803#endif 804#ifdef IN_LIBGLOCALE 805 newp->encoding = encoding; 806#endif 807 newp->counter = _nl_msg_cat_cntr; 808 newp->domain = domain; 809 newp->translation = retval; 810 newp->translation_length = retlen; 811 812 gl_rwlock_wrlock (tree_lock); 813 814 /* Insert the entry in the search tree. */ 815 foundp = (struct known_translation_t **) 816 tsearch (newp, &root, transcmp); 817 818 gl_rwlock_unlock (tree_lock); 819 820 if (foundp == NULL 821 || __builtin_expect (*foundp != newp, 0)) 822 /* The insert failed. */ 823 free (newp); 824 } 825 } 826 else 827 { 828 /* We can update the existing entry. */ 829 (*foundp)->counter = _nl_msg_cat_cntr; 830 (*foundp)->domain = domain; 831 (*foundp)->translation = retval; 832 (*foundp)->translation_length = retlen; 833 } 834 835 __set_errno (saved_errno); 836 837 /* Now deal with plural. */ 838 if (plural) 839 retval = plural_lookup (domain, n, retval, retlen); 840 841 gl_rwlock_unlock (_nl_state_lock); 842 return retval; 843 } 844 } 845 } 846 847 return_untranslated: 848 /* Return the untranslated MSGID. */ 849 FREE_BLOCKS (block_list); 850 gl_rwlock_unlock (_nl_state_lock); 851#ifndef _LIBC 852 if (!ENABLE_SECURE) 853 { 854 extern void _nl_log_untranslated (const char *logfilename, 855 const char *domainname, 856 const char *msgid1, const char *msgid2, 857 int plural); 858 const char *logfilename = getenv ("GETTEXT_LOG_UNTRANSLATED"); 859 860 if (logfilename != NULL && logfilename[0] != '\0') 861 _nl_log_untranslated (logfilename, domainname, msgid1, msgid2, plural); 862 } 863#endif 864 __set_errno (saved_errno); 865 return (plural == 0 866 ? (char *) msgid1 867 /* Use the Germanic plural rule. */ 868 : n == 1 ? (char *) msgid1 : (char *) msgid2); 869} 870 871 872/* Look up the translation of msgid within DOMAIN_FILE and DOMAINBINDING. 873 Return it if found. Return NULL if not found or in case of a conversion 874 failure (problem in the particular message catalog). Return (char *) -1 875 in case of a memory allocation failure during conversion (only if 876 ENCODING != NULL resp. CONVERT == true). */ 877char * 878internal_function 879#ifdef IN_LIBGLOCALE 880_nl_find_msg (struct loaded_l10nfile *domain_file, 881 struct binding *domainbinding, const char *encoding, 882 const char *msgid, 883 size_t *lengthp) 884#else 885_nl_find_msg (struct loaded_l10nfile *domain_file, 886 struct binding *domainbinding, 887 const char *msgid, int convert, 888 size_t *lengthp) 889#endif 890{ 891 struct loaded_domain *domain; 892 nls_uint32 nstrings; 893 size_t act; 894 char *result; 895 size_t resultlen; 896 897 if (domain_file->decided <= 0) 898 _nl_load_domain (domain_file, domainbinding); 899 900 if (domain_file->data == NULL) 901 return NULL; 902 903 domain = (struct loaded_domain *) domain_file->data; 904 905 nstrings = domain->nstrings; 906 907 /* Locate the MSGID and its translation. */ 908 if (domain->hash_tab != NULL) 909 { 910 /* Use the hashing table. */ 911 nls_uint32 len = strlen (msgid); 912 nls_uint32 hash_val = __hash_string (msgid); 913 nls_uint32 idx = hash_val % domain->hash_size; 914 nls_uint32 incr = 1 + (hash_val % (domain->hash_size - 2)); 915 916 while (1) 917 { 918 nls_uint32 nstr = 919 W (domain->must_swap_hash_tab, domain->hash_tab[idx]); 920 921 if (nstr == 0) 922 /* Hash table entry is empty. */ 923 return NULL; 924 925 nstr--; 926 927 /* Compare msgid with the original string at index nstr. 928 We compare the lengths with >=, not ==, because plural entries 929 are represented by strings with an embedded NUL. */ 930 if (nstr < nstrings 931 ? W (domain->must_swap, domain->orig_tab[nstr].length) >= len 932 && (strcmp (msgid, 933 domain->data + W (domain->must_swap, 934 domain->orig_tab[nstr].offset)) 935 == 0) 936 : domain->orig_sysdep_tab[nstr - nstrings].length > len 937 && (strcmp (msgid, 938 domain->orig_sysdep_tab[nstr - nstrings].pointer) 939 == 0)) 940 { 941 act = nstr; 942 goto found; 943 } 944 945 if (idx >= domain->hash_size - incr) 946 idx -= domain->hash_size - incr; 947 else 948 idx += incr; 949 } 950 /* NOTREACHED */ 951 } 952 else 953 { 954 /* Try the default method: binary search in the sorted array of 955 messages. */ 956 size_t top, bottom; 957 958 bottom = 0; 959 top = nstrings; 960 while (bottom < top) 961 { 962 int cmp_val; 963 964 act = (bottom + top) / 2; 965 cmp_val = strcmp (msgid, (domain->data 966 + W (domain->must_swap, 967 domain->orig_tab[act].offset))); 968 if (cmp_val < 0) 969 top = act; 970 else if (cmp_val > 0) 971 bottom = act + 1; 972 else 973 goto found; 974 } 975 /* No translation was found. */ 976 return NULL; 977 } 978 979 found: 980 /* The translation was found at index ACT. If we have to convert the 981 string to use a different character set, this is the time. */ 982 if (act < nstrings) 983 { 984 result = (char *) 985 (domain->data + W (domain->must_swap, domain->trans_tab[act].offset)); 986 resultlen = W (domain->must_swap, domain->trans_tab[act].length) + 1; 987 } 988 else 989 { 990 result = (char *) domain->trans_sysdep_tab[act - nstrings].pointer; 991 resultlen = domain->trans_sysdep_tab[act - nstrings].length; 992 } 993 994#if defined _LIBC || HAVE_ICONV 995# ifdef IN_LIBGLOCALE 996 if (encoding != NULL) 997# else 998 if (convert) 999# endif 1000 { 1001 /* We are supposed to do a conversion. */ 1002# ifndef IN_LIBGLOCALE 1003 const char *encoding = get_output_charset (domainbinding); 1004# endif 1005 size_t nconversions; 1006 struct converted_domain *convd; 1007 size_t i; 1008 1009 /* Protect against reallocation of the table. */ 1010 gl_rwlock_rdlock (domain->conversions_lock); 1011 1012 /* Search whether a table with converted translations for this 1013 encoding has already been allocated. */ 1014 nconversions = domain->nconversions; 1015 convd = NULL; 1016 1017 for (i = nconversions; i > 0; ) 1018 { 1019 i--; 1020 if (strcmp (domain->conversions[i].encoding, encoding) == 0) 1021 { 1022 convd = &domain->conversions[i]; 1023 break; 1024 } 1025 } 1026 1027 gl_rwlock_unlock (domain->conversions_lock); 1028 1029 if (convd == NULL) 1030 { 1031 /* We have to allocate a new conversions table. */ 1032 gl_rwlock_wrlock (domain->conversions_lock); 1033 1034 /* Maybe in the meantime somebody added the translation. 1035 Recheck. */ 1036 for (i = nconversions; i > 0; ) 1037 { 1038 i--; 1039 if (strcmp (domain->conversions[i].encoding, encoding) == 0) 1040 { 1041 convd = &domain->conversions[i]; 1042 goto found_convd; 1043 } 1044 } 1045 1046 { 1047 /* Allocate a table for the converted translations for this 1048 encoding. */ 1049 struct converted_domain *new_conversions = 1050 (struct converted_domain *) 1051 (domain->conversions != NULL 1052 ? realloc (domain->conversions, 1053 (nconversions + 1) * sizeof (struct converted_domain)) 1054 : malloc ((nconversions + 1) * sizeof (struct converted_domain))); 1055 1056 if (__builtin_expect (new_conversions == NULL, 0)) 1057 { 1058 /* Nothing we can do, no more memory. We cannot use the 1059 translation because it might be encoded incorrectly. */ 1060 unlock_fail: 1061 gl_rwlock_unlock (domain->conversions_lock); 1062 return (char *) -1; 1063 } 1064 1065 domain->conversions = new_conversions; 1066 1067 /* Copy the 'encoding' string to permanent storage. */ 1068 encoding = strdup (encoding); 1069 if (__builtin_expect (encoding == NULL, 0)) 1070 /* Nothing we can do, no more memory. We cannot use the 1071 translation because it might be encoded incorrectly. */ 1072 goto unlock_fail; 1073 1074 convd = &new_conversions[nconversions]; 1075 convd->encoding = encoding; 1076 1077 /* Find out about the character set the file is encoded with. 1078 This can be found (in textual form) in the entry "". If this 1079 entry does not exist or if this does not contain the 'charset=' 1080 information, we will assume the charset matches the one the 1081 current locale and we don't have to perform any conversion. */ 1082# ifdef _LIBC 1083 convd->conv = (__gconv_t) -1; 1084# else 1085# if HAVE_ICONV 1086 convd->conv = (iconv_t) -1; 1087# endif 1088# endif 1089 { 1090 char *nullentry; 1091 size_t nullentrylen; 1092 1093 /* Get the header entry. This is a recursion, but it doesn't 1094 reallocate domain->conversions because we pass 1095 encoding = NULL or convert = 0, respectively. */ 1096 nullentry = 1097# ifdef IN_LIBGLOCALE 1098 _nl_find_msg (domain_file, domainbinding, NULL, "", 1099 &nullentrylen); 1100# else 1101 _nl_find_msg (domain_file, domainbinding, "", 0, &nullentrylen); 1102# endif 1103 1104 if (nullentry != NULL) 1105 { 1106 const char *charsetstr; 1107 1108 charsetstr = strstr (nullentry, "charset="); 1109 if (charsetstr != NULL) 1110 { 1111 size_t len; 1112 char *charset; 1113 const char *outcharset; 1114 1115 charsetstr += strlen ("charset="); 1116 len = strcspn (charsetstr, " \t\n"); 1117 1118 charset = (char *) alloca (len + 1); 1119# if defined _LIBC || HAVE_MEMPCPY 1120 *((char *) mempcpy (charset, charsetstr, len)) = '\0'; 1121# else 1122 memcpy (charset, charsetstr, len); 1123 charset[len] = '\0'; 1124# endif 1125 1126 outcharset = encoding; 1127 1128# ifdef _LIBC 1129 /* We always want to use transliteration. */ 1130 outcharset = norm_add_slashes (outcharset, "TRANSLIT"); 1131 charset = norm_add_slashes (charset, ""); 1132 int r = __gconv_open (outcharset, charset, &convd->conv, 1133 GCONV_AVOID_NOCONV); 1134 if (__builtin_expect (r != __GCONV_OK, 0)) 1135 { 1136 /* If the output encoding is the same there is 1137 nothing to do. Otherwise do not use the 1138 translation at all. */ 1139 if (__builtin_expect (r != __GCONV_NULCONV, 1)) 1140 { 1141 gl_rwlock_unlock (domain->conversions_lock); 1142 free ((char *) encoding); 1143 return NULL; 1144 } 1145 1146 convd->conv = (__gconv_t) -1; 1147 } 1148# else 1149# if HAVE_ICONV 1150 /* When using GNU libc >= 2.2 or GNU libiconv >= 1.5, 1151 we want to use transliteration. */ 1152# if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2) || __GLIBC__ > 2 \ 1153 || _LIBICONV_VERSION >= 0x0105 1154 if (strchr (outcharset, '/') == NULL) 1155 { 1156 char *tmp; 1157 1158 len = strlen (outcharset); 1159 tmp = (char *) alloca (len + 10 + 1); 1160 memcpy (tmp, outcharset, len); 1161 memcpy (tmp + len, "//TRANSLIT", 10 + 1); 1162 outcharset = tmp; 1163 1164 convd->conv = iconv_open (outcharset, charset); 1165 1166 freea (outcharset); 1167 } 1168 else 1169# endif 1170 convd->conv = iconv_open (outcharset, charset); 1171# endif 1172# endif 1173 1174 freea (charset); 1175 } 1176 } 1177 } 1178 convd->conv_tab = NULL; 1179 /* Here domain->conversions is still == new_conversions. */ 1180 domain->nconversions++; 1181 } 1182 1183 found_convd: 1184 gl_rwlock_unlock (domain->conversions_lock); 1185 } 1186 1187 if ( 1188# ifdef _LIBC 1189 convd->conv != (__gconv_t) -1 1190# else 1191# if HAVE_ICONV 1192 convd->conv != (iconv_t) -1 1193# endif 1194# endif 1195 ) 1196 { 1197 /* We are supposed to do a conversion. First allocate an 1198 appropriate table with the same structure as the table 1199 of translations in the file, where we can put the pointers 1200 to the converted strings in. 1201 There is a slight complication with plural entries. They 1202 are represented by consecutive NUL terminated strings. We 1203 handle this case by converting RESULTLEN bytes, including 1204 NULs. */ 1205 1206 if (convd->conv_tab == NULL 1207 && ((convd->conv_tab = 1208 (char **) calloc (nstrings + domain->n_sysdep_strings, 1209 sizeof (char *))) 1210 == NULL)) 1211 /* Mark that we didn't succeed allocating a table. */ 1212 convd->conv_tab = (char **) -1; 1213 1214 if (__builtin_expect (convd->conv_tab == (char **) -1, 0)) 1215 /* Nothing we can do, no more memory. We cannot use the 1216 translation because it might be encoded incorrectly. */ 1217 return (char *) -1; 1218 1219 if (convd->conv_tab[act] == NULL) 1220 { 1221 /* We haven't used this string so far, so it is not 1222 translated yet. Do this now. */ 1223 /* We use a bit more efficient memory handling. 1224 We allocate always larger blocks which get used over 1225 time. This is faster than many small allocations. */ 1226 __libc_lock_define_initialized (static, lock) 1227# define INITIAL_BLOCK_SIZE 4080 1228 static unsigned char *freemem; 1229 static size_t freemem_size; 1230 1231 const unsigned char *inbuf; 1232 unsigned char *outbuf; 1233 int malloc_count; 1234# ifndef _LIBC 1235 transmem_block_t *transmem_list = NULL; 1236# endif 1237 1238 __libc_lock_lock (lock); 1239 1240 inbuf = (const unsigned char *) result; 1241 outbuf = freemem + sizeof (size_t); 1242 1243 malloc_count = 0; 1244 while (1) 1245 { 1246 transmem_block_t *newmem; 1247# ifdef _LIBC 1248 size_t non_reversible; 1249 int res; 1250 1251 if (freemem_size < sizeof (size_t)) 1252 goto resize_freemem; 1253 1254 res = __gconv (convd->conv, 1255 &inbuf, inbuf + resultlen, 1256 &outbuf, 1257 outbuf + freemem_size - sizeof (size_t), 1258 &non_reversible); 1259 1260 if (res == __GCONV_OK || res == __GCONV_EMPTY_INPUT) 1261 break; 1262 1263 if (res != __GCONV_FULL_OUTPUT) 1264 { 1265 /* We should not use the translation at all, it 1266 is incorrectly encoded. */ 1267 __libc_lock_unlock (lock); 1268 return NULL; 1269 } 1270 1271 inbuf = (const unsigned char *) result; 1272# else 1273# if HAVE_ICONV 1274 const char *inptr = (const char *) inbuf; 1275 size_t inleft = resultlen; 1276 char *outptr = (char *) outbuf; 1277 size_t outleft; 1278 1279 if (freemem_size < sizeof (size_t)) 1280 goto resize_freemem; 1281 1282 outleft = freemem_size - sizeof (size_t); 1283 if (iconv (convd->conv, 1284 (ICONV_CONST char **) &inptr, &inleft, 1285 &outptr, &outleft) 1286 != (size_t) (-1)) 1287 { 1288 outbuf = (unsigned char *) outptr; 1289 break; 1290 } 1291 if (errno != E2BIG) 1292 { 1293 __libc_lock_unlock (lock); 1294 return NULL; 1295 } 1296# endif 1297# endif 1298 1299 resize_freemem: 1300 /* We must allocate a new buffer or resize the old one. */ 1301 if (malloc_count > 0) 1302 { 1303 ++malloc_count; 1304 freemem_size = malloc_count * INITIAL_BLOCK_SIZE; 1305 newmem = (transmem_block_t *) realloc (transmem_list, 1306 freemem_size); 1307# ifdef _LIBC 1308 if (newmem != NULL) 1309 transmem_list = transmem_list->next; 1310 else 1311 { 1312 struct transmem_list *old = transmem_list; 1313 1314 transmem_list = transmem_list->next; 1315 free (old); 1316 } 1317# endif 1318 } 1319 else 1320 { 1321 malloc_count = 1; 1322 freemem_size = INITIAL_BLOCK_SIZE; 1323 newmem = (transmem_block_t *) malloc (freemem_size); 1324 } 1325 if (__builtin_expect (newmem == NULL, 0)) 1326 { 1327 freemem = NULL; 1328 freemem_size = 0; 1329 __libc_lock_unlock (lock); 1330 return (char *) -1; 1331 } 1332 1333# ifdef _LIBC 1334 /* Add the block to the list of blocks we have to free 1335 at some point. */ 1336 newmem->next = transmem_list; 1337 transmem_list = newmem; 1338 1339 freemem = (unsigned char *) newmem->data; 1340 freemem_size -= offsetof (struct transmem_list, data); 1341# else 1342 transmem_list = newmem; 1343 freemem = newmem; 1344# endif 1345 1346 outbuf = freemem + sizeof (size_t); 1347 } 1348 1349 /* We have now in our buffer a converted string. Put this 1350 into the table of conversions. */ 1351 *(size_t *) freemem = outbuf - freemem - sizeof (size_t); 1352 convd->conv_tab[act] = (char *) freemem; 1353 /* Shrink freemem, but keep it aligned. */ 1354 freemem_size -= outbuf - freemem; 1355 freemem = outbuf; 1356 freemem += freemem_size & (alignof (size_t) - 1); 1357 freemem_size = freemem_size & ~ (alignof (size_t) - 1); 1358 1359 __libc_lock_unlock (lock); 1360 } 1361 1362 /* Now convd->conv_tab[act] contains the translation of all 1363 the plural variants. */ 1364 result = convd->conv_tab[act] + sizeof (size_t); 1365 resultlen = *(size_t *) convd->conv_tab[act]; 1366 } 1367 } 1368 1369 /* The result string is converted. */ 1370 1371#endif /* _LIBC || HAVE_ICONV */ 1372 1373 *lengthp = resultlen; 1374 return result; 1375} 1376 1377 1378/* Look up a plural variant. */ 1379static char * 1380internal_function 1381plural_lookup (struct loaded_l10nfile *domain, unsigned long int n, 1382 const char *translation, size_t translation_len) 1383{ 1384 struct loaded_domain *domaindata = (struct loaded_domain *) domain->data; 1385 unsigned long int index; 1386 const char *p; 1387 1388 index = plural_eval (domaindata->plural, n); 1389 if (index >= domaindata->nplurals) 1390 /* This should never happen. It means the plural expression and the 1391 given maximum value do not match. */ 1392 index = 0; 1393 1394 /* Skip INDEX strings at TRANSLATION. */ 1395 p = translation; 1396 while (index-- > 0) 1397 { 1398#ifdef _LIBC 1399 p = __rawmemchr (p, '\0'); 1400#else 1401 p = strchr (p, '\0'); 1402#endif 1403 /* And skip over the NUL byte. */ 1404 p++; 1405 1406 if (p >= translation + translation_len) 1407 /* This should never happen. It means the plural expression 1408 evaluated to a value larger than the number of variants 1409 available for MSGID1. */ 1410 return (char *) translation; 1411 } 1412 return (char *) p; 1413} 1414 1415#ifndef _LIBC 1416/* Return string representation of locale CATEGORY. */ 1417static const char * 1418internal_function 1419category_to_name (int category) 1420{ 1421 const char *retval; 1422 1423 switch (category) 1424 { 1425#ifdef LC_COLLATE 1426 case LC_COLLATE: 1427 retval = "LC_COLLATE"; 1428 break; 1429#endif 1430#ifdef LC_CTYPE 1431 case LC_CTYPE: 1432 retval = "LC_CTYPE"; 1433 break; 1434#endif 1435#ifdef LC_MONETARY 1436 case LC_MONETARY: 1437 retval = "LC_MONETARY"; 1438 break; 1439#endif 1440#ifdef LC_NUMERIC 1441 case LC_NUMERIC: 1442 retval = "LC_NUMERIC"; 1443 break; 1444#endif 1445#ifdef LC_TIME 1446 case LC_TIME: 1447 retval = "LC_TIME"; 1448 break; 1449#endif 1450#ifdef LC_MESSAGES 1451 case LC_MESSAGES: 1452 retval = "LC_MESSAGES"; 1453 break; 1454#endif 1455#ifdef LC_RESPONSE 1456 case LC_RESPONSE: 1457 retval = "LC_RESPONSE"; 1458 break; 1459#endif 1460#ifdef LC_ALL 1461 case LC_ALL: 1462 /* This might not make sense but is perhaps better than any other 1463 value. */ 1464 retval = "LC_ALL"; 1465 break; 1466#endif 1467 default: 1468 /* If you have a better idea for a default value let me know. */ 1469 retval = "LC_XXX"; 1470 } 1471 1472 return retval; 1473} 1474#endif 1475 1476/* Guess value of current locale from value of the environment variables 1477 or system-dependent defaults. */ 1478static const char * 1479internal_function 1480#ifdef IN_LIBGLOCALE 1481guess_category_value (int category, const char *categoryname, 1482 const char *locale) 1483 1484#else 1485guess_category_value (int category, const char *categoryname) 1486#endif 1487{ 1488 const char *language; 1489#ifndef IN_LIBGLOCALE 1490 const char *locale; 1491# ifndef _LIBC 1492 const char *language_default; 1493 int locale_defaulted; 1494# endif 1495#endif 1496 1497 /* We use the settings in the following order: 1498 1. The value of the environment variable 'LANGUAGE'. This is a GNU 1499 extension. Its value can be a colon-separated list of locale names. 1500 2. The value of the environment variable 'LC_ALL', 'LC_xxx', or 'LANG'. 1501 More precisely, the first among these that is set to a non-empty value. 1502 This is how POSIX specifies it. The value is a single locale name. 1503 3. A system-dependent preference list of languages. Its value can be a 1504 colon-separated list of locale names. 1505 4. A system-dependent default locale name. 1506 This way: 1507 - System-dependent settings can be overridden by environment variables. 1508 - If the system provides both a list of languages and a default locale, 1509 the former is used. */ 1510 1511#ifndef IN_LIBGLOCALE 1512 /* Fetch the locale name, through the POSIX method of looking to `LC_ALL', 1513 `LC_xxx', and `LANG'. On some systems this can be done by the 1514 `setlocale' function itself. */ 1515# ifdef _LIBC 1516 locale = __current_locale_name (category); 1517# else 1518# if HAVE_STRUCT___LOCALE_STRUCT___NAMES && defined USE_IN_GETTEXT_TESTS 1519 /* The __names field is not public glibc API and must therefore not be used 1520 in code that is installed in public locations. */ 1521 locale_t thread_locale = uselocale (NULL); 1522 if (thread_locale != LC_GLOBAL_LOCALE) 1523 { 1524 locale = thread_locale->__names[category]; 1525 locale_defaulted = 0; 1526 } 1527 else 1528# endif 1529 { 1530 locale = _nl_locale_name_posix (category, categoryname); 1531 locale_defaulted = 0; 1532 if (locale == NULL) 1533 { 1534 locale = _nl_locale_name_default (); 1535 locale_defaulted = 1; 1536 } 1537 } 1538# endif 1539#endif 1540 1541 /* Ignore LANGUAGE and its system-dependent analogon if the locale is set 1542 to "C" because 1543 1. "C" locale usually uses the ASCII encoding, and most international 1544 messages use non-ASCII characters. These characters get displayed 1545 as question marks (if using glibc's iconv()) or as invalid 8-bit 1546 characters (because other iconv()s refuse to convert most non-ASCII 1547 characters to ASCII). In any case, the output is ugly. 1548 2. The precise output of some programs in the "C" locale is specified 1549 by POSIX and should not depend on environment variables like 1550 "LANGUAGE" or system-dependent information. We allow such programs 1551 to use gettext(). */ 1552 if (strcmp (locale, "C") == 0) 1553 return locale; 1554 1555 /* The highest priority value is the value of the 'LANGUAGE' environment 1556 variable. */ 1557 language = getenv ("LANGUAGE"); 1558 if (language != NULL && language[0] != '\0') 1559 return language; 1560#if !defined IN_LIBGLOCALE && !defined _LIBC 1561 /* The next priority value is the locale name, if not defaulted. */ 1562 if (locale_defaulted) 1563 { 1564 /* The next priority value is the default language preferences list. */ 1565 language_default = _nl_language_preferences_default (); 1566 if (language_default != NULL) 1567 return language_default; 1568 } 1569 /* The least priority value is the locale name, if defaulted. */ 1570#endif 1571 return locale; 1572} 1573 1574#if (defined _LIBC || HAVE_ICONV) && !defined IN_LIBGLOCALE 1575/* Returns the output charset. */ 1576static const char * 1577internal_function 1578get_output_charset (struct binding *domainbinding) 1579{ 1580 /* The output charset should normally be determined by the locale. But 1581 sometimes the locale is not used or not correctly set up, so we provide 1582 a possibility for the user to override this: the OUTPUT_CHARSET 1583 environment variable. Moreover, the value specified through 1584 bind_textdomain_codeset overrides both. */ 1585 if (domainbinding != NULL && domainbinding->codeset != NULL) 1586 return domainbinding->codeset; 1587 else 1588 { 1589 /* For speed reasons, we look at the value of OUTPUT_CHARSET only 1590 once. This is a user variable that is not supposed to change 1591 during a program run. */ 1592 static char *output_charset_cache; 1593 static int output_charset_cached; 1594 1595 if (!output_charset_cached) 1596 { 1597 const char *value = getenv ("OUTPUT_CHARSET"); 1598 1599 if (value != NULL && value[0] != '\0') 1600 { 1601 size_t len = strlen (value) + 1; 1602 char *value_copy = (char *) malloc (len); 1603 1604 if (value_copy != NULL) 1605 memcpy (value_copy, value, len); 1606 output_charset_cache = value_copy; 1607 } 1608 output_charset_cached = 1; 1609 } 1610 1611 if (output_charset_cache != NULL) 1612 return output_charset_cache; 1613 else 1614 { 1615# ifdef _LIBC 1616 return _NL_CURRENT (LC_CTYPE, CODESET); 1617# else 1618# if HAVE_ICONV 1619 return locale_charset (); 1620# endif 1621# endif 1622 } 1623 } 1624} 1625#endif 1626 1627/* @@ begin of epilog @@ */ 1628 1629/* We don't want libintl.a to depend on any other library. So we 1630 avoid the non-standard function stpcpy. In GNU C Library this 1631 function is available, though. Also allow the symbol HAVE_STPCPY 1632 to be defined. */ 1633#if !_LIBC && !HAVE_STPCPY 1634static char * 1635stpcpy (char *dest, const char *src) 1636{ 1637 while ((*dest++ = *src++) != '\0') 1638 /* Do nothing. */ ; 1639 return dest - 1; 1640} 1641#endif 1642 1643#if !_LIBC && !HAVE_MEMPCPY 1644static void * 1645mempcpy (void *dest, const void *src, size_t n) 1646{ 1647 return (void *) ((char *) memcpy (dest, src, n) + n); 1648} 1649#endif 1650 1651#if !_LIBC && !HAVE_TSEARCH 1652# include "tsearch.c" 1653#endif 1654 1655 1656#ifdef _LIBC 1657/* If we want to free all resources we have to do some work at 1658 program's end. */ 1659libc_freeres_fn (free_mem) 1660{ 1661 void *old; 1662 1663 while (_nl_domain_bindings != NULL) 1664 { 1665 struct binding *oldp = _nl_domain_bindings; 1666 _nl_domain_bindings = _nl_domain_bindings->next; 1667 if (oldp->dirname != _nl_default_dirname) 1668 /* Yes, this is a pointer comparison. */ 1669 free (oldp->dirname); 1670 free (oldp->codeset); 1671 free (oldp); 1672 } 1673 1674 if (_nl_current_default_domain != _nl_default_default_domain) 1675 /* Yes, again a pointer comparison. */ 1676 free ((char *) _nl_current_default_domain); 1677 1678 /* Remove the search tree with the known translations. */ 1679 __tdestroy (root, free); 1680 root = NULL; 1681 1682 while (transmem_list != NULL) 1683 { 1684 old = transmem_list; 1685 transmem_list = transmem_list->next; 1686 free (old); 1687 } 1688} 1689#endif 1690