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