1 /* Implementation of the internal dcigettext function.
2 Copyright (C) 1995-2017 Free Software Foundation, Inc.
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.
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.
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/>. */
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. */
21 # define _GNU_SOURCE 1
28 #include <sys/types.h>
31 # define alloca __builtin_alloca
32 # define HAVE_ALLOCA 1
36 # define alloca _alloca
38 # if defined HAVE_ALLOCA_H || defined _LIBC
57 # define __set_errno(val) errno = (val)
64 #if defined HAVE_UNISTD_H || defined _LIBC
71 /* Guess whether integer division by zero raises signal SIGFPE.
72 Set to 1 only if you know for sure. In case of doubt, set to 0. */
73 # if defined __alpha__ || defined __arm__ || defined __i386__ \
74 || defined __m68k__ || defined __s390__
75 # define INTDIV0_RAISES_SIGFPE 1
77 # define INTDIV0_RAISES_SIGFPE 0
80 #if !INTDIV0_RAISES_SIGFPE
84 #if defined HAVE_SYS_PARAM_H || defined _LIBC
85 # include <sys/param.h>
89 # include "localcharset.h"
93 #include "plural-exp.h"
100 # include "libgnuintl.h"
102 #include "hash-string.h"
104 /* Handle multi-threaded applications. */
106 # include <libc-lock.h>
107 # define gl_rwlock_define_initialized __libc_rwlock_define_initialized
108 # define gl_rwlock_rdlock __libc_rwlock_rdlock
109 # define gl_rwlock_wrlock __libc_rwlock_wrlock
110 # define gl_rwlock_unlock __libc_rwlock_unlock
115 /* Alignment of types. */
116 #if defined __GNUC__ && __GNUC__ >= 2
117 # define alignof(TYPE) __alignof__ (TYPE)
119 # define alignof(TYPE) \
120 ((int) &((struct { char dummy1; TYPE dummy2; } *) 0)->dummy2)
123 /* Some compilers, like SunOS4 cc, don't have offsetof in <stddef.h>. */
125 # define offsetof(type,ident) ((size_t)&(((type*)0)->ident))
128 /* @@ end of prolog @@ */
131 /* Rename the non ANSI C functions. This is required by the standard
132 because some ANSI C functions will require linking with this object
133 file and the name space must not be polluted. */
134 # define strdup __strdup
135 # define getcwd __getcwd
137 # define stpcpy __stpcpy
139 # define tfind __tfind
141 # if !defined HAVE_GETCWD
143 # define getcwd(buf, max) getwd (buf)
146 # define getcwd(buf, max) (getcwd) (buf, max, 0)
152 static char *stpcpy (char *dest
, const char *src
);
154 # ifndef HAVE_MEMPCPY
155 static void *mempcpy (void *dest
, const void *src
, size_t n
);
159 /* Use a replacement if the system does not provide the `tsearch' function
161 #if defined HAVE_TSEARCH || defined _LIBC
164 # define tsearch libintl_tsearch
165 # define tfind libintl_tfind
166 # define tdelete libintl_tdelete
167 # define twalk libintl_twalk
168 # include "tsearch.h"
172 # define tsearch __tsearch
175 /* Amount to increase buffer size by in each try. */
178 /* The following is from pathmax.h. */
179 /* Non-POSIX BSD systems might have gcc's limits.h, which doesn't define
180 PATH_MAX but might cause redefinition warnings when sys/param.h is
181 later included (as on MORE/BSD 4.3). */
182 #if defined _POSIX_VERSION || (defined HAVE_LIMITS_H && !defined __GNUC__)
186 #ifndef _POSIX_PATH_MAX
187 # define _POSIX_PATH_MAX 255
190 #if !defined PATH_MAX && defined _PC_PATH_MAX
191 # define PATH_MAX (__pathconf ("/", _PC_PATH_MAX) < 1 ? 1024 : __pathconf ("/", _PC_PATH_MAX))
194 /* Don't include sys/param.h if it already has been. */
195 #if defined HAVE_SYS_PARAM_H && !defined PATH_MAX && !defined MAXPATHLEN
196 # include <sys/param.h>
199 #if !defined PATH_MAX && defined MAXPATHLEN
200 # define PATH_MAX MAXPATHLEN
204 # define PATH_MAX _POSIX_PATH_MAX
208 ISSLASH(C) tests whether C is a directory separator character.
209 IS_ABSOLUTE_PATH(P) tests whether P is an absolute path. If it is not,
210 it may be concatenated to a directory pathname.
211 IS_PATH_WITH_DIR(P) tests whether P contains a directory specification.
213 #if defined _WIN32 || defined __WIN32__ || defined __CYGWIN__ || defined __EMX__ || defined __DJGPP__
214 /* Win32, Cygwin, OS/2, DOS */
215 # define ISSLASH(C) ((C) == '/' || (C) == '\\')
216 # define HAS_DEVICE(P) \
217 ((((P)[0] >= 'A' && (P)[0] <= 'Z') || ((P)[0] >= 'a' && (P)[0] <= 'z')) \
219 # define IS_ABSOLUTE_PATH(P) (ISSLASH ((P)[0]) || HAS_DEVICE (P))
220 # define IS_PATH_WITH_DIR(P) \
221 (strchr (P, '/') != NULL || strchr (P, '\\') != NULL || HAS_DEVICE (P))
224 # define ISSLASH(C) ((C) == '/')
225 # define IS_ABSOLUTE_PATH(P) ISSLASH ((P)[0])
226 # define IS_PATH_WITH_DIR(P) (strchr (P, '/') != NULL)
229 /* Whether to support different locales in different threads. */
230 #if defined _LIBC || HAVE_USELOCALE || defined IN_LIBGLOCALE
231 # define HAVE_PER_THREAD_LOCALE
234 /* This is the type used for the search tree where known translations
236 struct known_translation_t
238 /* Domain in which to search. */
239 const char *domainname
;
244 #ifdef HAVE_PER_THREAD_LOCALE
245 /* Name of the relevant locale category, or "" for the global locale. */
246 const char *localename
;
250 /* The character encoding. */
251 const char *encoding
;
254 /* State of the catalog counter at the point the string was found. */
257 /* Catalog where the string was found. */
258 struct loaded_l10nfile
*domain
;
260 /* And finally the translation. */
261 const char *translation
;
262 size_t translation_length
;
264 /* Pointer to the string in question. */
267 char appended
[ZERO
]; /* used if domain != NULL */
268 const char *ptr
; /* used if domain == NULL */
273 gl_rwlock_define_initialized (static, tree_lock
)
275 /* Root of the search tree with known translations. */
278 /* Function to compare two entries in the table of known translations. */
280 transcmp (const void *p1
, const void *p2
)
282 const struct known_translation_t
*s1
;
283 const struct known_translation_t
*s2
;
286 s1
= (const struct known_translation_t
*) p1
;
287 s2
= (const struct known_translation_t
*) p2
;
289 result
= strcmp (s1
->domain
!= NULL
? s1
->msgid
.appended
: s1
->msgid
.ptr
,
290 s2
->domain
!= NULL
? s2
->msgid
.appended
: s2
->msgid
.ptr
);
293 result
= strcmp (s1
->domainname
, s2
->domainname
);
296 #ifdef HAVE_PER_THREAD_LOCALE
297 result
= strcmp (s1
->localename
, s2
->localename
);
302 result
= strcmp (s1
->encoding
, s2
->encoding
);
305 /* We compare the category last (though this is the cheapest
306 operation) since it is hopefully always the same (namely
308 result
= s1
->category
- s2
->category
;
316 /* Name of the default domain used for gettext(3) prior any call to
317 textdomain(3). The default value for this is "messages". */
318 const char _nl_default_default_domain
[] attribute_hidden
= "messages";
320 #ifndef IN_LIBGLOCALE
321 /* Value used as the default domain for gettext(3). */
322 const char *_nl_current_default_domain attribute_hidden
323 = _nl_default_default_domain
;
326 /* Contains the default location of the message catalogs. */
328 extern const char _nl_default_dirname
[];
331 extern const char _nl_default_dirname
[];
332 libc_hidden_proto (_nl_default_dirname
)
334 const char _nl_default_dirname
[] = LOCALEDIR
;
336 libc_hidden_data_def (_nl_default_dirname
)
340 #ifndef IN_LIBGLOCALE
341 /* List with bindings of specific domains created by bindtextdomain()
343 struct binding
*_nl_domain_bindings
;
346 /* Prototypes for local functions. */
347 static char *plural_lookup (struct loaded_l10nfile
*domain
,
349 const char *translation
, size_t translation_len
)
353 static const char *guess_category_value (int category
,
354 const char *categoryname
,
355 const char *localename
)
358 static const char *guess_category_value (int category
,
359 const char *categoryname
)
364 # include "../locale/localeinfo.h"
365 # define category_to_name(category) \
366 _nl_category_names.str + _nl_category_name_idxs[category]
368 static const char *category_to_name (int category
) internal_function
;
370 #if (defined _LIBC || HAVE_ICONV) && !defined IN_LIBGLOCALE
371 static const char *get_output_charset (struct binding
*domainbinding
)
376 /* For those losing systems which don't have `alloca' we have to add
377 some additional code emulating it. */
379 /* Nothing has to be done. */
380 # define freea(p) /* nothing */
381 # define ADD_BLOCK(list, address) /* nothing */
382 # define FREE_BLOCKS(list) /* nothing */
387 struct block_list
*next
;
389 # define ADD_BLOCK(list, addr) \
391 struct block_list *newp = (struct block_list *) malloc (sizeof (*newp)); \
392 /* If we cannot get a free block we cannot add the new element to \
394 if (newp != NULL) { \
395 newp->address = (addr); \
396 newp->next = (list); \
400 # define FREE_BLOCKS(list) \
402 while (list != NULL) { \
403 struct block_list *old = list; \
405 free (old->address); \
410 # define alloca(size) (malloc (size))
411 # define freea(p) free (p)
412 #endif /* have alloca */
416 /* List of blocks allocated for translations. */
417 typedef struct transmem_list
419 struct transmem_list
*next
;
422 static struct transmem_list
*transmem_list
;
424 typedef unsigned char transmem_block_t
;
428 /* Names for the libintl functions are a problem. They must not clash
429 with existing names and they should follow ANSI C. But this source
430 code is also used in GNU C Library where the names have a __
431 prefix. So we have to make a difference here. */
433 # define DCIGETTEXT __dcigettext
435 # define DCIGETTEXT libintl_dcigettext
438 /* Lock variable to protect the global data in the gettext implementation. */
439 gl_rwlock_define_initialized (, _nl_state_lock attribute_hidden
)
441 /* Checking whether the binaries runs SUID must be done and glibc provides
442 easier methods therefore we make a difference here. */
444 # define ENABLE_SECURE __libc_enable_secure
445 # define DETERMINE_SECURE
453 # ifndef HAVE_GETEUID
454 # define geteuid() getuid()
456 # ifndef HAVE_GETEGID
457 # define getegid() getgid()
459 static int enable_secure
;
460 # define ENABLE_SECURE (enable_secure == 1)
461 # define DETERMINE_SECURE \
462 if (enable_secure == 0) \
464 if (getuid () != geteuid () || getgid () != getegid ()) \
467 enable_secure = -1; \
471 /* Get the function to evaluate the plural expression. */
472 #include "eval-plural.h"
474 /* Look up MSGID in the DOMAINNAME message catalog for the current
475 CATEGORY locale and, if PLURAL is nonzero, search over string
476 depending on the plural form determined by N. */
479 gl_dcigettext (const char *domainname
,
480 const char *msgid1
, const char *msgid2
,
481 int plural
, unsigned long int n
,
483 const char *localename
, const char *encoding
)
486 DCIGETTEXT (const char *domainname
, const char *msgid1
, const char *msgid2
,
487 int plural
, unsigned long int n
, int category
)
491 struct block_list
*block_list
= NULL
;
493 struct loaded_l10nfile
*domain
;
494 struct binding
*binding
;
495 const char *categoryname
;
496 const char *categoryvalue
;
503 struct known_translation_t search
;
504 struct known_translation_t
**foundp
= NULL
;
505 #if defined HAVE_PER_THREAD_LOCALE && !defined IN_LIBGLOCALE
506 const char *localename
;
508 size_t domainname_len
;
510 /* If no real MSGID is given return NULL. */
515 if (category
< 0 || category
>= __LC_LAST
|| category
== LC_ALL
)
519 /* Use the Germanic plural rule. */
520 : n
== 1 ? (char *) msgid1
: (char *) msgid2
);
523 /* Preserve the `errno' value. */
527 __libc_rwlock_define (extern, __libc_setlocale_lock attribute_hidden
)
528 __libc_rwlock_rdlock (__libc_setlocale_lock
);
531 gl_rwlock_rdlock (_nl_state_lock
);
533 /* If DOMAINNAME is NULL, we are interested in the default domain. If
534 CATEGORY is not LC_MESSAGES this might not make much sense but the
535 definition left this undefined. */
536 if (domainname
== NULL
)
537 domainname
= _nl_current_default_domain
;
539 /* OS/2 specific: backward compatibility with older libintl versions */
540 #ifdef LC_MESSAGES_COMPAT
541 if (category
== LC_MESSAGES_COMPAT
)
542 category
= LC_MESSAGES
;
545 /* Try to find the translation among those which we found at
547 search
.domain
= NULL
;
548 search
.msgid
.ptr
= msgid1
;
549 search
.domainname
= domainname
;
550 search
.category
= category
;
551 #ifdef HAVE_PER_THREAD_LOCALE
552 # ifndef IN_LIBGLOCALE
554 localename
= strdupa (__current_locale_name (category
));
556 categoryname
= category_to_name (category
);
557 # define CATEGORYNAME_INITIALIZED
558 localename
= _nl_locale_name_thread_unsafe (category
, categoryname
);
559 if (localename
== NULL
)
563 search
.localename
= localename
;
564 # ifdef IN_LIBGLOCALE
565 search
.encoding
= encoding
;
568 /* Since tfind/tsearch manage a balanced tree, concurrent tfind and
569 tsearch calls can be fatal. */
570 gl_rwlock_rdlock (tree_lock
);
572 foundp
= (struct known_translation_t
**) tfind (&search
, &root
, transcmp
);
574 gl_rwlock_unlock (tree_lock
);
576 if (foundp
!= NULL
&& (*foundp
)->counter
== _nl_msg_cat_cntr
)
578 /* Now deal with plural. */
580 retval
= plural_lookup ((*foundp
)->domain
, n
, (*foundp
)->translation
,
581 (*foundp
)->translation_length
);
583 retval
= (char *) (*foundp
)->translation
;
585 gl_rwlock_unlock (_nl_state_lock
);
587 __libc_rwlock_unlock (__libc_setlocale_lock
);
589 __set_errno (saved_errno
);
594 /* See whether this is a SUID binary or not. */
597 /* First find matching binding. */
599 /* We can use a trivial binding, since _nl_find_msg will ignore it anyway,
600 and _nl_load_domain and _nl_find_domain just pass it through. */
602 dirname
= bindtextdomain (domainname
, NULL
);
604 for (binding
= _nl_domain_bindings
; binding
!= NULL
; binding
= binding
->next
)
606 int compare
= strcmp (domainname
, binding
->domainname
);
612 /* It is not in the list. */
619 dirname
= _nl_default_dirname
;
622 dirname
= binding
->dirname
;
624 if (!IS_ABSOLUTE_PATH (dirname
))
626 /* We have a relative path. Make it absolute now. */
627 size_t dirname_len
= strlen (dirname
) + 1;
629 char *resolved_dirname
;
632 path_max
= (unsigned int) PATH_MAX
;
633 path_max
+= 2; /* The getcwd docs say to do this. */
637 resolved_dirname
= (char *) alloca (path_max
+ dirname_len
);
638 ADD_BLOCK (block_list
, tmp_dirname
);
641 ret
= getcwd (resolved_dirname
, path_max
);
642 if (ret
!= NULL
|| errno
!= ERANGE
)
645 path_max
+= path_max
/ 2;
646 path_max
+= PATH_INCR
;
650 /* We cannot get the current working directory. Don't signal an
651 error but simply return the default string. */
652 goto return_untranslated
;
654 stpcpy (stpcpy (strchr (resolved_dirname
, '\0'), "/"), dirname
);
655 dirname
= resolved_dirname
;
657 #ifndef IN_LIBGLOCALE
661 /* Now determine the symbolic name of CATEGORY and its value. */
662 #ifndef CATEGORYNAME_INITIALIZED
663 categoryname
= category_to_name (category
);
666 categoryvalue
= guess_category_value (category
, categoryname
, localename
);
668 categoryvalue
= guess_category_value (category
, categoryname
);
671 domainname_len
= strlen (domainname
);
672 xdomainname
= (char *) alloca (strlen (categoryname
)
673 + domainname_len
+ 5);
674 ADD_BLOCK (block_list
, xdomainname
);
676 stpcpy ((char *) mempcpy (stpcpy (stpcpy (xdomainname
, categoryname
), "/"),
677 domainname
, domainname_len
),
680 /* Creating working area. */
681 single_locale
= (char *) alloca (strlen (categoryvalue
) + 1);
682 ADD_BLOCK (block_list
, single_locale
);
685 /* Search for the given string. This is a loop because we perhaps
686 got an ordered list of languages to consider for the translation. */
689 /* Make CATEGORYVALUE point to the next element of the list. */
690 while (categoryvalue
[0] != '\0' && categoryvalue
[0] == ':')
692 if (categoryvalue
[0] == '\0')
694 /* The whole contents of CATEGORYVALUE has been searched but
695 no valid entry has been found. We solve this situation
696 by implicitly appending a "C" entry, i.e. no translation
698 single_locale
[0] = 'C';
699 single_locale
[1] = '\0';
703 char *cp
= single_locale
;
704 while (categoryvalue
[0] != '\0' && categoryvalue
[0] != ':')
705 *cp
++ = *categoryvalue
++;
708 /* When this is a SUID binary we must not allow accessing files
709 outside the dedicated directories. */
710 if (ENABLE_SECURE
&& IS_PATH_WITH_DIR (single_locale
))
711 /* Ingore this entry. */
715 /* If the current locale value is C (or POSIX) we don't load a
716 domain. Return the MSGID. */
717 if (strcmp (single_locale
, "C") == 0
718 || strcmp (single_locale
, "POSIX") == 0)
721 /* Find structure describing the message catalog matching the
722 DOMAINNAME and CATEGORY. */
723 domain
= _nl_find_domain (dirname
, single_locale
, xdomainname
, binding
);
727 #if defined IN_LIBGLOCALE
728 retval
= _nl_find_msg (domain
, binding
, encoding
, msgid1
, &retlen
);
730 retval
= _nl_find_msg (domain
, binding
, msgid1
, 1, &retlen
);
737 for (cnt
= 0; domain
->successor
[cnt
] != NULL
; ++cnt
)
739 #if defined IN_LIBGLOCALE
740 retval
= _nl_find_msg (domain
->successor
[cnt
], binding
,
741 encoding
, msgid1
, &retlen
);
743 retval
= _nl_find_msg (domain
->successor
[cnt
], binding
,
747 /* Resource problems are not fatal, instead we return no
749 if (__builtin_expect (retval
== (char *) -1, 0))
750 goto return_untranslated
;
754 domain
= domain
->successor
[cnt
];
760 /* Returning -1 means that some resource problem exists
761 (likely memory) and that the strings could not be
762 converted. Return the original strings. */
763 if (__builtin_expect (retval
== (char *) -1, 0))
768 /* Found the translation of MSGID1 in domain DOMAIN:
769 starting at RETVAL, RETLEN bytes. */
770 FREE_BLOCKS (block_list
);
773 /* Create a new entry and add it to the search tree. */
776 struct known_translation_t
*newp
;
778 msgid_len
= strlen (msgid1
) + 1;
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
.appended
, msgid1
,
795 memcpy (new_domainname
, domainname
, domainname_len
+ 1);
796 #ifdef HAVE_PER_THREAD_LOCALE
797 new_localename
= new_domainname
+ domainname_len
+ 1;
798 strcpy (new_localename
, localename
);
800 newp
->domainname
= new_domainname
;
801 newp
->category
= category
;
802 #ifdef HAVE_PER_THREAD_LOCALE
803 newp
->localename
= new_localename
;
806 newp
->encoding
= encoding
;
808 newp
->counter
= _nl_msg_cat_cntr
;
809 newp
->domain
= domain
;
810 newp
->translation
= retval
;
811 newp
->translation_length
= retlen
;
813 gl_rwlock_wrlock (tree_lock
);
815 /* Insert the entry in the search tree. */
816 foundp
= (struct known_translation_t
**)
817 tsearch (newp
, &root
, transcmp
);
819 gl_rwlock_unlock (tree_lock
);
822 || __builtin_expect (*foundp
!= newp
, 0))
823 /* The insert failed. */
829 /* We can update the existing entry. */
830 (*foundp
)->counter
= _nl_msg_cat_cntr
;
831 (*foundp
)->domain
= domain
;
832 (*foundp
)->translation
= retval
;
833 (*foundp
)->translation_length
= retlen
;
836 __set_errno (saved_errno
);
838 /* Now deal with plural. */
840 retval
= plural_lookup (domain
, n
, retval
, retlen
);
842 gl_rwlock_unlock (_nl_state_lock
);
844 __libc_rwlock_unlock (__libc_setlocale_lock
);
852 /* Return the untranslated MSGID. */
853 FREE_BLOCKS (block_list
);
854 gl_rwlock_unlock (_nl_state_lock
);
856 __libc_rwlock_unlock (__libc_setlocale_lock
);
861 extern void _nl_log_untranslated (const char *logfilename
,
862 const char *domainname
,
863 const char *msgid1
, const char *msgid2
,
865 const char *logfilename
= getenv ("GETTEXT_LOG_UNTRANSLATED");
867 if (logfilename
!= NULL
&& logfilename
[0] != '\0')
868 _nl_log_untranslated (logfilename
, domainname
, msgid1
, msgid2
, plural
);
871 __set_errno (saved_errno
);
874 /* Use the Germanic plural rule. */
875 : n
== 1 ? (char *) msgid1
: (char *) msgid2
);
879 /* Look up the translation of msgid within DOMAIN_FILE and DOMAINBINDING.
880 Return it if found. Return NULL if not found or in case of a conversion
881 failure (problem in the particular message catalog). Return (char *) -1
882 in case of a memory allocation failure during conversion (only if
883 ENCODING != NULL resp. CONVERT == true). */
887 _nl_find_msg (struct loaded_l10nfile
*domain_file
,
888 struct binding
*domainbinding
, const char *encoding
,
892 _nl_find_msg (struct loaded_l10nfile
*domain_file
,
893 struct binding
*domainbinding
,
894 const char *msgid
, int convert
,
898 struct loaded_domain
*domain
;
904 if (domain_file
->decided
<= 0)
905 _nl_load_domain (domain_file
, domainbinding
);
907 if (domain_file
->data
== NULL
)
910 domain
= (struct loaded_domain
*) domain_file
->data
;
912 nstrings
= domain
->nstrings
;
914 /* Locate the MSGID and its translation. */
915 if (domain
->hash_tab
!= NULL
)
917 /* Use the hashing table. */
918 nls_uint32 len
= strlen (msgid
);
919 nls_uint32 hash_val
= __hash_string (msgid
);
920 nls_uint32 idx
= hash_val
% domain
->hash_size
;
921 nls_uint32 incr
= 1 + (hash_val
% (domain
->hash_size
- 2));
926 W (domain
->must_swap_hash_tab
, domain
->hash_tab
[idx
]);
929 /* Hash table entry is empty. */
934 /* Compare msgid with the original string at index nstr.
935 We compare the lengths with >=, not ==, because plural entries
936 are represented by strings with an embedded NUL. */
938 ? W (domain
->must_swap
, domain
->orig_tab
[nstr
].length
) >= len
940 domain
->data
+ W (domain
->must_swap
,
941 domain
->orig_tab
[nstr
].offset
))
943 : domain
->orig_sysdep_tab
[nstr
- nstrings
].length
> len
945 domain
->orig_sysdep_tab
[nstr
- nstrings
].pointer
)
952 if (idx
>= domain
->hash_size
- incr
)
953 idx
-= domain
->hash_size
- incr
;
961 /* Try the default method: binary search in the sorted array of
971 act
= (bottom
+ top
) / 2;
972 cmp_val
= strcmp (msgid
, (domain
->data
973 + W (domain
->must_swap
,
974 domain
->orig_tab
[act
].offset
)));
977 else if (cmp_val
> 0)
982 /* No translation was found. */
987 /* The translation was found at index ACT. If we have to convert the
988 string to use a different character set, this is the time. */
992 (domain
->data
+ W (domain
->must_swap
, domain
->trans_tab
[act
].offset
));
993 resultlen
= W (domain
->must_swap
, domain
->trans_tab
[act
].length
) + 1;
997 result
= (char *) domain
->trans_sysdep_tab
[act
- nstrings
].pointer
;
998 resultlen
= domain
->trans_sysdep_tab
[act
- nstrings
].length
;
1001 #if defined _LIBC || HAVE_ICONV
1002 # ifdef IN_LIBGLOCALE
1003 if (encoding
!= NULL
)
1008 /* We are supposed to do a conversion. */
1009 # ifndef IN_LIBGLOCALE
1010 const char *encoding
= get_output_charset (domainbinding
);
1012 size_t nconversions
;
1013 struct converted_domain
*convd
;
1016 /* Protect against reallocation of the table. */
1017 gl_rwlock_rdlock (domain
->conversions_lock
);
1019 /* Search whether a table with converted translations for this
1020 encoding has already been allocated. */
1021 nconversions
= domain
->nconversions
;
1024 for (i
= nconversions
; i
> 0; )
1027 if (strcmp (domain
->conversions
[i
].encoding
, encoding
) == 0)
1029 convd
= &domain
->conversions
[i
];
1034 gl_rwlock_unlock (domain
->conversions_lock
);
1038 /* We have to allocate a new conversions table. */
1039 gl_rwlock_wrlock (domain
->conversions_lock
);
1040 nconversions
= domain
->nconversions
;
1042 /* Maybe in the meantime somebody added the translation.
1044 for (i
= nconversions
; i
> 0; )
1047 if (strcmp (domain
->conversions
[i
].encoding
, encoding
) == 0)
1049 convd
= &domain
->conversions
[i
];
1055 /* Allocate a table for the converted translations for this
1057 struct converted_domain
*new_conversions
=
1058 (struct converted_domain
*)
1059 (domain
->conversions
!= NULL
1060 ? realloc (domain
->conversions
,
1061 (nconversions
+ 1) * sizeof (struct converted_domain
))
1062 : malloc ((nconversions
+ 1) * sizeof (struct converted_domain
)));
1064 if (__builtin_expect (new_conversions
== NULL
, 0))
1066 /* Nothing we can do, no more memory. We cannot use the
1067 translation because it might be encoded incorrectly. */
1069 gl_rwlock_unlock (domain
->conversions_lock
);
1073 domain
->conversions
= new_conversions
;
1075 /* Copy the 'encoding' string to permanent storage. */
1076 encoding
= strdup (encoding
);
1077 if (__builtin_expect (encoding
== NULL
, 0))
1078 /* Nothing we can do, no more memory. We cannot use the
1079 translation because it might be encoded incorrectly. */
1082 convd
= &new_conversions
[nconversions
];
1083 convd
->encoding
= encoding
;
1085 /* Find out about the character set the file is encoded with.
1086 This can be found (in textual form) in the entry "". If this
1087 entry does not exist or if this does not contain the 'charset='
1088 information, we will assume the charset matches the one the
1089 current locale and we don't have to perform any conversion. */
1091 convd
->conv
= (__gconv_t
) -1;
1094 convd
->conv
= (iconv_t
) -1;
1099 size_t nullentrylen
;
1101 /* Get the header entry. This is a recursion, but it doesn't
1102 reallocate domain->conversions because we pass
1103 encoding = NULL or convert = 0, respectively. */
1105 # ifdef IN_LIBGLOCALE
1106 _nl_find_msg (domain_file
, domainbinding
, NULL
, "",
1109 _nl_find_msg (domain_file
, domainbinding
, "", 0, &nullentrylen
);
1112 /* Resource problems are fatal. If we continue onwards we will
1113 only attempt to calloc a new conv_tab and fail later. */
1114 if (__builtin_expect (nullentry
== (char *) -1, 0))
1117 if (nullentry
!= NULL
)
1119 const char *charsetstr
;
1121 charsetstr
= strstr (nullentry
, "charset=");
1122 if (charsetstr
!= NULL
)
1126 const char *outcharset
;
1128 charsetstr
+= strlen ("charset=");
1129 len
= strcspn (charsetstr
, " \t\n");
1131 charset
= (char *) alloca (len
+ 1);
1132 # if defined _LIBC || HAVE_MEMPCPY
1133 *((char *) mempcpy (charset
, charsetstr
, len
)) = '\0';
1135 memcpy (charset
, charsetstr
, len
);
1136 charset
[len
] = '\0';
1139 outcharset
= encoding
;
1142 /* We always want to use transliteration. */
1143 outcharset
= norm_add_slashes (outcharset
, "TRANSLIT");
1144 charset
= norm_add_slashes (charset
, "");
1145 int r
= __gconv_open (outcharset
, charset
, &convd
->conv
,
1146 GCONV_AVOID_NOCONV
);
1147 if (__builtin_expect (r
!= __GCONV_OK
, 0))
1149 /* If the output encoding is the same there is
1150 nothing to do. Otherwise do not use the
1151 translation at all. */
1152 if (__builtin_expect (r
!= __GCONV_NULCONV
, 1))
1154 gl_rwlock_unlock (domain
->conversions_lock
);
1155 free ((char *) encoding
);
1159 convd
->conv
= (__gconv_t
) -1;
1163 /* When using GNU libc >= 2.2 or GNU libiconv >= 1.5,
1164 we want to use transliteration. */
1165 # if (((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2) || __GLIBC__ > 2) \
1166 && !defined __UCLIBC__) \
1167 || _LIBICONV_VERSION >= 0x0105
1168 if (strchr (outcharset
, '/') == NULL
)
1172 len
= strlen (outcharset
);
1173 tmp
= (char *) alloca (len
+ 10 + 1);
1174 memcpy (tmp
, outcharset
, len
);
1175 memcpy (tmp
+ len
, "//TRANSLIT", 10 + 1);
1178 convd
->conv
= iconv_open (outcharset
, charset
);
1184 convd
->conv
= iconv_open (outcharset
, charset
);
1192 convd
->conv_tab
= NULL
;
1193 /* Here domain->conversions is still == new_conversions. */
1194 domain
->nconversions
++;
1198 gl_rwlock_unlock (domain
->conversions_lock
);
1203 convd
->conv
!= (__gconv_t
) -1
1206 convd
->conv
!= (iconv_t
) -1
1211 /* We are supposed to do a conversion. First allocate an
1212 appropriate table with the same structure as the table
1213 of translations in the file, where we can put the pointers
1214 to the converted strings in.
1215 There is a slight complication with plural entries. They
1216 are represented by consecutive NUL terminated strings. We
1217 handle this case by converting RESULTLEN bytes, including
1220 /* This lock primarily protects the memory management variables
1221 freemem, freemem_size. It also protects write accesses to
1222 convd->conv_tab. It's not worth using a separate lock (such
1223 as domain->conversions_lock) for this purpose, because when
1224 modifying convd->conv_tab, we also need to lock freemem,
1225 freemem_size for most of the time. */
1226 __libc_lock_define_initialized (static, lock
)
1228 if (__builtin_expect (convd
->conv_tab
== NULL
, 0))
1230 __libc_lock_lock (lock
);
1231 if (convd
->conv_tab
== NULL
)
1234 (char **) calloc (nstrings
+ domain
->n_sysdep_strings
,
1236 if (convd
->conv_tab
!= NULL
)
1237 goto not_translated_yet
;
1238 /* Mark that we didn't succeed allocating a table. */
1239 convd
->conv_tab
= (char **) -1;
1241 __libc_lock_unlock (lock
);
1244 if (__builtin_expect (convd
->conv_tab
== (char **) -1, 0))
1245 /* Nothing we can do, no more memory. We cannot use the
1246 translation because it might be encoded incorrectly. */
1249 if (convd
->conv_tab
[act
] == NULL
)
1251 /* We haven't used this string so far, so it is not
1252 translated yet. Do this now. */
1253 /* We use a bit more efficient memory handling.
1254 We allocate always larger blocks which get used over
1255 time. This is faster than many small allocations. */
1256 # define INITIAL_BLOCK_SIZE 4080
1257 static unsigned char *freemem
;
1258 static size_t freemem_size
;
1260 const unsigned char *inbuf
;
1261 unsigned char *outbuf
;
1264 transmem_block_t
*transmem_list
;
1267 __libc_lock_lock (lock
);
1270 inbuf
= (const unsigned char *) result
;
1271 outbuf
= freemem
+ sizeof (size_t);
1273 transmem_list
= NULL
;
1279 transmem_block_t
*newmem
;
1281 size_t non_reversible
;
1284 if (freemem_size
< sizeof (size_t))
1285 goto resize_freemem
;
1287 res
= __gconv (convd
->conv
,
1288 &inbuf
, inbuf
+ resultlen
,
1290 outbuf
+ freemem_size
- sizeof (size_t),
1293 if (res
== __GCONV_OK
|| res
== __GCONV_EMPTY_INPUT
)
1296 if (res
!= __GCONV_FULL_OUTPUT
)
1298 /* We should not use the translation at all, it
1299 is incorrectly encoded. */
1300 __libc_lock_unlock (lock
);
1304 inbuf
= (const unsigned char *) result
;
1307 const char *inptr
= (const char *) inbuf
;
1308 size_t inleft
= resultlen
;
1309 char *outptr
= (char *) outbuf
;
1312 if (freemem_size
< sizeof (size_t))
1313 goto resize_freemem
;
1315 outleft
= freemem_size
- sizeof (size_t);
1316 if (iconv (convd
->conv
,
1317 (ICONV_CONST
char **) &inptr
, &inleft
,
1321 outbuf
= (unsigned char *) outptr
;
1326 __libc_lock_unlock (lock
);
1333 /* We must allocate a new buffer or resize the old one. */
1334 if (malloc_count
> 0)
1337 freemem_size
= malloc_count
* INITIAL_BLOCK_SIZE
;
1338 newmem
= (transmem_block_t
*) realloc (transmem_list
,
1342 transmem_list
= newmem
;
1345 struct transmem_list
*old
= transmem_list
;
1347 transmem_list
= transmem_list
->next
;
1355 freemem_size
= INITIAL_BLOCK_SIZE
;
1356 newmem
= (transmem_block_t
*) malloc (freemem_size
);
1360 /* Add the block to the list of blocks we have to free
1362 newmem
->next
= transmem_list
;
1363 transmem_list
= newmem
;
1365 /* Fall through and return -1. */
1368 if (__builtin_expect (newmem
== NULL
, 0))
1372 __libc_lock_unlock (lock
);
1377 freemem
= (unsigned char *) newmem
->data
;
1378 freemem_size
-= offsetof (struct transmem_list
, data
);
1380 transmem_list
= newmem
;
1384 outbuf
= freemem
+ sizeof (size_t);
1387 /* We have now in our buffer a converted string. Put this
1388 into the table of conversions. */
1389 *(size_t *) freemem
= outbuf
- freemem
- sizeof (size_t);
1390 convd
->conv_tab
[act
] = (char *) freemem
;
1391 /* Shrink freemem, but keep it aligned. */
1392 freemem_size
-= outbuf
- freemem
;
1394 freemem
+= freemem_size
& (alignof (size_t) - 1);
1395 freemem_size
= freemem_size
& ~ (alignof (size_t) - 1);
1397 __libc_lock_unlock (lock
);
1400 /* Now convd->conv_tab[act] contains the translation of all
1401 the plural variants. */
1402 result
= convd
->conv_tab
[act
] + sizeof (size_t);
1403 resultlen
= *(size_t *) convd
->conv_tab
[act
];
1407 /* The result string is converted. */
1409 #endif /* _LIBC || HAVE_ICONV */
1411 *lengthp
= resultlen
;
1416 /* Look up a plural variant. */
1419 plural_lookup (struct loaded_l10nfile
*domain
, unsigned long int n
,
1420 const char *translation
, size_t translation_len
)
1422 struct loaded_domain
*domaindata
= (struct loaded_domain
*) domain
->data
;
1423 unsigned long int index
;
1426 index
= plural_eval (domaindata
->plural
, n
);
1427 if (index
>= domaindata
->nplurals
)
1428 /* This should never happen. It means the plural expression and the
1429 given maximum value do not match. */
1432 /* Skip INDEX strings at TRANSLATION. */
1437 p
= __rawmemchr (p
, '\0');
1439 p
= strchr (p
, '\0');
1441 /* And skip over the NUL byte. */
1444 if (p
>= translation
+ translation_len
)
1445 /* This should never happen. It means the plural expression
1446 evaluated to a value larger than the number of variants
1447 available for MSGID1. */
1448 return (char *) translation
;
1454 /* Return string representation of locale CATEGORY. */
1457 category_to_name (int category
)
1465 retval
= "LC_COLLATE";
1470 retval
= "LC_CTYPE";
1475 retval
= "LC_MONETARY";
1480 retval
= "LC_NUMERIC";
1490 retval
= "LC_MESSAGES";
1495 retval
= "LC_RESPONSE";
1500 /* This might not make sense but is perhaps better than any other
1506 /* If you have a better idea for a default value let me know. */
1514 /* Guess value of current locale from value of the environment variables
1515 or system-dependent defaults. */
1518 #ifdef IN_LIBGLOCALE
1519 guess_category_value (int category
, const char *categoryname
,
1523 guess_category_value (int category
, const char *categoryname
)
1526 const char *language
;
1527 #ifndef IN_LIBGLOCALE
1530 const char *language_default
;
1531 int locale_defaulted
;
1535 /* We use the settings in the following order:
1536 1. The value of the environment variable 'LANGUAGE'. This is a GNU
1537 extension. Its value can be a colon-separated list of locale names.
1538 2. The value of the environment variable 'LC_ALL', 'LC_xxx', or 'LANG'.
1539 More precisely, the first among these that is set to a non-empty value.
1540 This is how POSIX specifies it. The value is a single locale name.
1541 3. A system-dependent preference list of languages. Its value can be a
1542 colon-separated list of locale names.
1543 4. A system-dependent default locale name.
1545 - System-dependent settings can be overridden by environment variables.
1546 - If the system provides both a list of languages and a default locale,
1547 the former is used. */
1549 #ifndef IN_LIBGLOCALE
1550 /* Fetch the locale name, through the POSIX method of looking to `LC_ALL',
1551 `LC_xxx', and `LANG'. On some systems this can be done by the
1552 `setlocale' function itself. */
1554 locale
= __current_locale_name (category
);
1556 locale_defaulted
= 0;
1558 locale
= _nl_locale_name_thread_unsafe (category
, categoryname
);
1562 locale
= _nl_locale_name_posix (category
, categoryname
);
1565 locale
= _nl_locale_name_default ();
1566 locale_defaulted
= 1;
1572 /* Ignore LANGUAGE and its system-dependent analogon if the locale is set
1574 1. "C" locale usually uses the ASCII encoding, and most international
1575 messages use non-ASCII characters. These characters get displayed
1576 as question marks (if using glibc's iconv()) or as invalid 8-bit
1577 characters (because other iconv()s refuse to convert most non-ASCII
1578 characters to ASCII). In any case, the output is ugly.
1579 2. The precise output of some programs in the "C" locale is specified
1580 by POSIX and should not depend on environment variables like
1581 "LANGUAGE" or system-dependent information. We allow such programs
1582 to use gettext(). */
1583 if (strcmp (locale
, "C") == 0)
1586 /* The highest priority value is the value of the 'LANGUAGE' environment
1588 language
= getenv ("LANGUAGE");
1589 if (language
!= NULL
&& language
[0] != '\0')
1591 #if !defined IN_LIBGLOCALE && !defined _LIBC
1592 /* The next priority value is the locale name, if not defaulted. */
1593 if (locale_defaulted
)
1595 /* The next priority value is the default language preferences list. */
1596 language_default
= _nl_language_preferences_default ();
1597 if (language_default
!= NULL
)
1598 return language_default
;
1600 /* The least priority value is the locale name, if defaulted. */
1605 #if (defined _LIBC || HAVE_ICONV) && !defined IN_LIBGLOCALE
1606 /* Returns the output charset. */
1609 get_output_charset (struct binding
*domainbinding
)
1611 /* The output charset should normally be determined by the locale. But
1612 sometimes the locale is not used or not correctly set up, so we provide
1613 a possibility for the user to override this: the OUTPUT_CHARSET
1614 environment variable. Moreover, the value specified through
1615 bind_textdomain_codeset overrides both. */
1616 if (domainbinding
!= NULL
&& domainbinding
->codeset
!= NULL
)
1617 return domainbinding
->codeset
;
1620 /* For speed reasons, we look at the value of OUTPUT_CHARSET only
1621 once. This is a user variable that is not supposed to change
1622 during a program run. */
1623 static char *output_charset_cache
;
1624 static int output_charset_cached
;
1626 if (!output_charset_cached
)
1628 const char *value
= getenv ("OUTPUT_CHARSET");
1630 if (value
!= NULL
&& value
[0] != '\0')
1632 size_t len
= strlen (value
) + 1;
1633 char *value_copy
= (char *) malloc (len
);
1635 if (value_copy
!= NULL
)
1636 memcpy (value_copy
, value
, len
);
1637 output_charset_cache
= value_copy
;
1639 output_charset_cached
= 1;
1642 if (output_charset_cache
!= NULL
)
1643 return output_charset_cache
;
1647 return _NL_CURRENT (LC_CTYPE
, CODESET
);
1650 return locale_charset ();
1658 /* @@ begin of epilog @@ */
1660 /* We don't want libintl.a to depend on any other library. So we
1661 avoid the non-standard function stpcpy. In GNU C Library this
1662 function is available, though. Also allow the symbol HAVE_STPCPY
1664 #if !_LIBC && !HAVE_STPCPY
1666 stpcpy (char *dest
, const char *src
)
1668 while ((*dest
++ = *src
++) != '\0')
1674 #if !_LIBC && !HAVE_MEMPCPY
1676 mempcpy (void *dest
, const void *src
, size_t n
)
1678 return (void *) ((char *) memcpy (dest
, src
, n
) + n
);
1682 #if !_LIBC && !HAVE_TSEARCH
1683 # include "tsearch.c"
1688 /* If we want to free all resources we have to do some work at
1690 libc_freeres_fn (free_mem
)
1694 while (_nl_domain_bindings
!= NULL
)
1696 struct binding
*oldp
= _nl_domain_bindings
;
1697 _nl_domain_bindings
= _nl_domain_bindings
->next
;
1698 if (oldp
->dirname
!= _nl_default_dirname
)
1699 /* Yes, this is a pointer comparison. */
1700 free (oldp
->dirname
);
1701 free (oldp
->codeset
);
1705 if (_nl_current_default_domain
!= _nl_default_default_domain
)
1706 /* Yes, again a pointer comparison. */
1707 free ((char *) _nl_current_default_domain
);
1709 /* Remove the search tree with the known translations. */
1710 __tdestroy (root
, free
);
1713 while (transmem_list
!= NULL
)
1715 old
= transmem_list
;
1716 transmem_list
= transmem_list
->next
;