Home | History | Annotate | Line # | Download | only in intl
dcigettext.c revision 1.1
      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
     50 char *alloca ();
     51 #    endif
     52 #   endif
     53 #  endif
     54 # endif
     55 #endif
     56 
     57 #include <errno.h>
     58 #ifndef errno
     59 extern 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
    156 char *getwd ();
    157 #  define getcwd(buf, max) getwd (buf)
    158 # else
    159 #  if VMS
    160 #   define getcwd(buf, max) (getcwd) (buf, max, 0)
    161 #  else
    162 char *getcwd ();
    163 #  endif
    164 # endif
    165 # ifndef HAVE_STPCPY
    166 static char *stpcpy (char *dest, const char *src);
    167 # endif
    168 # ifndef HAVE_MEMPCPY
    169 static 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.  */
    234 struct 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 
    271 gl_rwlock_define_initialized (static, tree_lock)
    272 
    273 static 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.  */
    280 static int
    281 transcmp (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".  */
    319 const char _nl_default_default_domain[] attribute_hidden = "messages";
    320 
    321 #ifndef IN_LIBGLOCALE
    322 /* Value used as the default domain for gettext(3).  */
    323 const 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__
    329 extern const char _nl_default_dirname[];
    330 #else
    331 # ifdef _LIBC
    332 extern const char _nl_default_dirname[];
    333 libc_hidden_proto (_nl_default_dirname)
    334 # endif
    335 const char _nl_default_dirname[] = LOCALEDIR;
    336 # ifdef _LIBC
    337 libc_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.  */
    344 struct binding *_nl_domain_bindings;
    345 #endif
    346 
    347 /* Prototypes for local functions.  */
    348 static 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
    354 static const char *guess_category_value (int category,
    355 					 const char *categoryname,
    356 					 const char *localename)
    357      internal_function;
    358 #else
    359 static 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
    369 static const char *category_to_name (int category) internal_function;
    370 #endif
    371 #if (defined _LIBC || HAVE_ICONV) && !defined IN_LIBGLOCALE
    372 static 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
    385 struct 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.  */
    418 typedef struct transmem_list
    419 {
    420   struct transmem_list *next;
    421   char data[ZERO];
    422 } transmem_block_t;
    423 static struct transmem_list *transmem_list;
    424 #else
    425 typedef 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.  */
    440 gl_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
    460 static 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
    479 char *
    480 gl_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
    486 char *
    487 DCIGETTEXT (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).  */
    880 char *
    881 internal_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.  */
   1347 static char *
   1348 internal_function
   1349 plural_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.  */
   1385 static const char *
   1386 internal_function
   1387 category_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.  */
   1446 static const char *
   1447 internal_function
   1448 #ifdef IN_LIBGLOCALE
   1449 guess_category_value (int category, const char *categoryname,
   1450 		      const char *locale)
   1451 
   1452 #else
   1453 guess_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.  */
   1544 static const char *
   1545 internal_function
   1546 get_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
   1603 static char *
   1604 stpcpy (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
   1613 static void *
   1614 mempcpy (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.  */
   1624 libc_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