]> git.deb.at Git - pkg/abook.git/blob - intl/dcigettext.c
b2add5db3ecbd258fa92371b1e689bde565919a6
[pkg/abook.git] / intl / dcigettext.c
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
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 *
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
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
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
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
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
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 *
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 *
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.  */
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