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