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