1
/* Implementation of the internal dcigettext function.
2
Copyright (C) 1995-1999, 2000-2007 Free Software Foundation, Inc.
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)
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.
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,
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. */
23
# define _GNU_SOURCE 1
30
/* NL_LOCALE_NAME does not work in glibc-2.4. Ignore it. */
31
#undef HAVE_NL_LOCALE_NAME
33
#include <sys/types.h>
36
# define alloca __builtin_alloca
37
# define HAVE_ALLOCA 1
41
# define alloca _alloca
43
# if defined HAVE_ALLOCA_H || defined _LIBC
62
# define __set_errno(val) errno = (val)
69
#if defined HAVE_UNISTD_H || defined _LIBC
76
/* Guess whether integer division by zero raises signal SIGFPE.
77
Set to 1 only if you know for sure. In case of doubt, set to 0. */
78
# if defined __alpha__ || defined __arm__ || defined __i386__ \
79
|| defined __m68k__ || defined __s390__
80
# define INTDIV0_RAISES_SIGFPE 1
82
# define INTDIV0_RAISES_SIGFPE 0
85
#if !INTDIV0_RAISES_SIGFPE
89
#if defined HAVE_SYS_PARAM_H || defined _LIBC
90
# include <sys/param.h>
94
# if HAVE_NL_LOCALE_NAME
95
# include <langinfo.h>
97
# include "localcharset.h"
100
#include "gettextP.h"
101
#include "plural-exp.h"
103
# include <libintl.h>
105
# ifdef IN_LIBGLOCALE
106
# include <libintl.h>
108
# include "libgnuintl.h"
110
#include "hash-string.h"
112
/* Handle multi-threaded applications. */
114
# include <bits/libc-lock.h>
115
# define gl_rwlock_define_initialized __libc_rwlock_define_initialized
116
# define gl_rwlock_rdlock __libc_rwlock_rdlock
117
# define gl_rwlock_wrlock __libc_rwlock_wrlock
118
# define gl_rwlock_unlock __libc_rwlock_unlock
123
/* Alignment of types. */
124
#if defined __GNUC__ && __GNUC__ >= 2
125
# define alignof(TYPE) __alignof__ (TYPE)
127
# define alignof(TYPE) \
128
((int) &((struct { char dummy1; TYPE dummy2; } *) 0)->dummy2)
131
/* Some compilers, like SunOS4 cc, don't have offsetof in <stddef.h>. */
133
# define offsetof(type,ident) ((size_t)&(((type*)0)->ident))
136
/* @@ end of prolog @@ */
139
/* Rename the non ANSI C functions. This is required by the standard
140
because some ANSI C functions will require linking with this object
141
file and the name space must not be polluted. */
142
# define getcwd __getcwd
144
# define stpcpy __stpcpy
146
# define tfind __tfind
148
# if !defined HAVE_GETCWD
150
# define getcwd(buf, max) getwd (buf)
153
# define getcwd(buf, max) (getcwd) (buf, max, 0)
159
static char *stpcpy (char *dest, const char *src);
161
# ifndef HAVE_MEMPCPY
162
static void *mempcpy (void *dest, const void *src, size_t n);
166
/* Use a replacement if the system does not provide the `tsearch' function
168
#if HAVE_TSEARCH || defined _LIBC
171
# define tsearch libintl_tsearch
172
# define tfind libintl_tfind
173
# define tdelete libintl_tdelete
174
# define twalk libintl_twalk
175
# include "tsearch.h"
179
# define tsearch __tsearch
182
/* Amount to increase buffer size by in each try. */
185
/* The following is from pathmax.h. */
186
/* Non-POSIX BSD systems might have gcc's limits.h, which doesn't define
187
PATH_MAX but might cause redefinition warnings when sys/param.h is
188
later included (as on MORE/BSD 4.3). */
189
#if defined _POSIX_VERSION || (defined HAVE_LIMITS_H && !defined __GNUC__)
193
#ifndef _POSIX_PATH_MAX
194
# define _POSIX_PATH_MAX 255
197
#if !defined PATH_MAX && defined _PC_PATH_MAX
198
# define PATH_MAX (pathconf ("/", _PC_PATH_MAX) < 1 ? 1024 : pathconf ("/", _PC_PATH_MAX))
201
/* Don't include sys/param.h if it already has been. */
202
#if defined HAVE_SYS_PARAM_H && !defined PATH_MAX && !defined MAXPATHLEN
203
# include <sys/param.h>
206
#if !defined PATH_MAX && defined MAXPATHLEN
207
# define PATH_MAX MAXPATHLEN
211
# define PATH_MAX _POSIX_PATH_MAX
215
ISSLASH(C) tests whether C is a directory separator character.
216
IS_ABSOLUTE_PATH(P) tests whether P is an absolute path. If it is not,
217
it may be concatenated to a directory pathname.
218
IS_PATH_WITH_DIR(P) tests whether P contains a directory specification.
220
#if defined _WIN32 || defined __WIN32__ || defined __CYGWIN__ || defined __EMX__ || defined __DJGPP__
221
/* Win32, Cygwin, OS/2, DOS */
222
# define ISSLASH(C) ((C) == '/' || (C) == '\\')
223
# define HAS_DEVICE(P) \
224
((((P)[0] >= 'A' && (P)[0] <= 'Z') || ((P)[0] >= 'a' && (P)[0] <= 'z')) \
226
# define IS_ABSOLUTE_PATH(P) (ISSLASH ((P)[0]) || HAS_DEVICE (P))
227
# define IS_PATH_WITH_DIR(P) \
228
(strchr (P, '/') != NULL || strchr (P, '\\') != NULL || HAS_DEVICE (P))
231
# define ISSLASH(C) ((C) == '/')
232
# define IS_ABSOLUTE_PATH(P) ISSLASH ((P)[0])
233
# define IS_PATH_WITH_DIR(P) (strchr (P, '/') != NULL)
236
/* Whether to support different locales in different threads. */
237
#if defined _LIBC || HAVE_NL_LOCALE_NAME || (HAVE_STRUCT___LOCALE_STRUCT___NAMES && defined USE_IN_GETTEXT_TESTS) || defined IN_LIBGLOCALE
238
# define HAVE_PER_THREAD_LOCALE
241
/* This is the type used for the search tree where known translations
243
struct known_translation_t
245
/* Domain in which to search. */
246
const char *domainname;
251
#ifdef HAVE_PER_THREAD_LOCALE
252
/* Name of the relevant locale category, or "" for the global locale. */
253
const char *localename;
257
/* The character encoding. */
258
const char *encoding;
261
/* State of the catalog counter at the point the string was found. */
264
/* Catalog where the string was found. */
265
struct loaded_l10nfile *domain;
267
/* And finally the translation. */
268
const char *translation;
269
size_t translation_length;
271
/* Pointer to the string in question. */
275
gl_rwlock_define_initialized (static, tree_lock)
277
/* Root of the search tree with known translations. */
280
/* Function to compare two entries in the table of known translations. */
282
transcmp (const void *p1, const void *p2)
284
const struct known_translation_t *s1;
285
const struct known_translation_t *s2;
288
s1 = (const struct known_translation_t *) p1;
289
s2 = (const struct known_translation_t *) p2;
291
result = strcmp (s1->msgid, s2->msgid);
294
result = strcmp (s1->domainname, s2->domainname);
297
#ifdef HAVE_PER_THREAD_LOCALE
298
result = strcmp (s1->localename, s2->localename);
303
result = strcmp (s1->encoding, s2->encoding);
306
/* We compare the category last (though this is the cheapest
307
operation) since it is hopefully always the same (namely
309
result = s1->category - s2->category;
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";
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;
327
/* Contains the default location of the message catalogs. */
329
extern const char _nl_default_dirname[];
332
extern const char _nl_default_dirname[];
333
libc_hidden_proto (_nl_default_dirname)
335
const char _nl_default_dirname[] = LOCALEDIR;
337
libc_hidden_data_def (_nl_default_dirname)
341
#ifndef IN_LIBGLOCALE
342
/* List with bindings of specific domains created by bindtextdomain()
344
struct binding *_nl_domain_bindings;
347
/* Prototypes for local functions. */
348
static char *plural_lookup (struct loaded_l10nfile *domain,
350
const char *translation, size_t translation_len)
354
static const char *guess_category_value (int category,
355
const char *categoryname,
356
const char *localename)
359
static const char *guess_category_value (int category,
360
const char *categoryname)
365
# include "../locale/localeinfo.h"
366
# define category_to_name(category) \
367
_nl_category_names.str + _nl_category_name_idxs[category]
369
static const char *category_to_name (int category) internal_function;
371
#if (defined _LIBC || HAVE_ICONV) && !defined IN_LIBGLOCALE
372
static const char *get_output_charset (struct binding *domainbinding)
377
/* For those loosing systems which don't have `alloca' we have to add
378
some additional code emulating it. */
380
/* Nothing has to be done. */
381
# define freea(p) /* nothing */
382
# define ADD_BLOCK(list, address) /* nothing */
383
# define FREE_BLOCKS(list) /* nothing */
388
struct block_list *next;
390
# define ADD_BLOCK(list, addr) \
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 \
395
if (newp != NULL) { \
396
newp->address = (addr); \
397
newp->next = (list); \
401
# define FREE_BLOCKS(list) \
403
while (list != NULL) { \
404
struct block_list *old = list; \
406
free (old->address); \
411
# define alloca(size) (malloc (size))
412
# define freea(p) free (p)
413
#endif /* have alloca */
417
/* List of blocks allocated for translations. */
418
typedef struct transmem_list
420
struct transmem_list *next;
423
static struct transmem_list *transmem_list;
425
typedef unsigned char transmem_block_t;
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. */
434
# define DCIGETTEXT __dcigettext
436
# define DCIGETTEXT libintl_dcigettext
439
/* Lock variable to protect the global data in the gettext implementation. */
440
gl_rwlock_define_initialized (, _nl_state_lock attribute_hidden)
442
/* Checking whether the binaries runs SUID must be done and glibc provides
443
easier methods therefore we make a difference here. */
445
# define ENABLE_SECURE __libc_enable_secure
446
# define DETERMINE_SECURE
454
# ifndef HAVE_GETEUID
455
# define geteuid() getuid()
457
# ifndef HAVE_GETEGID
458
# define getegid() getgid()
460
static int enable_secure;
461
# define ENABLE_SECURE (enable_secure == 1)
462
# define DETERMINE_SECURE \
463
if (enable_secure == 0) \
465
if (getuid () != geteuid () || getgid () != getegid ()) \
468
enable_secure = -1; \
472
/* Get the function to evaluate the plural expression. */
473
#include "eval-plural.h"
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. */
480
gl_dcigettext (const char *domainname,
481
const char *msgid1, const char *msgid2,
482
int plural, unsigned long int n,
484
const char *localename, const char *encoding)
487
DCIGETTEXT (const char *domainname, const char *msgid1, const char *msgid2,
488
int plural, unsigned long int n, int category)
492
struct block_list *block_list = NULL;
494
struct loaded_l10nfile *domain;
495
struct binding *binding;
496
const char *categoryname;
497
const char *categoryvalue;
504
struct known_translation_t *search;
505
struct known_translation_t **foundp = NULL;
507
#if defined HAVE_PER_THREAD_LOCALE && !defined IN_LIBGLOCALE
508
const char *localename;
510
size_t domainname_len;
512
/* If no real MSGID is given return NULL. */
517
if (category < 0 || category >= __LC_LAST || category == LC_ALL)
521
/* Use the Germanic plural rule. */
522
: n == 1 ? (char *) msgid1 : (char *) msgid2);
525
/* Preserve the `errno' value. */
528
gl_rwlock_rdlock (_nl_state_lock);
530
/* If DOMAINNAME is NULL, we are interested in the default domain. If
531
CATEGORY is not LC_MESSAGES this might not make much sense but the
532
definition left this undefined. */
533
if (domainname == NULL)
534
domainname = _nl_current_default_domain;
536
/* OS/2 specific: backward compatibility with older libintl versions */
537
#ifdef LC_MESSAGES_COMPAT
538
if (category == LC_MESSAGES_COMPAT)
539
category = LC_MESSAGES;
542
msgid_len = strlen (msgid1) + 1;
544
/* Try to find the translation among those which we found at
546
search = (struct known_translation_t *)
547
alloca (offsetof (struct known_translation_t, msgid) + msgid_len);
548
memcpy (search->msgid, msgid1, msgid_len);
549
search->domainname = domainname;
550
search->category = category;
551
#ifdef HAVE_PER_THREAD_LOCALE
552
# ifndef IN_LIBGLOCALE
554
localename = __current_locale_name (category);
556
# if HAVE_NL_LOCALE_NAME
557
/* NL_LOCALE_NAME is public glibc API introduced in glibc-2.4. */
558
localename = nl_langinfo (NL_LOCALE_NAME (category));
560
# if HAVE_STRUCT___LOCALE_STRUCT___NAMES && defined USE_IN_GETTEXT_TESTS
561
/* The __names field is not public glibc API and must therefore not be used
562
in code that is installed in public locations. */
564
locale_t thread_locale = uselocale (NULL);
565
if (thread_locale != LC_GLOBAL_LOCALE)
566
localename = thread_locale->__names[category];
574
search->localename = localename;
575
# ifdef IN_LIBGLOCALE
576
search->encoding = encoding;
579
/* Since tfind/tsearch manage a balanced tree, concurrent tfind and
580
tsearch calls can be fatal. */
581
gl_rwlock_rdlock (tree_lock);
583
foundp = (struct known_translation_t **) tfind (search, &root, transcmp);
585
gl_rwlock_unlock (tree_lock);
588
if (foundp != NULL && (*foundp)->counter == _nl_msg_cat_cntr)
590
/* Now deal with plural. */
592
retval = plural_lookup ((*foundp)->domain, n, (*foundp)->translation,
593
(*foundp)->translation_length);
595
retval = (char *) (*foundp)->translation;
597
gl_rwlock_unlock (_nl_state_lock);
598
__set_errno (saved_errno);
603
/* See whether this is a SUID binary or not. */
606
/* First find matching binding. */
608
/* We can use a trivial binding, since _nl_find_msg will ignore it anyway,
609
and _nl_load_domain and _nl_find_domain just pass it through. */
611
dirname = bindtextdomain (domainname, NULL);
613
for (binding = _nl_domain_bindings; binding != NULL; binding = binding->next)
615
int compare = strcmp (domainname, binding->domainname);
621
/* It is not in the list. */
628
dirname = _nl_default_dirname;
631
dirname = binding->dirname;
633
if (!IS_ABSOLUTE_PATH (dirname))
635
/* We have a relative path. Make it absolute now. */
636
size_t dirname_len = strlen (dirname) + 1;
638
char *resolved_dirname;
641
path_max = (unsigned int) PATH_MAX;
642
path_max += 2; /* The getcwd docs say to do this. */
646
resolved_dirname = (char *) alloca (path_max + dirname_len);
647
ADD_BLOCK (block_list, tmp_dirname);
650
ret = getcwd (resolved_dirname, path_max);
651
if (ret != NULL || errno != ERANGE)
654
path_max += path_max / 2;
655
path_max += PATH_INCR;
659
/* We cannot get the current working directory. Don't signal an
660
error but simply return the default string. */
661
goto return_untranslated;
663
stpcpy (stpcpy (strchr (resolved_dirname, '\0'), "/"), dirname);
664
dirname = resolved_dirname;
666
#ifndef IN_LIBGLOCALE
670
/* Now determine the symbolic name of CATEGORY and its value. */
671
categoryname = category_to_name (category);
673
categoryvalue = guess_category_value (category, categoryname, localename);
675
categoryvalue = guess_category_value (category, categoryname);
678
domainname_len = strlen (domainname);
679
xdomainname = (char *) alloca (strlen (categoryname)
680
+ domainname_len + 5);
681
ADD_BLOCK (block_list, xdomainname);
683
stpcpy ((char *) mempcpy (stpcpy (stpcpy (xdomainname, categoryname), "/"),
684
domainname, domainname_len),
687
/* Creating working area. */
688
single_locale = (char *) alloca (strlen (categoryvalue) + 1);
689
ADD_BLOCK (block_list, single_locale);
692
/* Search for the given string. This is a loop because we perhaps
693
got an ordered list of languages to consider for the translation. */
696
/* Make CATEGORYVALUE point to the next element of the list. */
697
while (categoryvalue[0] != '\0' && categoryvalue[0] == ':')
699
if (categoryvalue[0] == '\0')
701
/* The whole contents of CATEGORYVALUE has been searched but
702
no valid entry has been found. We solve this situation
703
by implicitly appending a "C" entry, i.e. no translation
705
single_locale[0] = 'C';
706
single_locale[1] = '\0';
710
char *cp = single_locale;
711
while (categoryvalue[0] != '\0' && categoryvalue[0] != ':')
712
*cp++ = *categoryvalue++;
715
/* When this is a SUID binary we must not allow accessing files
716
outside the dedicated directories. */
717
if (ENABLE_SECURE && IS_PATH_WITH_DIR (single_locale))
718
/* Ingore this entry. */
722
/* If the current locale value is C (or POSIX) we don't load a
723
domain. Return the MSGID. */
724
if (strcmp (single_locale, "C") == 0
725
|| strcmp (single_locale, "POSIX") == 0)
728
/* Find structure describing the message catalog matching the
729
DOMAINNAME and CATEGORY. */
730
domain = _nl_find_domain (dirname, single_locale, xdomainname, binding);
734
#if defined IN_LIBGLOCALE
735
retval = _nl_find_msg (domain, binding, encoding, msgid1, &retlen);
737
retval = _nl_find_msg (domain, binding, msgid1, 1, &retlen);
744
for (cnt = 0; domain->successor[cnt] != NULL; ++cnt)
746
#if defined IN_LIBGLOCALE
747
retval = _nl_find_msg (domain->successor[cnt], binding,
748
encoding, msgid1, &retlen);
750
retval = _nl_find_msg (domain->successor[cnt], binding,
756
domain = domain->successor[cnt];
762
/* Returning -1 means that some resource problem exists
763
(likely memory) and that the strings could not be
764
converted. Return the original strings. */
765
if (__builtin_expect (retval == (char *) -1, 0))
770
/* Found the translation of MSGID1 in domain DOMAIN:
771
starting at RETVAL, RETLEN bytes. */
772
FREE_BLOCKS (block_list);
775
/* Create a new entry and add it to the search tree. */
777
struct known_translation_t *newp;
779
size = offsetof (struct known_translation_t, msgid)
780
+ msgid_len + domainname_len + 1;
781
#ifdef HAVE_PER_THREAD_LOCALE
782
size += strlen (localename) + 1;
784
newp = (struct known_translation_t *) malloc (size);
787
char *new_domainname;
788
#ifdef HAVE_PER_THREAD_LOCALE
789
char *new_localename;
793
(char *) mempcpy (newp->msgid, msgid1, msgid_len);
794
memcpy (new_domainname, domainname, domainname_len + 1);
795
#ifdef HAVE_PER_THREAD_LOCALE
796
new_localename = new_domainname + domainname_len + 1;
797
strcpy (new_localename, localename);
799
newp->domainname = new_domainname;
800
newp->category = category;
801
#ifdef HAVE_PER_THREAD_LOCALE
802
newp->localename = new_localename;
805
newp->encoding = encoding;
807
newp->counter = _nl_msg_cat_cntr;
808
newp->domain = domain;
809
newp->translation = retval;
810
newp->translation_length = retlen;
812
gl_rwlock_wrlock (tree_lock);
814
/* Insert the entry in the search tree. */
815
foundp = (struct known_translation_t **)
816
tsearch (newp, &root, transcmp);
818
gl_rwlock_unlock (tree_lock);
821
|| __builtin_expect (*foundp != newp, 0))
822
/* The insert failed. */
828
/* We can update the existing entry. */
829
(*foundp)->counter = _nl_msg_cat_cntr;
830
(*foundp)->domain = domain;
831
(*foundp)->translation = retval;
832
(*foundp)->translation_length = retlen;
835
__set_errno (saved_errno);
837
/* Now deal with plural. */
839
retval = plural_lookup (domain, n, retval, retlen);
841
gl_rwlock_unlock (_nl_state_lock);
848
/* Return the untranslated MSGID. */
849
FREE_BLOCKS (block_list);
850
gl_rwlock_unlock (_nl_state_lock);
854
extern void _nl_log_untranslated (const char *logfilename,
855
const char *domainname,
856
const char *msgid1, const char *msgid2,
858
const char *logfilename = getenv ("GETTEXT_LOG_UNTRANSLATED");
860
if (logfilename != NULL && logfilename[0] != '\0')
861
_nl_log_untranslated (logfilename, domainname, msgid1, msgid2, plural);
864
__set_errno (saved_errno);
867
/* Use the Germanic plural rule. */
868
: n == 1 ? (char *) msgid1 : (char *) msgid2);
872
/* Look up the translation of msgid within DOMAIN_FILE and DOMAINBINDING.
873
Return it if found. Return NULL if not found or in case of a conversion
874
failure (problem in the particular message catalog). Return (char *) -1
875
in case of a memory allocation failure during conversion (only if
876
ENCODING != NULL resp. CONVERT == true). */
880
_nl_find_msg (struct loaded_l10nfile *domain_file,
881
struct binding *domainbinding, const char *encoding,
885
_nl_find_msg (struct loaded_l10nfile *domain_file,
886
struct binding *domainbinding,
887
const char *msgid, int convert,
891
struct loaded_domain *domain;
897
if (domain_file->decided <= 0)
898
_nl_load_domain (domain_file, domainbinding);
900
if (domain_file->data == NULL)
903
domain = (struct loaded_domain *) domain_file->data;
905
nstrings = domain->nstrings;
907
/* Locate the MSGID and its translation. */
908
if (domain->hash_tab != NULL)
910
/* Use the hashing table. */
911
nls_uint32 len = strlen (msgid);
912
nls_uint32 hash_val = __hash_string (msgid);
913
nls_uint32 idx = hash_val % domain->hash_size;
914
nls_uint32 incr = 1 + (hash_val % (domain->hash_size - 2));
919
W (domain->must_swap_hash_tab, domain->hash_tab[idx]);
922
/* Hash table entry is empty. */
927
/* Compare msgid with the original string at index nstr.
928
We compare the lengths with >=, not ==, because plural entries
929
are represented by strings with an embedded NUL. */
931
? W (domain->must_swap, domain->orig_tab[nstr].length) >= len
933
domain->data + W (domain->must_swap,
934
domain->orig_tab[nstr].offset))
936
: domain->orig_sysdep_tab[nstr - nstrings].length > len
938
domain->orig_sysdep_tab[nstr - nstrings].pointer)
945
if (idx >= domain->hash_size - incr)
946
idx -= domain->hash_size - incr;
954
/* Try the default method: binary search in the sorted array of
964
act = (bottom + top) / 2;
965
cmp_val = strcmp (msgid, (domain->data
966
+ W (domain->must_swap,
967
domain->orig_tab[act].offset)));
970
else if (cmp_val > 0)
975
/* No translation was found. */
980
/* The translation was found at index ACT. If we have to convert the
981
string to use a different character set, this is the time. */
985
(domain->data + W (domain->must_swap, domain->trans_tab[act].offset));
986
resultlen = W (domain->must_swap, domain->trans_tab[act].length) + 1;
990
result = (char *) domain->trans_sysdep_tab[act - nstrings].pointer;
991
resultlen = domain->trans_sysdep_tab[act - nstrings].length;
994
#if defined _LIBC || HAVE_ICONV
995
# ifdef IN_LIBGLOCALE
996
if (encoding != NULL)
1001
/* We are supposed to do a conversion. */
1002
# ifndef IN_LIBGLOCALE
1003
const char *encoding = get_output_charset (domainbinding);
1005
size_t nconversions;
1006
struct converted_domain *convd;
1009
/* Protect against reallocation of the table. */
1010
gl_rwlock_rdlock (domain->conversions_lock);
1012
/* Search whether a table with converted translations for this
1013
encoding has already been allocated. */
1014
nconversions = domain->nconversions;
1017
for (i = nconversions; i > 0; )
1020
if (strcmp (domain->conversions[i].encoding, encoding) == 0)
1022
convd = &domain->conversions[i];
1027
gl_rwlock_unlock (domain->conversions_lock);
1031
/* We have to allocate a new conversions table. */
1032
gl_rwlock_wrlock (domain->conversions_lock);
1034
/* Maybe in the meantime somebody added the translation.
1036
for (i = nconversions; i > 0; )
1039
if (strcmp (domain->conversions[i].encoding, encoding) == 0)
1041
convd = &domain->conversions[i];
1047
/* Allocate a table for the converted translations for this
1049
struct converted_domain *new_conversions =
1050
(struct converted_domain *)
1051
(domain->conversions != NULL
1052
? realloc (domain->conversions,
1053
(nconversions + 1) * sizeof (struct converted_domain))
1054
: malloc ((nconversions + 1) * sizeof (struct converted_domain)));
1056
if (__builtin_expect (new_conversions == NULL, 0))
1058
/* Nothing we can do, no more memory. We cannot use the
1059
translation because it might be encoded incorrectly. */
1061
gl_rwlock_unlock (domain->conversions_lock);
1065
domain->conversions = new_conversions;
1067
/* Copy the 'encoding' string to permanent storage. */
1068
encoding = strdup (encoding);
1069
if (__builtin_expect (encoding == NULL, 0))
1070
/* Nothing we can do, no more memory. We cannot use the
1071
translation because it might be encoded incorrectly. */
1074
convd = &new_conversions[nconversions];
1075
convd->encoding = encoding;
1077
/* Find out about the character set the file is encoded with.
1078
This can be found (in textual form) in the entry "". If this
1079
entry does not exist or if this does not contain the 'charset='
1080
information, we will assume the charset matches the one the
1081
current locale and we don't have to perform any conversion. */
1083
convd->conv = (__gconv_t) -1;
1086
convd->conv = (iconv_t) -1;
1091
size_t nullentrylen;
1093
/* Get the header entry. This is a recursion, but it doesn't
1094
reallocate domain->conversions because we pass
1095
encoding = NULL or convert = 0, respectively. */
1097
# ifdef IN_LIBGLOCALE
1098
_nl_find_msg (domain_file, domainbinding, NULL, "",
1101
_nl_find_msg (domain_file, domainbinding, "", 0, &nullentrylen);
1104
if (nullentry != NULL)
1106
const char *charsetstr;
1108
charsetstr = strstr (nullentry, "charset=");
1109
if (charsetstr != NULL)
1113
const char *outcharset;
1115
charsetstr += strlen ("charset=");
1116
len = strcspn (charsetstr, " \t\n");
1118
charset = (char *) alloca (len + 1);
1119
# if defined _LIBC || HAVE_MEMPCPY
1120
*((char *) mempcpy (charset, charsetstr, len)) = '\0';
1122
memcpy (charset, charsetstr, len);
1123
charset[len] = '\0';
1126
outcharset = encoding;
1129
/* We always want to use transliteration. */
1130
outcharset = norm_add_slashes (outcharset, "TRANSLIT");
1131
charset = norm_add_slashes (charset, "");
1132
int r = __gconv_open (outcharset, charset, &convd->conv,
1133
GCONV_AVOID_NOCONV);
1134
if (__builtin_expect (r != __GCONV_OK, 0))
1136
/* If the output encoding is the same there is
1137
nothing to do. Otherwise do not use the
1138
translation at all. */
1139
if (__builtin_expect (r != __GCONV_NULCONV, 1))
1141
gl_rwlock_unlock (domain->conversions_lock);
1142
free ((char *) encoding);
1146
convd->conv = (__gconv_t) -1;
1150
/* When using GNU libc >= 2.2 or GNU libiconv >= 1.5,
1151
we want to use transliteration. */
1152
# if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2) || __GLIBC__ > 2 \
1153
|| _LIBICONV_VERSION >= 0x0105
1154
if (strchr (outcharset, '/') == NULL)
1158
len = strlen (outcharset);
1159
tmp = (char *) alloca (len + 10 + 1);
1160
memcpy (tmp, outcharset, len);
1161
memcpy (tmp + len, "//TRANSLIT", 10 + 1);
1164
convd->conv = iconv_open (outcharset, charset);
1170
convd->conv = iconv_open (outcharset, charset);
1178
convd->conv_tab = NULL;
1179
/* Here domain->conversions is still == new_conversions. */
1180
domain->nconversions++;
1184
gl_rwlock_unlock (domain->conversions_lock);
1189
convd->conv != (__gconv_t) -1
1192
convd->conv != (iconv_t) -1
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
1206
if (convd->conv_tab == NULL
1207
&& ((convd->conv_tab =
1208
(char **) calloc (nstrings + domain->n_sysdep_strings,
1211
/* Mark that we didn't succeed allocating a table. */
1212
convd->conv_tab = (char **) -1;
1214
if (__builtin_expect (convd->conv_tab == (char **) -1, 0))
1215
/* Nothing we can do, no more memory. We cannot use the
1216
translation because it might be encoded incorrectly. */
1219
if (convd->conv_tab[act] == NULL)
1221
/* We haven't used this string so far, so it is not
1222
translated yet. Do this now. */
1223
/* We use a bit more efficient memory handling.
1224
We allocate always larger blocks which get used over
1225
time. This is faster than many small allocations. */
1226
__libc_lock_define_initialized (static, lock)
1227
# define INITIAL_BLOCK_SIZE 4080
1228
static unsigned char *freemem;
1229
static size_t freemem_size;
1231
const unsigned char *inbuf;
1232
unsigned char *outbuf;
1235
transmem_block_t *transmem_list = NULL;
1238
__libc_lock_lock (lock);
1240
inbuf = (const unsigned char *) result;
1241
outbuf = freemem + sizeof (size_t);
1246
transmem_block_t *newmem;
1248
size_t non_reversible;
1251
if (freemem_size < sizeof (size_t))
1252
goto resize_freemem;
1254
res = __gconv (convd->conv,
1255
&inbuf, inbuf + resultlen,
1257
outbuf + freemem_size - sizeof (size_t),
1260
if (res == __GCONV_OK || res == __GCONV_EMPTY_INPUT)
1263
if (res != __GCONV_FULL_OUTPUT)
1265
/* We should not use the translation at all, it
1266
is incorrectly encoded. */
1267
__libc_lock_unlock (lock);
1271
inbuf = (const unsigned char *) result;
1274
const char *inptr = (const char *) inbuf;
1275
size_t inleft = resultlen;
1276
char *outptr = (char *) outbuf;
1279
if (freemem_size < sizeof (size_t))
1280
goto resize_freemem;
1282
outleft = freemem_size - sizeof (size_t);
1283
if (iconv (convd->conv,
1284
(ICONV_CONST char **) &inptr, &inleft,
1288
outbuf = (unsigned char *) outptr;
1293
__libc_lock_unlock (lock);
1300
/* We must allocate a new buffer or resize the old one. */
1301
if (malloc_count > 0)
1304
freemem_size = malloc_count * INITIAL_BLOCK_SIZE;
1305
newmem = (transmem_block_t *) realloc (transmem_list,
1309
transmem_list = transmem_list->next;
1312
struct transmem_list *old = transmem_list;
1314
transmem_list = transmem_list->next;
1322
freemem_size = INITIAL_BLOCK_SIZE;
1323
newmem = (transmem_block_t *) malloc (freemem_size);
1325
if (__builtin_expect (newmem == NULL, 0))
1329
__libc_lock_unlock (lock);
1334
/* Add the block to the list of blocks we have to free
1336
newmem->next = transmem_list;
1337
transmem_list = newmem;
1339
freemem = (unsigned char *) newmem->data;
1340
freemem_size -= offsetof (struct transmem_list, data);
1342
transmem_list = newmem;
1346
outbuf = freemem + sizeof (size_t);
1349
/* We have now in our buffer a converted string. Put this
1350
into the table of conversions. */
1351
*(size_t *) freemem = outbuf - freemem - sizeof (size_t);
1352
convd->conv_tab[act] = (char *) freemem;
1353
/* Shrink freemem, but keep it aligned. */
1354
freemem_size -= outbuf - freemem;
1356
freemem += freemem_size & (alignof (size_t) - 1);
1357
freemem_size = freemem_size & ~ (alignof (size_t) - 1);
1359
__libc_lock_unlock (lock);
1362
/* Now convd->conv_tab[act] contains the translation of all
1363
the plural variants. */
1364
result = convd->conv_tab[act] + sizeof (size_t);
1365
resultlen = *(size_t *) convd->conv_tab[act];
1369
/* The result string is converted. */
1371
#endif /* _LIBC || HAVE_ICONV */
1373
*lengthp = resultlen;
1378
/* Look up a plural variant. */
1381
plural_lookup (struct loaded_l10nfile *domain, unsigned long int n,
1382
const char *translation, size_t translation_len)
1384
struct loaded_domain *domaindata = (struct loaded_domain *) domain->data;
1385
unsigned long int index;
1388
index = plural_eval (domaindata->plural, n);
1389
if (index >= domaindata->nplurals)
1390
/* This should never happen. It means the plural expression and the
1391
given maximum value do not match. */
1394
/* Skip INDEX strings at TRANSLATION. */
1399
p = __rawmemchr (p, '\0');
1401
p = strchr (p, '\0');
1403
/* And skip over the NUL byte. */
1406
if (p >= translation + translation_len)
1407
/* This should never happen. It means the plural expression
1408
evaluated to a value larger than the number of variants
1409
available for MSGID1. */
1410
return (char *) translation;
1416
/* Return string representation of locale CATEGORY. */
1419
category_to_name (int category)
1427
retval = "LC_COLLATE";
1432
retval = "LC_CTYPE";
1437
retval = "LC_MONETARY";
1442
retval = "LC_NUMERIC";
1452
retval = "LC_MESSAGES";
1457
retval = "LC_RESPONSE";
1462
/* This might not make sense but is perhaps better than any other
1468
/* If you have a better idea for a default value let me know. */
1476
/* Guess value of current locale from value of the environment variables
1477
or system-dependent defaults. */
1480
#ifdef IN_LIBGLOCALE
1481
guess_category_value (int category, const char *categoryname,
1485
guess_category_value (int category, const char *categoryname)
1488
const char *language;
1489
#ifndef IN_LIBGLOCALE
1492
const char *language_default;
1493
int locale_defaulted;
1497
/* We use the settings in the following order:
1498
1. The value of the environment variable 'LANGUAGE'. This is a GNU
1499
extension. Its value can be a colon-separated list of locale names.
1500
2. The value of the environment variable 'LC_ALL', 'LC_xxx', or 'LANG'.
1501
More precisely, the first among these that is set to a non-empty value.
1502
This is how POSIX specifies it. The value is a single locale name.
1503
3. A system-dependent preference list of languages. Its value can be a
1504
colon-separated list of locale names.
1505
4. A system-dependent default locale name.
1507
- System-dependent settings can be overridden by environment variables.
1508
- If the system provides both a list of languages and a default locale,
1509
the former is used. */
1511
#ifndef IN_LIBGLOCALE
1512
/* Fetch the locale name, through the POSIX method of looking to `LC_ALL',
1513
`LC_xxx', and `LANG'. On some systems this can be done by the
1514
`setlocale' function itself. */
1516
locale = __current_locale_name (category);
1518
# if HAVE_STRUCT___LOCALE_STRUCT___NAMES && defined USE_IN_GETTEXT_TESTS
1519
/* The __names field is not public glibc API and must therefore not be used
1520
in code that is installed in public locations. */
1521
locale_t thread_locale = uselocale (NULL);
1522
if (thread_locale != LC_GLOBAL_LOCALE)
1524
locale = thread_locale->__names[category];
1525
locale_defaulted = 0;
1530
locale = _nl_locale_name_posix (category, categoryname);
1531
locale_defaulted = 0;
1534
locale = _nl_locale_name_default ();
1535
locale_defaulted = 1;
1541
/* Ignore LANGUAGE and its system-dependent analogon if the locale is set
1543
1. "C" locale usually uses the ASCII encoding, and most international
1544
messages use non-ASCII characters. These characters get displayed
1545
as question marks (if using glibc's iconv()) or as invalid 8-bit
1546
characters (because other iconv()s refuse to convert most non-ASCII
1547
characters to ASCII). In any case, the output is ugly.
1548
2. The precise output of some programs in the "C" locale is specified
1549
by POSIX and should not depend on environment variables like
1550
"LANGUAGE" or system-dependent information. We allow such programs
1551
to use gettext(). */
1552
if (strcmp (locale, "C") == 0)
1555
/* The highest priority value is the value of the 'LANGUAGE' environment
1557
language = getenv ("LANGUAGE");
1558
if (language != NULL && language[0] != '\0')
1560
#if !defined IN_LIBGLOCALE && !defined _LIBC
1561
/* The next priority value is the locale name, if not defaulted. */
1562
if (locale_defaulted)
1564
/* The next priority value is the default language preferences list. */
1565
language_default = _nl_language_preferences_default ();
1566
if (language_default != NULL)
1567
return language_default;
1569
/* The least priority value is the locale name, if defaulted. */
1574
#if (defined _LIBC || HAVE_ICONV) && !defined IN_LIBGLOCALE
1575
/* Returns the output charset. */
1578
get_output_charset (struct binding *domainbinding)
1580
/* The output charset should normally be determined by the locale. But
1581
sometimes the locale is not used or not correctly set up, so we provide
1582
a possibility for the user to override this: the OUTPUT_CHARSET
1583
environment variable. Moreover, the value specified through
1584
bind_textdomain_codeset overrides both. */
1585
if (domainbinding != NULL && domainbinding->codeset != NULL)
1586
return domainbinding->codeset;
1589
/* For speed reasons, we look at the value of OUTPUT_CHARSET only
1590
once. This is a user variable that is not supposed to change
1591
during a program run. */
1592
static char *output_charset_cache;
1593
static int output_charset_cached;
1595
if (!output_charset_cached)
1597
const char *value = getenv ("OUTPUT_CHARSET");
1599
if (value != NULL && value[0] != '\0')
1601
size_t len = strlen (value) + 1;
1602
char *value_copy = (char *) malloc (len);
1604
if (value_copy != NULL)
1605
memcpy (value_copy, value, len);
1606
output_charset_cache = value_copy;
1608
output_charset_cached = 1;
1611
if (output_charset_cache != NULL)
1612
return output_charset_cache;
1616
return _NL_CURRENT (LC_CTYPE, CODESET);
1619
return locale_charset ();
1627
/* @@ begin of epilog @@ */
1629
/* We don't want libintl.a to depend on any other library. So we
1630
avoid the non-standard function stpcpy. In GNU C Library this
1631
function is available, though. Also allow the symbol HAVE_STPCPY
1633
#if !_LIBC && !HAVE_STPCPY
1635
stpcpy (char *dest, const char *src)
1637
while ((*dest++ = *src++) != '\0')
1643
#if !_LIBC && !HAVE_MEMPCPY
1645
mempcpy (void *dest, const void *src, size_t n)
1647
return (void *) ((char *) memcpy (dest, src, n) + n);
1651
#if !_LIBC && !HAVE_TSEARCH
1652
# include "tsearch.c"
1657
/* If we want to free all resources we have to do some work at
1659
libc_freeres_fn (free_mem)
1663
while (_nl_domain_bindings != NULL)
1665
struct binding *oldp = _nl_domain_bindings;
1666
_nl_domain_bindings = _nl_domain_bindings->next;
1667
if (oldp->dirname != _nl_default_dirname)
1668
/* Yes, this is a pointer comparison. */
1669
free (oldp->dirname);
1670
free (oldp->codeset);
1674
if (_nl_current_default_domain != _nl_default_default_domain)
1675
/* Yes, again a pointer comparison. */
1676
free ((char *) _nl_current_default_domain);
1678
/* Remove the search tree with the known translations. */
1679
__tdestroy (root, free);
1682
while (transmem_list != NULL)
1684
old = transmem_list;
1685
transmem_list = transmem_list->next;