1 /* Implementation of the internal dcigettext function.
2 Copyright (C) 1995-1999, 2000-2006 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>
93 #if !defined _LIBC && HAVE_NL_LOCALE_NAME
94 # include <langinfo.h>
98 #include "plural-exp.h"
100 # include <libintl.h>
102 # ifdef IN_LIBGLOCALE
103 # include <libintl.h>
105 # include "libgnuintl.h"
107 #include "hash-string.h"
109 /* Handle multi-threaded applications. */
111 # include <bits/libc-lock.h>
112 # define gl_rwlock_define_initialized __libc_rwlock_define_initialized
113 # define gl_rwlock_rdlock __libc_rwlock_rdlock
114 # define gl_rwlock_wrlock __libc_rwlock_wrlock
115 # define gl_rwlock_unlock __libc_rwlock_unlock
120 /* Alignment of types. */
121 #if defined __GNUC__ && __GNUC__ >= 2
122 # define alignof(TYPE) __alignof__ (TYPE)
124 # define alignof(TYPE) \
125 ((int) &((struct { char dummy1; TYPE dummy2; } *) 0)->dummy2)
128 /* The internal variables in the standalone libintl.a must have different
129 names than the internal variables in GNU libc, otherwise programs
130 using libintl.a cannot be linked statically. */
132 # define _nl_default_default_domain libintl_nl_default_default_domain
133 # define _nl_current_default_domain libintl_nl_current_default_domain
134 # define _nl_default_dirname libintl_nl_default_dirname
135 # define _nl_domain_bindings libintl_nl_domain_bindings
138 /* Some compilers, like SunOS4 cc, don't have offsetof in <stddef.h>. */
140 # define offsetof(type,ident) ((size_t)&(((type*)0)->ident))
143 /* @@ end of prolog @@ */
146 /* Rename the non ANSI C functions. This is required by the standard
147 because some ANSI C functions will require linking with this object
148 file and the name space must not be polluted. */
149 # define getcwd __getcwd
151 # define stpcpy __stpcpy
153 # define tfind __tfind
155 # if !defined HAVE_GETCWD
157 # define getcwd(buf, max) getwd (buf)
160 # define getcwd(buf, max) (getcwd) (buf, max, 0)
166 static char *stpcpy (char *dest
, const char *src
);
168 # ifndef HAVE_MEMPCPY
169 static void *mempcpy (void *dest
, const void *src
, size_t n
);
173 /* Amount to increase buffer size by in each try. */
176 /* The following is from pathmax.h. */
177 /* Non-POSIX BSD systems might have gcc's limits.h, which doesn't define
178 PATH_MAX but might cause redefinition warnings when sys/param.h is
179 later included (as on MORE/BSD 4.3). */
180 #if defined _POSIX_VERSION || (defined HAVE_LIMITS_H && !defined __GNUC__)
184 #ifndef _POSIX_PATH_MAX
185 # define _POSIX_PATH_MAX 255
188 #if !defined PATH_MAX && defined _PC_PATH_MAX
189 # define PATH_MAX (pathconf ("/", _PC_PATH_MAX) < 1 ? 1024 : pathconf ("/", _PC_PATH_MAX))
192 /* Don't include sys/param.h if it already has been. */
193 #if defined HAVE_SYS_PARAM_H && !defined PATH_MAX && !defined MAXPATHLEN
194 # include <sys/param.h>
197 #if !defined PATH_MAX && defined MAXPATHLEN
198 # define PATH_MAX MAXPATHLEN
202 # define PATH_MAX _POSIX_PATH_MAX
206 ISSLASH(C) tests whether C is a directory separator character.
207 IS_ABSOLUTE_PATH(P) tests whether P is an absolute path. If it is not,
208 it may be concatenated to a directory pathname.
209 IS_PATH_WITH_DIR(P) tests whether P contains a directory specification.
211 #if defined _WIN32 || defined __WIN32__ || defined __CYGWIN__ || defined __EMX__ || defined __DJGPP__
212 /* Win32, Cygwin, OS/2, DOS */
213 # define ISSLASH(C) ((C) == '/' || (C) == '\\')
214 # define HAS_DEVICE(P) \
215 ((((P)[0] >= 'A' && (P)[0] <= 'Z') || ((P)[0] >= 'a' && (P)[0] <= 'z')) \
217 # define IS_ABSOLUTE_PATH(P) (ISSLASH ((P)[0]) || HAS_DEVICE (P))
218 # define IS_PATH_WITH_DIR(P) \
219 (strchr (P, '/') != NULL || strchr (P, '\\') != NULL || HAS_DEVICE (P))
222 # define ISSLASH(C) ((C) == '/')
223 # define IS_ABSOLUTE_PATH(P) ISSLASH ((P)[0])
224 # define IS_PATH_WITH_DIR(P) (strchr (P, '/') != NULL)
227 /* Whether to support different locales in different threads. */
228 #if defined _LIBC || HAVE_NL_LOCALE_NAME || (HAVE_STRUCT___LOCALE_STRUCT___NAMES && defined USE_IN_GETTEXT_TESTS) || defined IN_LIBGLOCALE
229 # define HAVE_PER_THREAD_LOCALE
232 /* This is the type used for the search tree where known translations
234 struct known_translation_t
236 /* Domain in which to search. */
237 const char *domainname
;
242 #ifdef HAVE_PER_THREAD_LOCALE
243 /* Name of the relevant locale category, or "" for the global locale. */
244 const char *localename
;
248 /* The character encoding. */
249 const char *encoding
;
252 /* State of the catalog counter at the point the string was found. */
255 /* Catalog where the string was found. */
256 struct loaded_l10nfile
*domain
;
258 /* And finally the translation. */
259 const char *translation
;
260 size_t translation_length
;
262 /* Pointer to the string in question. */
266 /* Root of the search tree with known translations. We can use this
267 only if the system provides the `tsearch' function family. */
268 #if defined HAVE_TSEARCH || defined _LIBC
271 gl_rwlock_define_initialized (static, tree_lock
)
276 # define tsearch __tsearch
279 /* Function to compare two entries in the table of known translations. */
281 transcmp (const void *p1
, const void *p2
)
283 const struct known_translation_t
*s1
;
284 const struct known_translation_t
*s2
;
287 s1
= (const struct known_translation_t
*) p1
;
288 s2
= (const struct known_translation_t
*) p2
;
290 result
= strcmp (s1
->msgid
, s2
->msgid
);
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
;
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 #if defined HAVE_TSEARCH || defined _LIBC
505 struct known_translation_t
*search
;
506 struct known_translation_t
**foundp
= NULL
;
508 # if defined HAVE_PER_THREAD_LOCALE && !defined IN_LIBGLOCALE
509 const char *localename
;
512 size_t domainname_len
;
514 /* If no real MSGID is given return NULL. */
519 if (category
< 0 || category
>= __LC_LAST
|| category
== LC_ALL
)
523 /* Use the Germanic plural rule. */
524 : n
== 1 ? (char *) msgid1
: (char *) msgid2
);
527 gl_rwlock_rdlock (_nl_state_lock
);
529 /* If DOMAINNAME is NULL, we are interested in the default domain. If
530 CATEGORY is not LC_MESSAGES this might not make much sense but the
531 definition left this undefined. */
532 if (domainname
== NULL
)
533 domainname
= _nl_current_default_domain
;
535 /* OS/2 specific: backward compatibility with older libintl versions */
536 #ifdef LC_MESSAGES_COMPAT
537 if (category
== LC_MESSAGES_COMPAT
)
538 category
= LC_MESSAGES
;
541 #if defined HAVE_TSEARCH || defined _LIBC
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
;
580 /* Since tfind/tsearch manage a balanced tree, concurrent tfind and
581 tsearch calls can be fatal. */
582 gl_rwlock_rdlock (tree_lock
);
584 foundp
= (struct known_translation_t
**) tfind (search
, &root
, transcmp
);
586 gl_rwlock_unlock (tree_lock
);
589 if (foundp
!= NULL
&& (*foundp
)->counter
== _nl_msg_cat_cntr
)
591 /* Now deal with plural. */
593 retval
= plural_lookup ((*foundp
)->domain
, n
, (*foundp
)->translation
,
594 (*foundp
)->translation_length
);
596 retval
= (char *) (*foundp
)->translation
;
598 gl_rwlock_unlock (_nl_state_lock
);
603 /* Preserve the `errno' value. */
606 /* See whether this is a SUID binary or not. */
609 /* First find matching binding. */
611 /* We can use a trivial binding, since _nl_find_msg will ignore it anyway,
612 and _nl_load_domain and _nl_find_domain just pass it through. */
614 dirname
= bindtextdomain (domainname
, NULL
);
616 for (binding
= _nl_domain_bindings
; binding
!= NULL
; binding
= binding
->next
)
618 int compare
= strcmp (domainname
, binding
->domainname
);
624 /* It is not in the list. */
631 dirname
= _nl_default_dirname
;
634 dirname
= binding
->dirname
;
636 if (!IS_ABSOLUTE_PATH (dirname
))
638 /* We have a relative path. Make it absolute now. */
639 size_t dirname_len
= strlen (dirname
) + 1;
641 char *resolved_dirname
;
644 path_max
= (unsigned int) PATH_MAX
;
645 path_max
+= 2; /* The getcwd docs say to do this. */
649 resolved_dirname
= (char *) alloca (path_max
+ dirname_len
);
650 ADD_BLOCK (block_list
, tmp_dirname
);
653 ret
= getcwd (resolved_dirname
, path_max
);
654 if (ret
!= NULL
|| errno
!= ERANGE
)
657 path_max
+= path_max
/ 2;
658 path_max
+= PATH_INCR
;
662 /* We cannot get the current working directory. Don't signal an
663 error but simply return the default string. */
664 goto return_untranslated
;
666 stpcpy (stpcpy (strchr (resolved_dirname
, '\0'), "/"), dirname
);
667 dirname
= resolved_dirname
;
669 #ifndef IN_LIBGLOCALE
673 /* Now determine the symbolic name of CATEGORY and its value. */
674 categoryname
= category_to_name (category
);
676 categoryvalue
= guess_category_value (category
, categoryname
, localename
);
678 categoryvalue
= guess_category_value (category
, categoryname
);
681 domainname_len
= strlen (domainname
);
682 xdomainname
= (char *) alloca (strlen (categoryname
)
683 + domainname_len
+ 5);
684 ADD_BLOCK (block_list
, xdomainname
);
686 stpcpy (mempcpy (stpcpy (stpcpy (xdomainname
, categoryname
), "/"),
687 domainname
, domainname_len
),
690 /* Creating working area. */
691 single_locale
= (char *) alloca (strlen (categoryvalue
) + 1);
692 ADD_BLOCK (block_list
, single_locale
);
695 /* Search for the given string. This is a loop because we perhaps
696 got an ordered list of languages to consider for the translation. */
699 /* Make CATEGORYVALUE point to the next element of the list. */
700 while (categoryvalue
[0] != '\0' && categoryvalue
[0] == ':')
702 if (categoryvalue
[0] == '\0')
704 /* The whole contents of CATEGORYVALUE has been searched but
705 no valid entry has been found. We solve this situation
706 by implicitly appending a "C" entry, i.e. no translation
708 single_locale
[0] = 'C';
709 single_locale
[1] = '\0';
713 char *cp
= single_locale
;
714 while (categoryvalue
[0] != '\0' && categoryvalue
[0] != ':')
715 *cp
++ = *categoryvalue
++;
718 /* When this is a SUID binary we must not allow accessing files
719 outside the dedicated directories. */
720 if (ENABLE_SECURE
&& IS_PATH_WITH_DIR (single_locale
))
721 /* Ingore this entry. */
725 /* If the current locale value is C (or POSIX) we don't load a
726 domain. Return the MSGID. */
727 if (strcmp (single_locale
, "C") == 0
728 || strcmp (single_locale
, "POSIX") == 0)
731 /* Find structure describing the message catalog matching the
732 DOMAINNAME and CATEGORY. */
733 domain
= _nl_find_domain (dirname
, single_locale
, xdomainname
, binding
);
737 #if defined IN_LIBGLOCALE
738 retval
= _nl_find_msg (domain
, binding
, encoding
, msgid1
, &retlen
);
740 retval
= _nl_find_msg (domain
, binding
, msgid1
, 1, &retlen
);
747 for (cnt
= 0; domain
->successor
[cnt
] != NULL
; ++cnt
)
749 #if defined IN_LIBGLOCALE
750 retval
= _nl_find_msg (domain
->successor
[cnt
], binding
,
751 encoding
, msgid1
, &retlen
);
753 retval
= _nl_find_msg (domain
->successor
[cnt
], binding
,
759 domain
= domain
->successor
[cnt
];
765 /* Returning -1 means that some resource problem exists
766 (likely memory) and that the strings could not be
767 converted. Return the original strings. */
768 if (__builtin_expect (retval
== (char *) -1, 0))
773 /* Found the translation of MSGID1 in domain DOMAIN:
774 starting at RETVAL, RETLEN bytes. */
775 FREE_BLOCKS (block_list
);
776 #if defined HAVE_TSEARCH || defined _LIBC
779 /* Create a new entry and add it to the search tree. */
781 struct known_translation_t
*newp
;
783 size
= offsetof (struct known_translation_t
, msgid
)
784 + msgid_len
+ domainname_len
+ 1;
785 # ifdef HAVE_PER_THREAD_LOCALE
786 size
+= strlen (localename
) + 1;
788 newp
= (struct known_translation_t
*) malloc (size
);
791 char *new_domainname
;
792 # ifdef HAVE_PER_THREAD_LOCALE
793 char *new_localename
;
796 new_domainname
= mempcpy (newp
->msgid
, msgid1
, msgid_len
);
797 memcpy (new_domainname
, domainname
, domainname_len
+ 1);
798 # ifdef HAVE_PER_THREAD_LOCALE
799 new_localename
= new_domainname
+ domainname_len
+ 1;
800 strcpy (new_localename
, localename
);
802 newp
->domainname
= new_domainname
;
803 newp
->category
= category
;
804 # ifdef HAVE_PER_THREAD_LOCALE
805 newp
->localename
= new_localename
;
807 # ifdef IN_LIBGLOCALE
808 newp
->encoding
= encoding
;
810 newp
->counter
= _nl_msg_cat_cntr
;
811 newp
->domain
= domain
;
812 newp
->translation
= retval
;
813 newp
->translation_length
= retlen
;
815 gl_rwlock_wrlock (tree_lock
);
817 /* Insert the entry in the search tree. */
818 foundp
= (struct known_translation_t
**)
819 tsearch (newp
, &root
, transcmp
);
821 gl_rwlock_unlock (tree_lock
);
824 || __builtin_expect (*foundp
!= newp
, 0))
825 /* The insert failed. */
831 /* We can update the existing entry. */
832 (*foundp
)->counter
= _nl_msg_cat_cntr
;
833 (*foundp
)->domain
= domain
;
834 (*foundp
)->translation
= retval
;
835 (*foundp
)->translation_length
= retlen
;
838 __set_errno (saved_errno
);
840 /* Now deal with plural. */
842 retval
= plural_lookup (domain
, n
, retval
, retlen
);
844 gl_rwlock_unlock (_nl_state_lock
);
851 /* Return the untranslated MSGID. */
852 FREE_BLOCKS (block_list
);
853 gl_rwlock_unlock (_nl_state_lock
);
857 extern void _nl_log_untranslated (const char *logfilename
,
858 const char *domainname
,
859 const char *msgid1
, const char *msgid2
,
861 const char *logfilename
= getenv ("GETTEXT_LOG_UNTRANSLATED");
863 if (logfilename
!= NULL
&& logfilename
[0] != '\0')
864 _nl_log_untranslated (logfilename
, domainname
, msgid1
, msgid2
, plural
);
867 __set_errno (saved_errno
);
870 /* Use the Germanic plural rule. */
871 : n
== 1 ? (char *) msgid1
: (char *) msgid2
);
875 /* Look up the translation of msgid within DOMAIN_FILE and DOMAINBINDING.
876 Return it if found. Return NULL if not found or in case of a conversion
877 failure (problem in the particular message catalog). Return (char *) -1
878 in case of a memory allocation failure during conversion (only if
879 ENCODING != NULL resp. CONVERT == true). */
883 _nl_find_msg (struct loaded_l10nfile
*domain_file
,
884 struct binding
*domainbinding
, const char *encoding
,
888 _nl_find_msg (struct loaded_l10nfile
*domain_file
,
889 struct binding
*domainbinding
,
890 const char *msgid
, int convert
,
894 struct loaded_domain
*domain
;
900 if (domain_file
->decided
<= 0)
901 _nl_load_domain (domain_file
, domainbinding
);
903 if (domain_file
->data
== NULL
)
906 domain
= (struct loaded_domain
*) domain_file
->data
;
908 nstrings
= domain
->nstrings
;
910 /* Locate the MSGID and its translation. */
911 if (domain
->hash_tab
!= NULL
)
913 /* Use the hashing table. */
914 nls_uint32 len
= strlen (msgid
);
915 nls_uint32 hash_val
= __hash_string (msgid
);
916 nls_uint32 idx
= hash_val
% domain
->hash_size
;
917 nls_uint32 incr
= 1 + (hash_val
% (domain
->hash_size
- 2));
922 W (domain
->must_swap_hash_tab
, domain
->hash_tab
[idx
]);
925 /* Hash table entry is empty. */
930 /* Compare msgid with the original string at index nstr.
931 We compare the lengths with >=, not ==, because plural entries
932 are represented by strings with an embedded NUL. */
934 ? W (domain
->must_swap
, domain
->orig_tab
[nstr
].length
) >= len
936 domain
->data
+ W (domain
->must_swap
,
937 domain
->orig_tab
[nstr
].offset
))
939 : domain
->orig_sysdep_tab
[nstr
- nstrings
].length
> len
941 domain
->orig_sysdep_tab
[nstr
- nstrings
].pointer
)
948 if (idx
>= domain
->hash_size
- incr
)
949 idx
-= domain
->hash_size
- incr
;
957 /* Try the default method: binary search in the sorted array of
967 act
= (bottom
+ top
) / 2;
968 cmp_val
= strcmp (msgid
, (domain
->data
969 + W (domain
->must_swap
,
970 domain
->orig_tab
[act
].offset
)));
973 else if (cmp_val
> 0)
978 /* No translation was found. */
983 /* The translation was found at index ACT. If we have to convert the
984 string to use a different character set, this is the time. */
988 (domain
->data
+ W (domain
->must_swap
, domain
->trans_tab
[act
].offset
));
989 resultlen
= W (domain
->must_swap
, domain
->trans_tab
[act
].length
) + 1;
993 result
= (char *) domain
->trans_sysdep_tab
[act
- nstrings
].pointer
;
994 resultlen
= domain
->trans_sysdep_tab
[act
- nstrings
].length
;
997 #if defined _LIBC || HAVE_ICONV
998 # ifdef IN_LIBGLOCALE
999 if (encoding
!= NULL
)
1004 /* We are supposed to do a conversion. */
1005 # ifndef IN_LIBGLOCALE
1006 const char *encoding
= get_output_charset (domainbinding
);
1009 /* Search whether a table with converted translations for this
1010 encoding has already been allocated. */
1011 size_t nconversions
= domain
->nconversions
;
1012 struct converted_domain
*convd
= NULL
;
1015 for (i
= nconversions
; i
> 0; )
1018 if (strcmp (domain
->conversions
[i
].encoding
, encoding
) == 0)
1020 convd
= &domain
->conversions
[i
];
1027 /* Allocate a table for the converted translations for this
1029 struct converted_domain
*new_conversions
=
1030 (struct converted_domain
*)
1031 (domain
->conversions
!= NULL
1032 ? realloc (domain
->conversions
,
1033 (nconversions
+ 1) * sizeof (struct converted_domain
))
1034 : malloc ((nconversions
+ 1) * sizeof (struct converted_domain
)));
1036 if (__builtin_expect (new_conversions
== NULL
, 0))
1037 /* Nothing we can do, no more memory. We cannot use the
1038 translation because it might be encoded incorrectly. */
1041 domain
->conversions
= new_conversions
;
1043 /* Copy the 'encoding' string to permanent storage. */
1044 encoding
= strdup (encoding
);
1045 if (__builtin_expect (encoding
== NULL
, 0))
1046 /* Nothing we can do, no more memory. We cannot use the
1047 translation because it might be encoded incorrectly. */
1050 convd
= &new_conversions
[nconversions
];
1051 convd
->encoding
= encoding
;
1053 /* Find out about the character set the file is encoded with.
1054 This can be found (in textual form) in the entry "". If this
1055 entry does not exist or if this does not contain the 'charset='
1056 information, we will assume the charset matches the one the
1057 current locale and we don't have to perform any conversion. */
1059 convd
->conv
= (__gconv_t
) -1;
1062 convd
->conv
= (iconv_t
) -1;
1067 size_t nullentrylen
;
1069 /* Get the header entry. This is a recursion, but it doesn't
1070 reallocate domain->conversions because we pass
1071 encoding = NULL or convert = 0, respectively. */
1073 # ifdef IN_LIBGLOCALE
1074 _nl_find_msg (domain_file
, domainbinding
, NULL
, "",
1077 _nl_find_msg (domain_file
, domainbinding
, "", 0, &nullentrylen
);
1080 if (nullentry
!= NULL
)
1082 const char *charsetstr
;
1084 charsetstr
= strstr (nullentry
, "charset=");
1085 if (charsetstr
!= NULL
)
1089 const char *outcharset
;
1091 charsetstr
+= strlen ("charset=");
1092 len
= strcspn (charsetstr
, " \t\n");
1094 charset
= (char *) alloca (len
+ 1);
1095 # if defined _LIBC || HAVE_MEMPCPY
1096 *((char *) mempcpy (charset
, charsetstr
, len
)) = '\0';
1098 memcpy (charset
, charsetstr
, len
);
1099 charset
[len
] = '\0';
1102 outcharset
= encoding
;
1105 /* We always want to use transliteration. */
1106 outcharset
= norm_add_slashes (outcharset
, "TRANSLIT");
1107 charset
= norm_add_slashes (charset
, "");
1108 int r
= __gconv_open (outcharset
, charset
, &convd
->conv
,
1109 GCONV_AVOID_NOCONV
);
1110 if (__builtin_expect (r
!= __GCONV_OK
, 0))
1112 /* If the output encoding is the same there is
1113 nothing to do. Otherwise do not use the
1114 translation at all. */
1115 if (__builtin_expect (r
!= __GCONV_NOCONV
, 1))
1118 convd
->conv
= (__gconv_t
) -1;
1122 /* When using GNU libc >= 2.2 or GNU libiconv >= 1.5,
1123 we want to use transliteration. */
1124 # if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2) || __GLIBC__ > 2 \
1125 || _LIBICONV_VERSION >= 0x0105
1126 if (strchr (outcharset
, '/') == NULL
)
1130 len
= strlen (outcharset
);
1131 tmp
= (char *) alloca (len
+ 10 + 1);
1132 memcpy (tmp
, outcharset
, len
);
1133 memcpy (tmp
+ len
, "//TRANSLIT", 10 + 1);
1136 convd
->conv
= iconv_open (outcharset
, charset
);
1142 convd
->conv
= iconv_open (outcharset
, charset
);
1150 convd
->conv_tab
= NULL
;
1151 /* Here domain->conversions is still == new_conversions. */
1152 domain
->nconversions
++;
1157 convd
->conv
!= (__gconv_t
) -1
1160 convd
->conv
!= (iconv_t
) -1
1165 /* We are supposed to do a conversion. First allocate an
1166 appropriate table with the same structure as the table
1167 of translations in the file, where we can put the pointers
1168 to the converted strings in.
1169 There is a slight complication with plural entries. They
1170 are represented by consecutive NUL terminated strings. We
1171 handle this case by converting RESULTLEN bytes, including
1174 if (convd
->conv_tab
== NULL
1175 && ((convd
->conv_tab
=
1176 (char **) calloc (nstrings
+ domain
->n_sysdep_strings
,
1179 /* Mark that we didn't succeed allocating a table. */
1180 convd
->conv_tab
= (char **) -1;
1182 if (__builtin_expect (convd
->conv_tab
== (char **) -1, 0))
1183 /* Nothing we can do, no more memory. We cannot use the
1184 translation because it might be encoded incorrectly. */
1187 if (convd
->conv_tab
[act
] == NULL
)
1189 /* We haven't used this string so far, so it is not
1190 translated yet. Do this now. */
1191 /* We use a bit more efficient memory handling.
1192 We allocate always larger blocks which get used over
1193 time. This is faster than many small allocations. */
1194 __libc_lock_define_initialized (static, lock
)
1195 # define INITIAL_BLOCK_SIZE 4080
1196 static unsigned char *freemem
;
1197 static size_t freemem_size
;
1199 const unsigned char *inbuf
;
1200 unsigned char *outbuf
;
1203 transmem_block_t
*transmem_list
= NULL
;
1206 __libc_lock_lock (lock
);
1208 inbuf
= (const unsigned char *) result
;
1209 outbuf
= freemem
+ sizeof (size_t);
1214 transmem_block_t
*newmem
;
1216 size_t non_reversible
;
1219 if (freemem_size
< sizeof (size_t))
1220 goto resize_freemem
;
1222 res
= __gconv (convd
->conv
,
1223 &inbuf
, inbuf
+ resultlen
,
1225 outbuf
+ freemem_size
- sizeof (size_t),
1228 if (res
== __GCONV_OK
|| res
== __GCONV_EMPTY_INPUT
)
1231 if (res
!= __GCONV_FULL_OUTPUT
)
1233 /* We should not use the translation at all, it
1234 is incorrectly encoded. */
1235 __libc_lock_unlock (lock
);
1239 inbuf
= (const unsigned char *) result
;
1242 const char *inptr
= (const char *) inbuf
;
1243 size_t inleft
= resultlen
;
1244 char *outptr
= (char *) outbuf
;
1247 if (freemem_size
< sizeof (size_t))
1248 goto resize_freemem
;
1250 outleft
= freemem_size
- sizeof (size_t);
1251 if (iconv (convd
->conv
,
1252 (ICONV_CONST
char **) &inptr
, &inleft
,
1256 outbuf
= (unsigned char *) outptr
;
1261 __libc_lock_unlock (lock
);
1268 /* We must allocate a new buffer or resize the old one. */
1269 if (malloc_count
> 0)
1272 freemem_size
= malloc_count
* INITIAL_BLOCK_SIZE
;
1273 newmem
= (transmem_block_t
*) realloc (transmem_list
,
1277 transmem_list
= transmem_list
->next
;
1280 struct transmem_list
*old
= transmem_list
;
1282 transmem_list
= transmem_list
->next
;
1290 freemem_size
= INITIAL_BLOCK_SIZE
;
1291 newmem
= (transmem_block_t
*) malloc (freemem_size
);
1293 if (__builtin_expect (newmem
== NULL
, 0))
1297 __libc_lock_unlock (lock
);
1302 /* Add the block to the list of blocks we have to free
1304 newmem
->next
= transmem_list
;
1305 transmem_list
= newmem
;
1307 freemem
= (unsigned char *) newmem
->data
;
1308 freemem_size
-= offsetof (struct transmem_list
, data
);
1310 transmem_list
= newmem
;
1314 outbuf
= freemem
+ sizeof (size_t);
1317 /* We have now in our buffer a converted string. Put this
1318 into the table of conversions. */
1319 *(size_t *) freemem
= outbuf
- freemem
- sizeof (size_t);
1320 convd
->conv_tab
[act
] = (char *) freemem
;
1321 /* Shrink freemem, but keep it aligned. */
1322 freemem_size
-= outbuf
- freemem
;
1324 freemem
+= freemem_size
& (alignof (size_t) - 1);
1325 freemem_size
= freemem_size
& ~ (alignof (size_t) - 1);
1327 __libc_lock_unlock (lock
);
1330 /* Now convd->conv_tab[act] contains the translation of all
1331 the plural variants. */
1332 result
= convd
->conv_tab
[act
] + sizeof (size_t);
1333 resultlen
= *(size_t *) convd
->conv_tab
[act
];
1337 /* The result string is converted. */
1339 #endif /* _LIBC || HAVE_ICONV */
1341 *lengthp
= resultlen
;
1346 /* Look up a plural variant. */
1349 plural_lookup (struct loaded_l10nfile
*domain
, unsigned long int n
,
1350 const char *translation
, size_t translation_len
)
1352 struct loaded_domain
*domaindata
= (struct loaded_domain
*) domain
->data
;
1353 unsigned long int index
;
1356 index
= plural_eval (domaindata
->plural
, n
);
1357 if (index
>= domaindata
->nplurals
)
1358 /* This should never happen. It means the plural expression and the
1359 given maximum value do not match. */
1362 /* Skip INDEX strings at TRANSLATION. */
1367 p
= __rawmemchr (p
, '\0');
1369 p
= strchr (p
, '\0');
1371 /* And skip over the NUL byte. */
1374 if (p
>= translation
+ translation_len
)
1375 /* This should never happen. It means the plural expression
1376 evaluated to a value larger than the number of variants
1377 available for MSGID1. */
1378 return (char *) translation
;
1384 /* Return string representation of locale CATEGORY. */
1387 category_to_name (int category
)
1395 retval
= "LC_COLLATE";
1400 retval
= "LC_CTYPE";
1405 retval
= "LC_MONETARY";
1410 retval
= "LC_NUMERIC";
1420 retval
= "LC_MESSAGES";
1425 retval
= "LC_RESPONSE";
1430 /* This might not make sense but is perhaps better than any other
1436 /* If you have a better idea for a default value let me know. */
1444 /* Guess value of current locale from value of the environment variables
1445 or system-dependent defaults. */
1448 #ifdef IN_LIBGLOCALE
1449 guess_category_value (int category
, const char *categoryname
,
1453 guess_category_value (int category
, const char *categoryname
)
1456 const char *language
;
1457 #ifndef IN_LIBGLOCALE
1460 const char *language_default
;
1461 int locale_defaulted
;
1465 /* We use the settings in the following order:
1466 1. The value of the environment variable 'LANGUAGE'. This is a GNU
1467 extension. Its value can be a colon-separated list of locale names.
1468 2. The value of the environment variable 'LC_ALL', 'LC_xxx', or 'LANG'.
1469 More precisely, the first among these that is set to a non-empty value.
1470 This is how POSIX specifies it. The value is a single locale name.
1471 3. A system-dependent preference list of languages. Its value can be a
1472 colon-separated list of locale names.
1473 4. A system-dependent default locale name.
1475 - System-dependent settings can be overridden by environment variables.
1476 - If the system provides both a list of languages and a default locale,
1477 the former is used. */
1479 #ifndef IN_LIBGLOCALE
1480 /* Fetch the locale name, through the POSIX method of looking to `LC_ALL',
1481 `LC_xxx', and `LANG'. On some systems this can be done by the
1482 `setlocale' function itself. */
1484 locale
= __current_locale_name (category
);
1486 # if HAVE_STRUCT___LOCALE_STRUCT___NAMES && defined USE_IN_GETTEXT_TESTS
1487 /* The __names field is not public glibc API and must therefore not be used
1488 in code that is installed in public locations. */
1489 locale_t thread_locale
= uselocale (NULL
);
1490 if (thread_locale
!= LC_GLOBAL_LOCALE
)
1492 locale
= thread_locale
->__names
[category
];
1493 locale_defaulted
= 0;
1498 locale
= _nl_locale_name_posix (category
, categoryname
);
1499 locale_defaulted
= 0;
1502 locale
= _nl_locale_name_default ();
1503 locale_defaulted
= 1;
1509 /* Ignore LANGUAGE and its system-dependent analogon if the locale is set
1511 1. "C" locale usually uses the ASCII encoding, and most international
1512 messages use non-ASCII characters. These characters get displayed
1513 as question marks (if using glibc's iconv()) or as invalid 8-bit
1514 characters (because other iconv()s refuse to convert most non-ASCII
1515 characters to ASCII). In any case, the output is ugly.
1516 2. The precise output of some programs in the "C" locale is specified
1517 by POSIX and should not depend on environment variables like
1518 "LANGUAGE" or system-dependent information. We allow such programs
1519 to use gettext(). */
1520 if (strcmp (locale
, "C") == 0)
1523 /* The highest priority value is the value of the 'LANGUAGE' environment
1525 language
= getenv ("LANGUAGE");
1526 if (language
!= NULL
&& language
[0] != '\0')
1528 #if !defined IN_LIBGLOCALE && !defined _LIBC
1529 /* The next priority value is the locale name, if not defaulted. */
1530 if (locale_defaulted
)
1532 /* The next priority value is the default language preferences list. */
1533 language_default
= _nl_language_preferences_default ();
1534 if (language_default
!= NULL
)
1535 return language_default
;
1537 /* The least priority value is the locale name, if defaulted. */
1542 #if (defined _LIBC || HAVE_ICONV) && !defined IN_LIBGLOCALE
1543 /* Returns the output charset. */
1546 get_output_charset (struct binding
*domainbinding
)
1548 /* The output charset should normally be determined by the locale. But
1549 sometimes the locale is not used or not correctly set up, so we provide
1550 a possibility for the user to override this: the OUTPUT_CHARSET
1551 environment variable. Moreover, the value specified through
1552 bind_textdomain_codeset overrides both. */
1553 if (domainbinding
!= NULL
&& domainbinding
->codeset
!= NULL
)
1554 return domainbinding
->codeset
;
1557 /* For speed reasons, we look at the value of OUTPUT_CHARSET only
1558 once. This is a user variable that is not supposed to change
1559 during a program run. */
1560 static char *output_charset_cache
;
1561 static int output_charset_cached
;
1563 if (!output_charset_cached
)
1565 const char *value
= getenv ("OUTPUT_CHARSET");
1567 if (value
!= NULL
&& value
[0] != '\0')
1569 size_t len
= strlen (value
) + 1;
1570 char *value_copy
= (char *) malloc (len
);
1572 if (value_copy
!= NULL
)
1573 memcpy (value_copy
, value
, len
);
1574 output_charset_cache
= value_copy
;
1576 output_charset_cached
= 1;
1579 if (output_charset_cache
!= NULL
)
1580 return output_charset_cache
;
1584 return _NL_CURRENT (LC_CTYPE
, CODESET
);
1587 extern const char *locale_charset (void);
1588 return locale_charset ();
1596 /* @@ begin of epilog @@ */
1598 /* We don't want libintl.a to depend on any other library. So we
1599 avoid the non-standard function stpcpy. In GNU C Library this
1600 function is available, though. Also allow the symbol HAVE_STPCPY
1602 #if !_LIBC && !HAVE_STPCPY
1604 stpcpy (char *dest
, const char *src
)
1606 while ((*dest
++ = *src
++) != '\0')
1612 #if !_LIBC && !HAVE_MEMPCPY
1614 mempcpy (void *dest
, const void *src
, size_t n
)
1616 return (void *) ((char *) memcpy (dest
, src
, n
) + n
);
1622 /* If we want to free all resources we have to do some work at
1624 libc_freeres_fn (free_mem
)
1628 while (_nl_domain_bindings
!= NULL
)
1630 struct binding
*oldp
= _nl_domain_bindings
;
1631 _nl_domain_bindings
= _nl_domain_bindings
->next
;
1632 if (oldp
->dirname
!= _nl_default_dirname
)
1633 /* Yes, this is a pointer comparison. */
1634 free (oldp
->dirname
);
1635 free (oldp
->codeset
);
1639 if (_nl_current_default_domain
!= _nl_default_default_domain
)
1640 /* Yes, again a pointer comparison. */
1641 free ((char *) _nl_current_default_domain
);
1643 /* Remove the search tree with the known translations. */
1644 __tdestroy (root
, free
);
1647 while (transmem_list
!= NULL
)
1649 old
= transmem_list
;
1650 transmem_list
= transmem_list
->next
;