1/* Implementation of the internal dcigettext function.
2 Copyright (C) 1995-2017 Free Software Foundation, Inc.
3
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU Lesser General Public License as published by
6 the Free Software Foundation; either version 2.1 of the License, or
7 (at your option) 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
12 GNU Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>. */
16
17/* Tell glibc's <string.h> to provide a prototype for mempcpy().
18 This must come before <config.h> because <config.h> may include
19 <features.h>, and once <features.h> has been included, it's too late. */
20#ifndef _GNU_SOURCE
21# define _GNU_SOURCE 1
22#endif
23
24#ifdef HAVE_CONFIG_H
25# include <config.h>
26#endif
27
28#include <sys/types.h>
29
30#ifdef __GNUC__
31# define alloca __builtin_alloca
32# define HAVE_ALLOCA 1
33#else
34# ifdef _MSC_VER
35# include <malloc.h>
36# define alloca _alloca
37# else
38# if defined HAVE_ALLOCA_H || defined _LIBC
39# include <alloca.h>
40# else
41# ifdef _AIX
42 #pragma alloca
43# else
44# ifndef alloca
45char *alloca ();
46# endif
47# endif
48# endif
49# endif
50#endif
51
52#include <errno.h>
53#ifndef errno
54extern int errno;
55#endif
56#ifndef __set_errno
57# define __set_errno(val) errno = (val)
58#endif
59
60#include <stddef.h>
61#include <stdlib.h>
62#include <stdio.h>
63#include <string.h>
64
65#if defined HAVE_UNISTD_H || defined _LIBC
66# include <unistd.h>
67#endif
68
69#include <locale.h>
70
71#ifdef _LIBC
72 /* Guess whether integer division by zero raises signal SIGFPE.
73 Set to 1 only if you know for sure. In case of doubt, set to 0. */
74# if defined __alpha__ || defined __arm__ || defined __i386__ \
75 || defined __m68k__ || defined __s390__
76# define INTDIV0_RAISES_SIGFPE 1
77# else
78# define INTDIV0_RAISES_SIGFPE 0
79# endif
80#endif
81#if !INTDIV0_RAISES_SIGFPE
82# include <signal.h>
83#endif
84
85#if defined HAVE_SYS_PARAM_H || defined _LIBC
86# include <sys/param.h>
87#endif
88
89#if !defined _LIBC
90# include "localcharset.h"
91#endif
92
93#include "gettextP.h"
94#include "plural-exp.h"
95#ifdef _LIBC
96# include <libintl.h>
97#else
98# ifdef IN_LIBGLOCALE
99# include <libintl.h>
100# endif
101# include "libgnuintl.h"
102#endif
103#include "hash-string.h"
104
105/* Handle multi-threaded applications. */
106#ifdef _LIBC
107# include <libc-lock.h>
108# define gl_rwlock_define_initialized __libc_rwlock_define_initialized
109# define gl_rwlock_rdlock __libc_rwlock_rdlock
110# define gl_rwlock_wrlock __libc_rwlock_wrlock
111# define gl_rwlock_unlock __libc_rwlock_unlock
112#else
113# include "lock.h"
114#endif
115
116/* Alignment of types. */
117#if defined __GNUC__ && __GNUC__ >= 2
118# define alignof(TYPE) __alignof__ (TYPE)
119#else
120# define alignof(TYPE) \
121 ((int) &((struct { char dummy1; TYPE dummy2; } *) 0)->dummy2)
122#endif
123
124/* Some compilers, like SunOS4 cc, don't have offsetof in <stddef.h>. */
125#ifndef offsetof
126# define offsetof(type,ident) ((size_t)&(((type*)0)->ident))
127#endif
128
129/* @@ end of prolog @@ */
130
131#ifdef _LIBC
132/* Rename the non ANSI C functions. This is required by the standard
133 because some ANSI C functions will require linking with this object
134 file and the name space must not be polluted. */
135# define strdup __strdup
136# define getcwd __getcwd
137# ifndef stpcpy
138# define stpcpy __stpcpy
139# endif
140# define tfind __tfind
141#else
142# if !defined HAVE_GETCWD
143char *getwd ();
144# define getcwd(buf, max) getwd (buf)
145# else
146# if VMS
147# define getcwd(buf, max) (getcwd) (buf, max, 0)
148# else
149char *getcwd ();
150# endif
151# endif
152# ifndef HAVE_STPCPY
153static char *stpcpy (char *dest, const char *src);
154# endif
155# ifndef HAVE_MEMPCPY
156static 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 defined 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. */
237struct 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
274gl_rwlock_define_initialized (static, tree_lock)
275
276/* Root of the search tree with known translations. */
277static void *root;
278
279/* Function to compare two entries in the table of known translations. */
280static int
281transcmp (const void *p1, const void *p2)
282{
283 const struct known_translation_t *s1;
284 const struct known_translation_t *s2;
285 int result;
286
287 s1 = (const struct known_translation_t *) p1;
288 s2 = (const struct known_translation_t *) p2;
289
290 result = strcmp (s1->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". */
319const char _nl_default_default_domain[] attribute_hidden = "messages";
320
321#ifndef IN_LIBGLOCALE
322/* Value used as the default domain for gettext(3). */
323const char *_nl_current_default_domain attribute_hidden
324 = _nl_default_default_domain;
325#endif
326
327/* Contains the default location of the message catalogs. */
328#if defined __EMX__
329extern const char _nl_default_dirname[];
330#else
331# ifdef _LIBC
332extern const char _nl_default_dirname[];
333libc_hidden_proto (_nl_default_dirname)
334# endif
335const char _nl_default_dirname[] = LOCALEDIR;
336# ifdef _LIBC
337libc_hidden_data_def (_nl_default_dirname)
338# endif
339#endif
340
341#ifndef IN_LIBGLOCALE
342/* List with bindings of specific domains created by bindtextdomain()
343 calls. */
344struct binding *_nl_domain_bindings;
345#endif
346
347/* Prototypes for local functions. */
348static char *plural_lookup (struct loaded_l10nfile *domain,
349 unsigned long int n,
350 const char *translation, size_t translation_len)
351 internal_function;
352
353#ifdef IN_LIBGLOCALE
354static const char *guess_category_value (int category,
355 const char *categoryname,
356 const char *localename)
357 internal_function;
358#else
359static const char *guess_category_value (int category,
360 const char *categoryname)
361 internal_function;
362#endif
363
364#ifdef _LIBC
365# include "../locale/localeinfo.h"
366# define category_to_name(category) \
367 _nl_category_names.str + _nl_category_name_idxs[category]
368#else
369static const char *category_to_name (int category) internal_function;
370#endif
371#if (defined _LIBC || HAVE_ICONV) && !defined IN_LIBGLOCALE
372static const char *get_output_charset (struct binding *domainbinding)
373 internal_function;
374#endif
375
376
377/* For those losing systems which don't have `alloca' we have to add
378 some additional code emulating it. */
379#ifdef HAVE_ALLOCA
380/* Nothing has to be done. */
381# define freea(p) /* nothing */
382# define ADD_BLOCK(list, address) /* nothing */
383# define FREE_BLOCKS(list) /* nothing */
384#else
385struct block_list
386{
387 void *address;
388 struct block_list *next;
389};
390# define ADD_BLOCK(list, addr) \
391 do { \
392 struct block_list *newp = (struct block_list *) malloc (sizeof (*newp)); \
393 /* If we cannot get a free block we cannot add the new element to \
394 the list. */ \
395 if (newp != NULL) { \
396 newp->address = (addr); \
397 newp->next = (list); \
398 (list) = newp; \
399 } \
400 } while (0)
401# define FREE_BLOCKS(list) \
402 do { \
403 while (list != NULL) { \
404 struct block_list *old = list; \
405 list = list->next; \
406 free (old->address); \
407 free (old); \
408 } \
409 } while (0)
410# undef alloca
411# define alloca(size) (malloc (size))
412# define freea(p) free (p)
413#endif /* have alloca */
414
415
416#ifdef _LIBC
417/* List of blocks allocated for translations. */
418typedef struct transmem_list
419{
420 struct transmem_list *next;
421 char data[ZERO];
422} transmem_block_t;
423static struct transmem_list *transmem_list;
424#else
425typedef unsigned char transmem_block_t;
426#endif
427
428
429/* Names for the libintl functions are a problem. They must not clash
430 with existing names and they should follow ANSI C. But this source
431 code is also used in GNU C Library where the names have a __
432 prefix. So we have to make a difference here. */
433#ifdef _LIBC
434# define DCIGETTEXT __dcigettext
435#else
436# define DCIGETTEXT libintl_dcigettext
437#endif
438
439/* Lock variable to protect the global data in the gettext implementation. */
440gl_rwlock_define_initialized (, _nl_state_lock attribute_hidden)
441
442/* Checking whether the binaries runs SUID must be done and glibc provides
443 easier methods therefore we make a difference here. */
444#ifdef _LIBC
445# define ENABLE_SECURE __libc_enable_secure
446# define DETERMINE_SECURE
447#else
448# ifndef HAVE_GETUID
449# define getuid() 0
450# endif
451# ifndef HAVE_GETGID
452# define getgid() 0
453# endif
454# ifndef HAVE_GETEUID
455# define geteuid() getuid()
456# endif
457# ifndef HAVE_GETEGID
458# define getegid() getgid()
459# endif
460static int enable_secure;
461# define ENABLE_SECURE (enable_secure == 1)
462# define DETERMINE_SECURE \
463 if (enable_secure == 0) \
464 { \
465 if (getuid () != geteuid () || getgid () != getegid ()) \
466 enable_secure = 1; \
467 else \
468 enable_secure = -1; \
469 }
470#endif
471
472/* Get the function to evaluate the plural expression. */
473#include "eval-plural.h"
474
475/* Look up MSGID in the DOMAINNAME message catalog for the current
476 CATEGORY locale and, if PLURAL is nonzero, search over string
477 depending on the plural form determined by N. */
478#ifdef IN_LIBGLOCALE
479char *
480gl_dcigettext (const char *domainname,
481 const char *msgid1, const char *msgid2,
482 int plural, unsigned long int n,
483 int category,
484 const char *localename, const char *encoding)
485#else
486char *
487DCIGETTEXT (const char *domainname, const char *msgid1, const char *msgid2,
488 int plural, unsigned long int n, int category)
489#endif
490{
491#ifndef HAVE_ALLOCA
492 struct block_list *block_list = NULL;
493#endif
494 struct loaded_l10nfile *domain;
495 struct binding *binding;
496 const char *categoryname;
497 const char *categoryvalue;
498 const char *dirname;
499 char *xdirname = NULL;
500 char *xdomainname;
501 char *single_locale;
502 char *retval;
503 size_t retlen;
504 int saved_errno;
505 struct known_translation_t search;
506 struct known_translation_t **foundp = NULL;
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#ifdef _LIBC
529 __libc_rwlock_define (extern, __libc_setlocale_lock attribute_hidden)
530 __libc_rwlock_rdlock (__libc_setlocale_lock);
531#endif
532
533 gl_rwlock_rdlock (_nl_state_lock);
534
535 /* If DOMAINNAME is NULL, we are interested in the default domain. If
536 CATEGORY is not LC_MESSAGES this might not make much sense but the
537 definition left this undefined. */
538 if (domainname == NULL)
539 domainname = _nl_current_default_domain;
540
541 /* OS/2 specific: backward compatibility with older libintl versions */
542#ifdef LC_MESSAGES_COMPAT
543 if (category == LC_MESSAGES_COMPAT)
544 category = LC_MESSAGES;
545#endif
546
547 /* Try to find the translation among those which we found at
548 some time. */
549 search.domain = NULL;
550 search.msgid.ptr = msgid1;
551 search.domainname = domainname;
552 search.category = category;
553#ifdef HAVE_PER_THREAD_LOCALE
554# ifndef IN_LIBGLOCALE
555# ifdef _LIBC
556 localename = __current_locale_name (category);
557# else
558 categoryname = category_to_name (category);
559# define CATEGORYNAME_INITIALIZED
560 localename = _nl_locale_name_thread_unsafe (category, categoryname);
561 if (localename == NULL)
562 localename = "";
563# endif
564# endif
565 search.localename = localename;
566# ifdef IN_LIBGLOCALE
567 search.encoding = encoding;
568# endif
569
570 /* Since tfind/tsearch manage a balanced tree, concurrent tfind and
571 tsearch calls can be fatal. */
572 gl_rwlock_rdlock (tree_lock);
573
574 foundp = (struct known_translation_t **) tfind (&search, &root, transcmp);
575
576 gl_rwlock_unlock (tree_lock);
577
578 if (foundp != NULL && (*foundp)->counter == _nl_msg_cat_cntr)
579 {
580 /* Now deal with plural. */
581 if (plural)
582 retval = plural_lookup ((*foundp)->domain, n, (*foundp)->translation,
583 (*foundp)->translation_length);
584 else
585 retval = (char *) (*foundp)->translation;
586
587 gl_rwlock_unlock (_nl_state_lock);
588# ifdef _LIBC
589 __libc_rwlock_unlock (__libc_setlocale_lock);
590# endif
591 __set_errno (saved_errno);
592 return retval;
593 }
594#endif
595
596 /* See whether this is a SUID binary or not. */
597 DETERMINE_SECURE;
598
599 /* First find matching binding. */
600#ifdef IN_LIBGLOCALE
601 /* We can use a trivial binding, since _nl_find_msg will ignore it anyway,
602 and _nl_load_domain and _nl_find_domain just pass it through. */
603 binding = NULL;
604 dirname = bindtextdomain (domainname, NULL);
605#else
606 for (binding = _nl_domain_bindings; binding != NULL; binding = binding->next)
607 {
608 int compare = strcmp (domainname, binding->domainname);
609 if (compare == 0)
610 /* We found it! */
611 break;
612 if (compare < 0)
613 {
614 /* It is not in the list. */
615 binding = NULL;
616 break;
617 }
618 }
619
620 if (binding == NULL)
621 dirname = _nl_default_dirname;
622 else
623 {
624 dirname = binding->dirname;
625#endif
626 if (!IS_ABSOLUTE_PATH (dirname))
627 {
628 /* We have a relative path. Make it absolute now. */
629 char *cwd = getcwd (NULL, 0);
630 if (cwd == NULL)
631 /* We cannot get the current working directory. Don't
632 signal an error but simply return the default
633 string. */
634 goto return_untranslated;
635 int ret = __asprintf (&xdirname, "%s/%s", cwd, dirname);
636 free (cwd);
637 if (ret < 0)
638 goto return_untranslated;
639 dirname = xdirname;
640 }
641#ifndef IN_LIBGLOCALE
642 }
643#endif
644
645 /* Now determine the symbolic name of CATEGORY and its value. */
646#ifndef CATEGORYNAME_INITIALIZED
647 categoryname = category_to_name (category);
648#endif
649#ifdef IN_LIBGLOCALE
650 categoryvalue = guess_category_value (category, categoryname, localename);
651#else
652 categoryvalue = guess_category_value (category, categoryname);
653#endif
654
655 domainname_len = strlen (domainname);
656 xdomainname = (char *) alloca (strlen (categoryname)
657 + domainname_len + 5);
658 ADD_BLOCK (block_list, xdomainname);
659
660 stpcpy ((char *) mempcpy (stpcpy (stpcpy (xdomainname, categoryname), "/"),
661 domainname, domainname_len),
662 ".mo");
663
664 /* Creating working area. */
665 single_locale = (char *) alloca (strlen (categoryvalue) + 1);
666 ADD_BLOCK (block_list, single_locale);
667
668
669 /* Search for the given string. This is a loop because we perhaps
670 got an ordered list of languages to consider for the translation. */
671 while (1)
672 {
673 /* Make CATEGORYVALUE point to the next element of the list. */
674 while (categoryvalue[0] != '\0' && categoryvalue[0] == ':')
675 ++categoryvalue;
676 if (categoryvalue[0] == '\0')
677 {
678 /* The whole contents of CATEGORYVALUE has been searched but
679 no valid entry has been found. We solve this situation
680 by implicitly appending a "C" entry, i.e. no translation
681 will take place. */
682 single_locale[0] = 'C';
683 single_locale[1] = '\0';
684 }
685 else
686 {
687 char *cp = single_locale;
688 while (categoryvalue[0] != '\0' && categoryvalue[0] != ':')
689 *cp++ = *categoryvalue++;
690 *cp = '\0';
691
692 /* When this is a SUID binary we must not allow accessing files
693 outside the dedicated directories. */
694 if (ENABLE_SECURE && IS_PATH_WITH_DIR (single_locale))
695 /* Ingore this entry. */
696 continue;
697 }
698
699 /* If the current locale value is C (or POSIX) we don't load a
700 domain. Return the MSGID. */
701 if (strcmp (single_locale, "C") == 0
702 || strcmp (single_locale, "POSIX") == 0)
703 break;
704
705 /* Find structure describing the message catalog matching the
706 DOMAINNAME and CATEGORY. */
707 domain = _nl_find_domain (dirname, single_locale, xdomainname, binding);
708
709 if (domain != NULL)
710 {
711#if defined IN_LIBGLOCALE
712 retval = _nl_find_msg (domain, binding, encoding, msgid1, &retlen);
713#else
714 retval = _nl_find_msg (domain, binding, msgid1, 1, &retlen);
715#endif
716
717 if (retval == NULL)
718 {
719 int cnt;
720
721 for (cnt = 0; domain->successor[cnt] != NULL; ++cnt)
722 {
723#if defined IN_LIBGLOCALE
724 retval = _nl_find_msg (domain->successor[cnt], binding,
725 encoding, msgid1, &retlen);
726#else
727 retval = _nl_find_msg (domain->successor[cnt], binding,
728 msgid1, 1, &retlen);
729#endif
730
731 /* Resource problems are not fatal, instead we return no
732 translation. */
733 if (__builtin_expect (retval == (char *) -1, 0))
734 goto return_untranslated;
735
736 if (retval != NULL)
737 {
738 domain = domain->successor[cnt];
739 break;
740 }
741 }
742 }
743
744 /* Returning -1 means that some resource problem exists
745 (likely memory) and that the strings could not be
746 converted. Return the original strings. */
747 if (__builtin_expect (retval == (char *) -1, 0))
748 break;
749
750 if (retval != NULL)
751 {
752 /* Found the translation of MSGID1 in domain DOMAIN:
753 starting at RETVAL, RETLEN bytes. */
754 free (xdirname);
755 FREE_BLOCKS (block_list);
756 if (foundp == NULL)
757 {
758 /* Create a new entry and add it to the search tree. */
759 size_t msgid_len;
760 size_t size;
761 struct known_translation_t *newp;
762
763 msgid_len = strlen (msgid1) + 1;
764 size = offsetof (struct known_translation_t, msgid)
765 + msgid_len + domainname_len + 1;
766#ifdef HAVE_PER_THREAD_LOCALE
767 size += strlen (localename) + 1;
768#endif
769 newp = (struct known_translation_t *) malloc (size);
770 if (newp != NULL)
771 {
772 char *new_domainname;
773#ifdef HAVE_PER_THREAD_LOCALE
774 char *new_localename;
775#endif
776
777 new_domainname =
778 (char *) mempcpy (newp->msgid.appended, msgid1,
779 msgid_len);
780 memcpy (new_domainname, domainname, domainname_len + 1);
781#ifdef HAVE_PER_THREAD_LOCALE
782 new_localename = new_domainname + domainname_len + 1;
783 strcpy (new_localename, localename);
784#endif
785 newp->domainname = new_domainname;
786 newp->category = category;
787#ifdef HAVE_PER_THREAD_LOCALE
788 newp->localename = new_localename;
789#endif
790#ifdef IN_LIBGLOCALE
791 newp->encoding = encoding;
792#endif
793 newp->counter = _nl_msg_cat_cntr;
794 newp->domain = domain;
795 newp->translation = retval;
796 newp->translation_length = retlen;
797
798 gl_rwlock_wrlock (tree_lock);
799
800 /* Insert the entry in the search tree. */
801 foundp = (struct known_translation_t **)
802 tsearch (newp, &root, transcmp);
803
804 gl_rwlock_unlock (tree_lock);
805
806 if (foundp == NULL
807 || __builtin_expect (*foundp != newp, 0))
808 /* The insert failed. */
809 free (newp);
810 }
811 }
812 else
813 {
814 /* We can update the existing entry. */
815 (*foundp)->counter = _nl_msg_cat_cntr;
816 (*foundp)->domain = domain;
817 (*foundp)->translation = retval;
818 (*foundp)->translation_length = retlen;
819 }
820
821 __set_errno (saved_errno);
822
823 /* Now deal with plural. */
824 if (plural)
825 retval = plural_lookup (domain, n, retval, retlen);
826
827 gl_rwlock_unlock (_nl_state_lock);
828#ifdef _LIBC
829 __libc_rwlock_unlock (__libc_setlocale_lock);
830#endif
831 return retval;
832 }
833 }
834 }
835
836 return_untranslated:
837 /* Return the untranslated MSGID. */
838 free (xdirname);
839 FREE_BLOCKS (block_list);
840 gl_rwlock_unlock (_nl_state_lock);
841#ifdef _LIBC
842 __libc_rwlock_unlock (__libc_setlocale_lock);
843#endif
844#ifndef _LIBC
845 if (!ENABLE_SECURE)
846 {
847 extern void _nl_log_untranslated (const char *logfilename,
848 const char *domainname,
849 const char *msgid1, const char *msgid2,
850 int plural);
851 const char *logfilename = getenv ("GETTEXT_LOG_UNTRANSLATED");
852
853 if (logfilename != NULL && logfilename[0] != '\0')
854 _nl_log_untranslated (logfilename, domainname, msgid1, msgid2, plural);
855 }
856#endif
857 __set_errno (saved_errno);
858 return (plural == 0
859 ? (char *) msgid1
860 /* Use the Germanic plural rule. */
861 : n == 1 ? (char *) msgid1 : (char *) msgid2);
862}
863
864
865/* Look up the translation of msgid within DOMAIN_FILE and DOMAINBINDING.
866 Return it if found. Return NULL if not found or in case of a conversion
867 failure (problem in the particular message catalog). Return (char *) -1
868 in case of a memory allocation failure during conversion (only if
869 ENCODING != NULL resp. CONVERT == true). */
870char *
871internal_function
872#ifdef IN_LIBGLOCALE
873_nl_find_msg (struct loaded_l10nfile *domain_file,
874 struct binding *domainbinding, const char *encoding,
875 const char *msgid,
876 size_t *lengthp)
877#else
878_nl_find_msg (struct loaded_l10nfile *domain_file,
879 struct binding *domainbinding,
880 const char *msgid, int convert,
881 size_t *lengthp)
882#endif
883{
884 struct loaded_domain *domain;
885 nls_uint32 nstrings;
886 size_t act;
887 char *result;
888 size_t resultlen;
889
890 if (domain_file->decided <= 0)
891 _nl_load_domain (domain_file, domainbinding);
892
893 if (domain_file->data == NULL)
894 return NULL;
895
896 domain = (struct loaded_domain *) domain_file->data;
897
898 nstrings = domain->nstrings;
899
900 /* Locate the MSGID and its translation. */
901 if (domain->hash_tab != NULL)
902 {
903 /* Use the hashing table. */
904 nls_uint32 len = strlen (msgid);
905 nls_uint32 hash_val = __hash_string (msgid);
906 nls_uint32 idx = hash_val % domain->hash_size;
907 nls_uint32 incr = 1 + (hash_val % (domain->hash_size - 2));
908
909 while (1)
910 {
911 nls_uint32 nstr =
912 W (domain->must_swap_hash_tab, domain->hash_tab[idx]);
913
914 if (nstr == 0)
915 /* Hash table entry is empty. */
916 return NULL;
917
918 nstr--;
919
920 /* Compare msgid with the original string at index nstr.
921 We compare the lengths with >=, not ==, because plural entries
922 are represented by strings with an embedded NUL. */
923 if (nstr < nstrings
924 ? W (domain->must_swap, domain->orig_tab[nstr].length) >= len
925 && (strcmp (msgid,
926 domain->data + W (domain->must_swap,
927 domain->orig_tab[nstr].offset))
928 == 0)
929 : domain->orig_sysdep_tab[nstr - nstrings].length > len
930 && (strcmp (msgid,
931 domain->orig_sysdep_tab[nstr - nstrings].pointer)
932 == 0))
933 {
934 act = nstr;
935 goto found;
936 }
937
938 if (idx >= domain->hash_size - incr)
939 idx -= domain->hash_size - incr;
940 else
941 idx += incr;
942 }
943 /* NOTREACHED */
944 }
945 else
946 {
947 /* Try the default method: binary search in the sorted array of
948 messages. */
949 size_t top, bottom;
950
951 bottom = 0;
952 top = nstrings;
953 while (bottom < top)
954 {
955 int cmp_val;
956
957 act = (bottom + top) / 2;
958 cmp_val = strcmp (msgid, (domain->data
959 + W (domain->must_swap,
960 domain->orig_tab[act].offset)));
961 if (cmp_val < 0)
962 top = act;
963 else if (cmp_val > 0)
964 bottom = act + 1;
965 else
966 goto found;
967 }
968 /* No translation was found. */
969 return NULL;
970 }
971
972 found:
973 /* The translation was found at index ACT. If we have to convert the
974 string to use a different character set, this is the time. */
975 if (act < nstrings)
976 {
977 result = (char *)
978 (domain->data + W (domain->must_swap, domain->trans_tab[act].offset));
979 resultlen = W (domain->must_swap, domain->trans_tab[act].length) + 1;
980 }
981 else
982 {
983 result = (char *) domain->trans_sysdep_tab[act - nstrings].pointer;
984 resultlen = domain->trans_sysdep_tab[act - nstrings].length;
985 }
986
987#if defined _LIBC || HAVE_ICONV
988# ifdef IN_LIBGLOCALE
989 if (encoding != NULL)
990# else
991 if (convert)
992# endif
993 {
994 /* We are supposed to do a conversion. */
995# ifndef IN_LIBGLOCALE
996 const char *encoding = get_output_charset (domainbinding);
997# endif
998 size_t nconversions;
999 struct converted_domain *convd;
1000 size_t i;
1001
1002 /* Protect against reallocation of the table. */
1003 gl_rwlock_rdlock (domain->conversions_lock);
1004
1005 /* Search whether a table with converted translations for this
1006 encoding has already been allocated. */
1007 nconversions = domain->nconversions;
1008 convd = NULL;
1009
1010 for (i = nconversions; i > 0; )
1011 {
1012 i--;
1013 if (strcmp (domain->conversions[i].encoding, encoding) == 0)
1014 {
1015 convd = &domain->conversions[i];
1016 break;
1017 }
1018 }
1019
1020 gl_rwlock_unlock (domain->conversions_lock);
1021
1022 if (convd == NULL)
1023 {
1024 /* We have to allocate a new conversions table. */
1025 gl_rwlock_wrlock (domain->conversions_lock);
1026 nconversions = domain->nconversions;
1027
1028 /* Maybe in the meantime somebody added the translation.
1029 Recheck. */
1030 for (i = nconversions; i > 0; )
1031 {
1032 i--;
1033 if (strcmp (domain->conversions[i].encoding, encoding) == 0)
1034 {
1035 convd = &domain->conversions[i];
1036 goto found_convd;
1037 }
1038 }
1039
1040 {
1041 /* Allocate a table for the converted translations for this
1042 encoding. */
1043 struct converted_domain *new_conversions =
1044 (struct converted_domain *)
1045 (domain->conversions != NULL
1046 ? realloc (domain->conversions,
1047 (nconversions + 1) * sizeof (struct converted_domain))
1048 : malloc ((nconversions + 1) * sizeof (struct converted_domain)));
1049
1050 if (__builtin_expect (new_conversions == NULL, 0))
1051 {
1052 /* Nothing we can do, no more memory. We cannot use the
1053 translation because it might be encoded incorrectly. */
1054 unlock_fail:
1055 gl_rwlock_unlock (domain->conversions_lock);
1056 return (char *) -1;
1057 }
1058
1059 domain->conversions = new_conversions;
1060
1061 /* Copy the 'encoding' string to permanent storage. */
1062 encoding = strdup (encoding);
1063 if (__builtin_expect (encoding == NULL, 0))
1064 /* Nothing we can do, no more memory. We cannot use the
1065 translation because it might be encoded incorrectly. */
1066 goto unlock_fail;
1067
1068 convd = &new_conversions[nconversions];
1069 convd->encoding = encoding;
1070
1071 /* Find out about the character set the file is encoded with.
1072 This can be found (in textual form) in the entry "". If this
1073 entry does not exist or if this does not contain the 'charset='
1074 information, we will assume the charset matches the one the
1075 current locale and we don't have to perform any conversion. */
1076# ifdef _LIBC
1077 convd->conv = (__gconv_t) -1;
1078# else
1079# if HAVE_ICONV
1080 convd->conv = (iconv_t) -1;
1081# endif
1082# endif
1083 {
1084 char *nullentry;
1085 size_t nullentrylen;
1086
1087 /* Get the header entry. This is a recursion, but it doesn't
1088 reallocate domain->conversions because we pass
1089 encoding = NULL or convert = 0, respectively. */
1090 nullentry =
1091# ifdef IN_LIBGLOCALE
1092 _nl_find_msg (domain_file, domainbinding, NULL, "",
1093 &nullentrylen);
1094# else
1095 _nl_find_msg (domain_file, domainbinding, "", 0, &nullentrylen);
1096# endif
1097
1098 /* Resource problems are fatal. If we continue onwards we will
1099 only attempt to calloc a new conv_tab and fail later. */
1100 if (__builtin_expect (nullentry == (char *) -1, 0))
1101 return (char *) -1;
1102
1103 if (nullentry != NULL)
1104 {
1105 const char *charsetstr;
1106
1107 charsetstr = strstr (nullentry, "charset=");
1108 if (charsetstr != NULL)
1109 {
1110 size_t len;
1111 char *charset;
1112 const char *outcharset;
1113
1114 charsetstr += strlen ("charset=");
1115 len = strcspn (charsetstr, " \t\n");
1116
1117 charset = (char *) alloca (len + 1);
1118# if defined _LIBC || HAVE_MEMPCPY
1119 *((char *) mempcpy (charset, charsetstr, len)) = '\0';
1120# else
1121 memcpy (charset, charsetstr, len);
1122 charset[len] = '\0';
1123# endif
1124
1125 outcharset = encoding;
1126
1127# ifdef _LIBC
1128 /* We always want to use transliteration. */
1129 outcharset = norm_add_slashes (outcharset, "TRANSLIT");
1130 charset = norm_add_slashes (charset, "");
1131 int r = __gconv_open (outcharset, charset, &convd->conv,
1132 GCONV_AVOID_NOCONV);
1133 if (__builtin_expect (r != __GCONV_OK, 0))
1134 {
1135 /* If the output encoding is the same there is
1136 nothing to do. Otherwise do not use the
1137 translation at all. */
1138 if (__builtin_expect (r != __GCONV_NULCONV, 1))
1139 {
1140 gl_rwlock_unlock (domain->conversions_lock);
1141 free ((char *) encoding);
1142 return NULL;
1143 }
1144
1145 convd->conv = (__gconv_t) -1;
1146 }
1147# else
1148# if HAVE_ICONV
1149 /* When using GNU libc >= 2.2 or GNU libiconv >= 1.5,
1150 we want to use transliteration. */
1151# if (((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2) || __GLIBC__ > 2) \
1152 && !defined __UCLIBC__) \
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 /* This lock primarily protects the memory management variables
1207 freemem, freemem_size. It also protects write accesses to
1208 convd->conv_tab. It's not worth using a separate lock (such
1209 as domain->conversions_lock) for this purpose, because when
1210 modifying convd->conv_tab, we also need to lock freemem,
1211 freemem_size for most of the time. */
1212 __libc_lock_define_initialized (static, lock)
1213
1214 if (__builtin_expect (convd->conv_tab == NULL, 0))
1215 {
1216 __libc_lock_lock (lock);
1217 if (convd->conv_tab == NULL)
1218 {
1219 convd->conv_tab =
1220 (char **) calloc (nstrings + domain->n_sysdep_strings,
1221 sizeof (char *));
1222 if (convd->conv_tab != NULL)
1223 goto not_translated_yet;
1224 /* Mark that we didn't succeed allocating a table. */
1225 convd->conv_tab = (char **) -1;
1226 }
1227 __libc_lock_unlock (lock);
1228 }
1229
1230 if (__builtin_expect (convd->conv_tab == (char **) -1, 0))
1231 /* Nothing we can do, no more memory. We cannot use the
1232 translation because it might be encoded incorrectly. */
1233 return (char *) -1;
1234
1235 if (convd->conv_tab[act] == NULL)
1236 {
1237 /* We haven't used this string so far, so it is not
1238 translated yet. Do this now. */
1239 /* We use a bit more efficient memory handling.
1240 We allocate always larger blocks which get used over
1241 time. This is faster than many small allocations. */
1242# define INITIAL_BLOCK_SIZE 4080
1243 static unsigned char *freemem;
1244 static size_t freemem_size;
1245
1246 const unsigned char *inbuf;
1247 unsigned char *outbuf;
1248 int malloc_count;
1249# ifndef _LIBC
1250 transmem_block_t *transmem_list;
1251# endif
1252
1253 __libc_lock_lock (lock);
1254 not_translated_yet:
1255
1256 inbuf = (const unsigned char *) result;
1257 outbuf = freemem + sizeof (size_t);
1258# ifndef _LIBC
1259 transmem_list = NULL;
1260# endif
1261
1262 malloc_count = 0;
1263 while (1)
1264 {
1265 transmem_block_t *newmem;
1266# ifdef _LIBC
1267 size_t non_reversible;
1268 int res;
1269
1270 if (freemem_size < sizeof (size_t))
1271 goto resize_freemem;
1272
1273 res = __gconv (convd->conv,
1274 &inbuf, inbuf + resultlen,
1275 &outbuf,
1276 outbuf + freemem_size - sizeof (size_t),
1277 &non_reversible);
1278
1279 if (res == __GCONV_OK || res == __GCONV_EMPTY_INPUT)
1280 break;
1281
1282 if (res != __GCONV_FULL_OUTPUT)
1283 {
1284 /* We should not use the translation at all, it
1285 is incorrectly encoded. */
1286 __libc_lock_unlock (lock);
1287 return NULL;
1288 }
1289
1290 inbuf = (const unsigned char *) result;
1291# else
1292# if HAVE_ICONV
1293 const char *inptr = (const char *) inbuf;
1294 size_t inleft = resultlen;
1295 char *outptr = (char *) outbuf;
1296 size_t outleft;
1297
1298 if (freemem_size < sizeof (size_t))
1299 goto resize_freemem;
1300
1301 outleft = freemem_size - sizeof (size_t);
1302 if (iconv (convd->conv,
1303 (ICONV_CONST char **) &inptr, &inleft,
1304 &outptr, &outleft)
1305 != (size_t) (-1))
1306 {
1307 outbuf = (unsigned char *) outptr;
1308 break;
1309 }
1310 if (errno != E2BIG)
1311 {
1312 __libc_lock_unlock (lock);
1313 return NULL;
1314 }
1315# endif
1316# endif
1317
1318 resize_freemem:
1319 /* We must allocate a new buffer or resize the old one. */
1320 if (malloc_count > 0)
1321 {
1322 ++malloc_count;
1323 freemem_size = malloc_count * INITIAL_BLOCK_SIZE;
1324 newmem = (transmem_block_t *) realloc (transmem_list,
1325 freemem_size);
1326# ifdef _LIBC
1327 if (newmem != NULL)
1328 transmem_list = newmem;
1329 else
1330 {
1331 struct transmem_list *old = transmem_list;
1332
1333 transmem_list = transmem_list->next;
1334 free (old);
1335 }
1336# endif
1337 }
1338 else
1339 {
1340 malloc_count = 1;
1341 freemem_size = INITIAL_BLOCK_SIZE;
1342 newmem = (transmem_block_t *) malloc (freemem_size);
1343# ifdef _LIBC
1344 if (newmem != NULL)
1345 {
1346 /* Add the block to the list of blocks we have to free
1347 at some point. */
1348 newmem->next = transmem_list;
1349 transmem_list = newmem;
1350 }
1351 /* Fall through and return -1. */
1352# endif
1353 }
1354 if (__builtin_expect (newmem == NULL, 0))
1355 {
1356 freemem = NULL;
1357 freemem_size = 0;
1358 __libc_lock_unlock (lock);
1359 return (char *) -1;
1360 }
1361
1362# ifdef _LIBC
1363 freemem = (unsigned char *) newmem->data;
1364 freemem_size -= offsetof (struct transmem_list, data);
1365# else
1366 transmem_list = newmem;
1367 freemem = newmem;
1368# endif
1369
1370 outbuf = freemem + sizeof (size_t);
1371 }
1372
1373 /* We have now in our buffer a converted string. Put this
1374 into the table of conversions. */
1375 *(size_t *) freemem = outbuf - freemem - sizeof (size_t);
1376 convd->conv_tab[act] = (char *) freemem;
1377 /* Shrink freemem, but keep it aligned. */
1378 freemem_size -= outbuf - freemem;
1379 freemem = outbuf;
1380 freemem += freemem_size & (alignof (size_t) - 1);
1381 freemem_size = freemem_size & ~ (alignof (size_t) - 1);
1382
1383 __libc_lock_unlock (lock);
1384 }
1385
1386 /* Now convd->conv_tab[act] contains the translation of all
1387 the plural variants. */
1388 result = convd->conv_tab[act] + sizeof (size_t);
1389 resultlen = *(size_t *) convd->conv_tab[act];
1390 }
1391 }
1392
1393 /* The result string is converted. */
1394
1395#endif /* _LIBC || HAVE_ICONV */
1396
1397 *lengthp = resultlen;
1398 return result;
1399}
1400
1401
1402/* Look up a plural variant. */
1403static char *
1404internal_function
1405plural_lookup (struct loaded_l10nfile *domain, unsigned long int n,
1406 const char *translation, size_t translation_len)
1407{
1408 struct loaded_domain *domaindata = (struct loaded_domain *) domain->data;
1409 unsigned long int index;
1410 const char *p;
1411
1412 index = plural_eval (domaindata->plural, n);
1413 if (index >= domaindata->nplurals)
1414 /* This should never happen. It means the plural expression and the
1415 given maximum value do not match. */
1416 index = 0;
1417
1418 /* Skip INDEX strings at TRANSLATION. */
1419 p = translation;
1420 while (index-- > 0)
1421 {
1422#ifdef _LIBC
1423 p = __rawmemchr (p, '\0');
1424#else
1425 p = strchr (p, '\0');
1426#endif
1427 /* And skip over the NUL byte. */
1428 p++;
1429
1430 if (p >= translation + translation_len)
1431 /* This should never happen. It means the plural expression
1432 evaluated to a value larger than the number of variants
1433 available for MSGID1. */
1434 return (char *) translation;
1435 }
1436 return (char *) p;
1437}
1438
1439#ifndef _LIBC
1440/* Return string representation of locale CATEGORY. */
1441static const char *
1442internal_function
1443category_to_name (int category)
1444{
1445 const char *retval;
1446
1447 switch (category)
1448 {
1449#ifdef LC_COLLATE
1450 case LC_COLLATE:
1451 retval = "LC_COLLATE";
1452 break;
1453#endif
1454#ifdef LC_CTYPE
1455 case LC_CTYPE:
1456 retval = "LC_CTYPE";
1457 break;
1458#endif
1459#ifdef LC_MONETARY
1460 case LC_MONETARY:
1461 retval = "LC_MONETARY";
1462 break;
1463#endif
1464#ifdef LC_NUMERIC
1465 case LC_NUMERIC:
1466 retval = "LC_NUMERIC";
1467 break;
1468#endif
1469#ifdef LC_TIME
1470 case LC_TIME:
1471 retval = "LC_TIME";
1472 break;
1473#endif
1474#ifdef LC_MESSAGES
1475 case LC_MESSAGES:
1476 retval = "LC_MESSAGES";
1477 break;
1478#endif
1479#ifdef LC_RESPONSE
1480 case LC_RESPONSE:
1481 retval = "LC_RESPONSE";
1482 break;
1483#endif
1484#ifdef LC_ALL
1485 case LC_ALL:
1486 /* This might not make sense but is perhaps better than any other
1487 value. */
1488 retval = "LC_ALL";
1489 break;
1490#endif
1491 default:
1492 /* If you have a better idea for a default value let me know. */
1493 retval = "LC_XXX";
1494 }
1495
1496 return retval;
1497}
1498#endif
1499
1500/* Guess value of current locale from value of the environment variables
1501 or system-dependent defaults. */
1502static const char *
1503internal_function
1504#ifdef IN_LIBGLOCALE
1505guess_category_value (int category, const char *categoryname,
1506 const char *locale)
1507
1508#else
1509guess_category_value (int category, const char *categoryname)
1510#endif
1511{
1512 const char *language;
1513#ifndef IN_LIBGLOCALE
1514 const char *locale;
1515# ifndef _LIBC
1516 const char *language_default;
1517 int locale_defaulted;
1518# endif
1519#endif
1520
1521 /* We use the settings in the following order:
1522 1. The value of the environment variable 'LANGUAGE'. This is a GNU
1523 extension. Its value can be a colon-separated list of locale names.
1524 2. The value of the environment variable 'LC_ALL', 'LC_xxx', or 'LANG'.
1525 More precisely, the first among these that is set to a non-empty value.
1526 This is how POSIX specifies it. The value is a single locale name.
1527 3. A system-dependent preference list of languages. Its value can be a
1528 colon-separated list of locale names.
1529 4. A system-dependent default locale name.
1530 This way:
1531 - System-dependent settings can be overridden by environment variables.
1532 - If the system provides both a list of languages and a default locale,
1533 the former is used. */
1534
1535#ifndef IN_LIBGLOCALE
1536 /* Fetch the locale name, through the POSIX method of looking to `LC_ALL',
1537 `LC_xxx', and `LANG'. On some systems this can be done by the
1538 `setlocale' function itself. */
1539# ifdef _LIBC
1540 locale = __current_locale_name (category);
1541# else
1542 locale_defaulted = 0;
1543# if HAVE_USELOCALE
1544 locale = _nl_locale_name_thread_unsafe (category, categoryname);
1545 if (locale == NULL)
1546# endif
1547 {
1548 locale = _nl_locale_name_posix (category, categoryname);
1549 if (locale == NULL)
1550 {
1551 locale = _nl_locale_name_default ();
1552 locale_defaulted = 1;
1553 }
1554 }
1555# endif
1556#endif
1557
1558 /* Ignore LANGUAGE and its system-dependent analogon if the locale is set
1559 to "C" because
1560 1. "C" locale usually uses the ASCII encoding, and most international
1561 messages use non-ASCII characters. These characters get displayed
1562 as question marks (if using glibc's iconv()) or as invalid 8-bit
1563 characters (because other iconv()s refuse to convert most non-ASCII
1564 characters to ASCII). In any case, the output is ugly.
1565 2. The precise output of some programs in the "C" locale is specified
1566 by POSIX and should not depend on environment variables like
1567 "LANGUAGE" or system-dependent information. We allow such programs
1568 to use gettext(). */
1569 if (strcmp (locale, "C") == 0)
1570 return locale;
1571
1572 /* The highest priority value is the value of the 'LANGUAGE' environment
1573 variable. */
1574 language = getenv ("LANGUAGE");
1575 if (language != NULL && language[0] != '\0')
1576 return language;
1577#if !defined IN_LIBGLOCALE && !defined _LIBC
1578 /* The next priority value is the locale name, if not defaulted. */
1579 if (locale_defaulted)
1580 {
1581 /* The next priority value is the default language preferences list. */
1582 language_default = _nl_language_preferences_default ();
1583 if (language_default != NULL)
1584 return language_default;
1585 }
1586 /* The least priority value is the locale name, if defaulted. */
1587#endif
1588 return locale;
1589}
1590
1591#if (defined _LIBC || HAVE_ICONV) && !defined IN_LIBGLOCALE
1592/* Returns the output charset. */
1593static const char *
1594internal_function
1595get_output_charset (struct binding *domainbinding)
1596{
1597 /* The output charset should normally be determined by the locale. But
1598 sometimes the locale is not used or not correctly set up, so we provide
1599 a possibility for the user to override this: the OUTPUT_CHARSET
1600 environment variable. Moreover, the value specified through
1601 bind_textdomain_codeset overrides both. */
1602 if (domainbinding != NULL && domainbinding->codeset != NULL)
1603 return domainbinding->codeset;
1604 else
1605 {
1606 /* For speed reasons, we look at the value of OUTPUT_CHARSET only
1607 once. This is a user variable that is not supposed to change
1608 during a program run. */
1609 static char *output_charset_cache;
1610 static int output_charset_cached;
1611
1612 if (!output_charset_cached)
1613 {
1614 const char *value = getenv ("OUTPUT_CHARSET");
1615
1616 if (value != NULL && value[0] != '\0')
1617 {
1618 size_t len = strlen (value) + 1;
1619 char *value_copy = (char *) malloc (len);
1620
1621 if (value_copy != NULL)
1622 memcpy (value_copy, value, len);
1623 output_charset_cache = value_copy;
1624 }
1625 output_charset_cached = 1;
1626 }
1627
1628 if (output_charset_cache != NULL)
1629 return output_charset_cache;
1630 else
1631 {
1632# ifdef _LIBC
1633 return _NL_CURRENT (LC_CTYPE, CODESET);
1634# else
1635# if HAVE_ICONV
1636 return locale_charset ();
1637# endif
1638# endif
1639 }
1640 }
1641}
1642#endif
1643
1644/* @@ begin of epilog @@ */
1645
1646/* We don't want libintl.a to depend on any other library. So we
1647 avoid the non-standard function stpcpy. In GNU C Library this
1648 function is available, though. Also allow the symbol HAVE_STPCPY
1649 to be defined. */
1650#if !_LIBC && !HAVE_STPCPY
1651static char *
1652stpcpy (char *dest, const char *src)
1653{
1654 while ((*dest++ = *src++) != '\0')
1655 /* Do nothing. */ ;
1656 return dest - 1;
1657}
1658#endif
1659
1660#if !_LIBC && !HAVE_MEMPCPY
1661static void *
1662mempcpy (void *dest, const void *src, size_t n)
1663{
1664 return (void *) ((char *) memcpy (dest, src, n) + n);
1665}
1666#endif
1667
1668#if !_LIBC && !HAVE_TSEARCH
1669# include "tsearch.c"
1670#endif
1671
1672
1673#ifdef _LIBC
1674/* If we want to free all resources we have to do some work at
1675 program's end. */
1676libc_freeres_fn (free_mem)
1677{
1678 void *old;
1679
1680 while (_nl_domain_bindings != NULL)
1681 {
1682 struct binding *oldp = _nl_domain_bindings;
1683 _nl_domain_bindings = _nl_domain_bindings->next;
1684 if (oldp->dirname != _nl_default_dirname)
1685 /* Yes, this is a pointer comparison. */
1686 free (oldp->dirname);
1687 free (oldp->codeset);
1688 free (oldp);
1689 }
1690
1691 if (_nl_current_default_domain != _nl_default_default_domain)
1692 /* Yes, again a pointer comparison. */
1693 free ((char *) _nl_current_default_domain);
1694
1695 /* Remove the search tree with the known translations. */
1696 __tdestroy (root, free);
1697 root = NULL;
1698
1699 while (transmem_list != NULL)
1700 {
1701 old = transmem_list;
1702 transmem_list = transmem_list->next;
1703 free (old);
1704 }
1705}
1706#endif
1707