1 /* Implementation of the internal dcigettext function.
2 Copyright (C) 1995-2002,2003,2004,2005 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, write to the Free
17 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
20 /* Tell glibc's <string.h> to provide a prototype for mempcpy().
21 This must come before <config.h> because <config.h> may include
22 <features.h>, and once <features.h> has been included, it's too late. */
24 # define _GNU_SOURCE 1
31 #include <sys/types.h>
34 # define alloca __builtin_alloca
35 # define HAVE_ALLOCA 1
37 # if defined HAVE_ALLOCA_H || defined _LIBC
55 # define __set_errno(val) errno = (val)
62 #if defined HAVE_UNISTD_H || defined _LIBC
68 #if defined HAVE_SYS_PARAM_H || defined _LIBC
69 # include <sys/param.h>
73 #include "plural-exp.h"
77 # include "libgnuintl.h"
79 #include "hash-string.h"
81 /* Thread safetyness. */
83 # include <bits/libc-lock.h>
85 /* Provide dummy implementation if this is outside glibc. */
86 # define __libc_lock_define_initialized(CLASS, NAME)
87 # define __libc_lock_lock(NAME)
88 # define __libc_lock_unlock(NAME)
89 # define __libc_rwlock_define_initialized(CLASS, NAME)
90 # define __libc_rwlock_rdlock(NAME)
91 # define __libc_rwlock_unlock(NAME)
94 /* Alignment of types. */
95 #if defined __GNUC__ && __GNUC__ >= 2
96 # define alignof(TYPE) __alignof__ (TYPE)
98 # define alignof(TYPE) \
99 ((int) &((struct { char dummy1; TYPE dummy2; } *) 0)->dummy2)
102 /* The internal variables in the standalone libintl.a must have different
103 names than the internal variables in GNU libc, otherwise programs
104 using libintl.a cannot be linked statically. */
106 # define _nl_default_default_domain libintl_nl_default_default_domain
107 # define _nl_current_default_domain libintl_nl_current_default_domain
108 # define _nl_default_dirname libintl_nl_default_dirname
109 # define _nl_domain_bindings libintl_nl_domain_bindings
112 /* Some compilers, like SunOS4 cc, don't have offsetof in <stddef.h>. */
114 # define offsetof(type,ident) ((size_t)&(((type*)0)->ident))
117 /* @@ end of prolog @@ */
120 /* Rename the non ANSI C functions. This is required by the standard
121 because some ANSI C functions will require linking with this object
122 file and the name space must not be polluted. */
123 # define getcwd __getcwd
125 # define stpcpy __stpcpy
127 # define tfind __tfind
129 # if !defined HAVE_GETCWD
131 # define getcwd(buf, max) getwd (buf)
136 static char *stpcpy
PARAMS ((char *dest
, const char *src
));
138 # ifndef HAVE_MEMPCPY
139 static void *mempcpy
PARAMS ((void *dest
, const void *src
, size_t n
));
143 /* Amount to increase buffer size by in each try. */
146 /* The following is from pathmax.h. */
147 /* Non-POSIX BSD systems might have gcc's limits.h, which doesn't define
148 PATH_MAX but might cause redefinition warnings when sys/param.h is
149 later included (as on MORE/BSD 4.3). */
150 #if defined _POSIX_VERSION || (defined HAVE_LIMITS_H && !defined __GNUC__)
154 #ifndef _POSIX_PATH_MAX
155 # define _POSIX_PATH_MAX 255
158 #if !defined PATH_MAX && defined _PC_PATH_MAX
159 # define PATH_MAX (pathconf ("/", _PC_PATH_MAX) < 1 ? 1024 : pathconf ("/", _PC_PATH_MAX))
162 /* Don't include sys/param.h if it already has been. */
163 #if defined HAVE_SYS_PARAM_H && !defined PATH_MAX && !defined MAXPATHLEN
164 # include <sys/param.h>
167 #if !defined PATH_MAX && defined MAXPATHLEN
168 # define PATH_MAX MAXPATHLEN
172 # define PATH_MAX _POSIX_PATH_MAX
175 /* Whether to support different locales in different threads. */
176 #if defined _LIBC || HAVE_NL_LOCALE_NAME
177 # define HAVE_PER_THREAD_LOCALE
180 /* This is the type used for the search tree where known translations
182 struct known_translation_t
184 /* Domain in which to search. */
185 const char *domainname
;
190 #ifdef HAVE_PER_THREAD_LOCALE
191 /* Name of the relevant locale category, or "" for the global locale. */
192 const char *localename
;
195 /* State of the catalog counter at the point the string was found. */
198 /* Catalog where the string was found. */
199 struct loaded_l10nfile
*domain
;
201 /* And finally the translation. */
202 const char *translation
;
203 size_t translation_length
;
205 /* Pointer to the string in question. */
209 /* Root of the search tree with known translations. We can use this
210 only if the system provides the `tsearch' function family. */
211 #if defined HAVE_TSEARCH || defined _LIBC
217 # define tsearch __tsearch
220 /* Function to compare two entries in the table of known translations. */
221 static int transcmp
PARAMS ((const void *p1
, const void *p2
));
227 const struct known_translation_t
*s1
;
228 const struct known_translation_t
*s2
;
231 s1
= (const struct known_translation_t
*) p1
;
232 s2
= (const struct known_translation_t
*) p2
;
234 result
= strcmp (s1
->msgid
, s2
->msgid
);
237 result
= strcmp (s1
->domainname
, s2
->domainname
);
240 #ifdef HAVE_PER_THREAD_LOCALE
241 result
= strcmp (s1
->localename
, s2
->localename
);
244 /* We compare the category last (though this is the cheapest
245 operation) since it is hopefully always the same (namely
247 result
= s1
->category
- s2
->category
;
255 /* Name of the default domain used for gettext(3) prior any call to
256 textdomain(3). The default value for this is "messages". */
257 const char _nl_default_default_domain
[] attribute_hidden
= "messages";
259 /* Value used as the default domain for gettext(3). */
260 const char *_nl_current_default_domain attribute_hidden
261 = _nl_default_default_domain
;
263 /* Contains the default location of the message catalogs. */
266 extern const char _nl_default_dirname
[];
267 libc_hidden_proto (_nl_default_dirname
)
269 const char _nl_default_dirname
[] = LOCALEDIR
;
271 libc_hidden_data_def (_nl_default_dirname
)
274 /* List with bindings of specific domains created by bindtextdomain()
276 struct binding
*_nl_domain_bindings
;
278 /* Prototypes for local functions. */
279 static char *plural_lookup
PARAMS ((struct loaded_l10nfile
*domain
,
281 const char *translation
,
282 size_t translation_len
))
284 static const char *guess_category_value
PARAMS ((int category
,
285 const char *categoryname
))
288 # include "../locale/localeinfo.h"
289 # define category_to_name(category) _nl_category_names[category]
291 static const char *category_to_name
PARAMS ((int category
)) internal_function
;
295 /* For those loosing systems which don't have `alloca' we have to add
296 some additional code emulating it. */
298 /* Nothing has to be done. */
299 # define freea(p) /* nothing */
300 # define ADD_BLOCK(list, address) /* nothing */
301 # define FREE_BLOCKS(list) /* nothing */
306 struct block_list
*next
;
308 # define ADD_BLOCK(list, addr) \
310 struct block_list *newp = (struct block_list *) malloc (sizeof (*newp)); \
311 /* If we cannot get a free block we cannot add the new element to \
313 if (newp != NULL) { \
314 newp->address = (addr); \
315 newp->next = (list); \
319 # define FREE_BLOCKS(list) \
321 while (list != NULL) { \
322 struct block_list *old = list; \
324 free (old->address); \
329 # define alloca(size) (malloc (size))
330 # define freea(p) free (p)
331 #endif /* have alloca */
335 /* List of blocks allocated for translations. */
336 typedef struct transmem_list
338 struct transmem_list
*next
;
341 static struct transmem_list
*transmem_list
;
343 typedef unsigned char transmem_block_t
;
345 #if defined _LIBC || HAVE_ICONV
346 static const char *get_output_charset
PARAMS ((struct binding
*domainbinding
))
351 /* Names for the libintl functions are a problem. They must not clash
352 with existing names and they should follow ANSI C. But this source
353 code is also used in GNU C Library where the names have a __
354 prefix. So we have to make a difference here. */
356 # define DCIGETTEXT __dcigettext
358 # define DCIGETTEXT libintl_dcigettext
361 /* Lock variable to protect the global data in the gettext implementation. */
363 __libc_rwlock_define_initialized (, _nl_state_lock attribute_hidden
)
366 /* Checking whether the binaries runs SUID must be done and glibc provides
367 easier methods therefore we make a difference here. */
369 # define ENABLE_SECURE __libc_enable_secure
370 # define DETERMINE_SECURE
378 # ifndef HAVE_GETEUID
379 # define geteuid() getuid()
381 # ifndef HAVE_GETEGID
382 # define getegid() getgid()
384 static int enable_secure
;
385 # define ENABLE_SECURE (enable_secure == 1)
386 # define DETERMINE_SECURE \
387 if (enable_secure == 0) \
389 if (getuid () != geteuid () || getgid () != getegid ()) \
392 enable_secure = -1; \
396 /* Get the function to evaluate the plural expression. */
397 #include "plural-eval.c"
399 /* Look up MSGID in the DOMAINNAME message catalog for the current
400 CATEGORY locale and, if PLURAL is nonzero, search over string
401 depending on the plural form determined by N. */
403 DCIGETTEXT (domainname
, msgid1
, msgid2
, plural
, n
, category
)
404 const char *domainname
;
412 struct block_list
*block_list
= NULL
;
414 struct loaded_l10nfile
*domain
;
415 struct binding
*binding
;
416 const char *categoryname
;
417 const char *categoryvalue
;
418 char *dirname
, *xdomainname
;
423 #if defined HAVE_TSEARCH || defined _LIBC
424 struct known_translation_t
*search
;
425 struct known_translation_t
**foundp
= NULL
;
427 # ifdef HAVE_PER_THREAD_LOCALE
428 const char *localename
;
431 size_t domainname_len
;
433 /* If no real MSGID is given return NULL. */
438 if (category
< 0 || category
>= __LC_LAST
|| category
== LC_ALL
)
442 /* Use the Germanic plural rule. */
443 : n
== 1 ? (char *) msgid1
: (char *) msgid2
);
446 __libc_rwlock_rdlock (_nl_state_lock
);
448 /* If DOMAINNAME is NULL, we are interested in the default domain. If
449 CATEGORY is not LC_MESSAGES this might not make much sense but the
450 definition left this undefined. */
451 if (domainname
== NULL
)
452 domainname
= _nl_current_default_domain
;
454 #if defined HAVE_TSEARCH || defined _LIBC
455 msgid_len
= strlen (msgid1
) + 1;
457 /* Try to find the translation among those which we found at
459 search
= (struct known_translation_t
*)
460 alloca (offsetof (struct known_translation_t
, msgid
) + msgid_len
);
461 memcpy (search
->msgid
, msgid1
, msgid_len
);
462 search
->domainname
= domainname
;
463 search
->category
= category
;
464 # ifdef HAVE_PER_THREAD_LOCALE
466 localename
= __current_locale_name (category
);
468 search
->localename
= localename
;
471 /* Since tfind/tsearch manage a balanced tree, concurrent tfind and
472 tsearch calls can be fatal. */
473 __libc_rwlock_define_initialized (static, tree_lock
);
474 __libc_rwlock_rdlock (tree_lock
);
476 foundp
= (struct known_translation_t
**) tfind (search
, &root
, transcmp
);
478 __libc_rwlock_unlock (tree_lock
);
481 if (foundp
!= NULL
&& (*foundp
)->counter
== _nl_msg_cat_cntr
)
483 /* Now deal with plural. */
485 retval
= plural_lookup ((*foundp
)->domain
, n
, (*foundp
)->translation
,
486 (*foundp
)->translation_length
);
488 retval
= (char *) (*foundp
)->translation
;
490 __libc_rwlock_unlock (_nl_state_lock
);
495 /* Preserve the `errno' value. */
498 /* See whether this is a SUID binary or not. */
501 /* First find matching binding. */
502 for (binding
= _nl_domain_bindings
; binding
!= NULL
; binding
= binding
->next
)
504 int compare
= strcmp (domainname
, binding
->domainname
);
510 /* It is not in the list. */
517 dirname
= (char *) _nl_default_dirname
;
518 else if (binding
->dirname
[0] == '/')
519 dirname
= binding
->dirname
;
522 /* We have a relative path. Make it absolute now. */
523 size_t dirname_len
= strlen (binding
->dirname
) + 1;
527 path_max
= (unsigned int) PATH_MAX
;
528 path_max
+= 2; /* The getcwd docs say to do this. */
532 dirname
= (char *) alloca (path_max
+ dirname_len
);
533 ADD_BLOCK (block_list
, dirname
);
536 ret
= getcwd (dirname
, path_max
);
537 if (ret
!= NULL
|| errno
!= ERANGE
)
540 path_max
+= path_max
/ 2;
541 path_max
+= PATH_INCR
;
546 /* We cannot get the current working directory. Don't signal an
547 error but simply return the default string. */
548 FREE_BLOCKS (block_list
);
549 __libc_rwlock_unlock (_nl_state_lock
);
550 __set_errno (saved_errno
);
553 /* Use the Germanic plural rule. */
554 : n
== 1 ? (char *) msgid1
: (char *) msgid2
);
557 stpcpy (stpcpy (strchr (dirname
, '\0'), "/"), binding
->dirname
);
560 /* Now determine the symbolic name of CATEGORY and its value. */
561 categoryname
= category_to_name (category
);
562 categoryvalue
= guess_category_value (category
, categoryname
);
564 domainname_len
= strlen (domainname
);
565 xdomainname
= (char *) alloca (strlen (categoryname
)
566 + domainname_len
+ 5);
567 ADD_BLOCK (block_list
, xdomainname
);
569 stpcpy (mempcpy (stpcpy (stpcpy (xdomainname
, categoryname
), "/"),
570 domainname
, domainname_len
),
573 /* Creating working area. */
574 single_locale
= (char *) alloca (strlen (categoryvalue
) + 1);
575 ADD_BLOCK (block_list
, single_locale
);
578 /* Search for the given string. This is a loop because we perhaps
579 got an ordered list of languages to consider for the translation. */
582 /* Make CATEGORYVALUE point to the next element of the list. */
583 while (categoryvalue
[0] != '\0' && categoryvalue
[0] == ':')
585 if (categoryvalue
[0] == '\0')
587 /* The whole contents of CATEGORYVALUE has been searched but
588 no valid entry has been found. We solve this situation
589 by implicitly appending a "C" entry, i.e. no translation
591 single_locale
[0] = 'C';
592 single_locale
[1] = '\0';
596 char *cp
= single_locale
;
597 while (categoryvalue
[0] != '\0' && categoryvalue
[0] != ':')
598 *cp
++ = *categoryvalue
++;
601 /* When this is a SUID binary we must not allow accessing files
602 outside the dedicated directories. */
603 if (ENABLE_SECURE
&& strchr (single_locale
, '/') != NULL
)
604 /* Ingore this entry. */
608 /* If the current locale value is C (or POSIX) we don't load a
609 domain. Return the MSGID. */
610 if (strcmp (single_locale
, "C") == 0
611 || strcmp (single_locale
, "POSIX") == 0)
613 FREE_BLOCKS (block_list
);
614 __libc_rwlock_unlock (_nl_state_lock
);
615 __set_errno (saved_errno
);
618 /* Use the Germanic plural rule. */
619 : n
== 1 ? (char *) msgid1
: (char *) msgid2
);
623 /* Find structure describing the message catalog matching the
624 DOMAINNAME and CATEGORY. */
625 domain
= _nl_find_domain (dirname
, single_locale
, xdomainname
, binding
);
629 retval
= _nl_find_msg (domain
, binding
, msgid1
, 1, &retlen
);
635 for (cnt
= 0; domain
->successor
[cnt
] != NULL
; ++cnt
)
637 retval
= _nl_find_msg (domain
->successor
[cnt
], binding
,
642 domain
= domain
->successor
[cnt
];
650 /* Found the translation of MSGID1 in domain DOMAIN:
651 starting at RETVAL, RETLEN bytes. */
652 FREE_BLOCKS (block_list
);
653 #if defined HAVE_TSEARCH || defined _LIBC
656 /* Create a new entry and add it to the search tree. */
658 struct known_translation_t
*newp
;
660 size
= offsetof (struct known_translation_t
, msgid
)
661 + msgid_len
+ domainname_len
+ 1;
662 # ifdef HAVE_PER_THREAD_LOCALE
663 size
+= strlen (localename
) + 1;
665 newp
= (struct known_translation_t
*) malloc (size
);
668 char *new_domainname
;
669 # ifdef HAVE_PER_THREAD_LOCALE
670 char *new_localename
;
673 new_domainname
= mempcpy (newp
->msgid
, msgid1
, msgid_len
);
674 memcpy (new_domainname
, domainname
, domainname_len
+ 1);
675 # ifdef HAVE_PER_THREAD_LOCALE
676 new_localename
= new_domainname
+ domainname_len
+ 1;
677 strcpy (new_localename
, localename
);
679 newp
->domainname
= new_domainname
;
680 newp
->category
= category
;
681 # ifdef HAVE_PER_THREAD_LOCALE
682 newp
->localename
= new_localename
;
684 newp
->counter
= _nl_msg_cat_cntr
;
685 newp
->domain
= domain
;
686 newp
->translation
= retval
;
687 newp
->translation_length
= retlen
;
689 __libc_rwlock_wrlock (tree_lock
);
691 /* Insert the entry in the search tree. */
692 foundp
= (struct known_translation_t
**)
693 tsearch (newp
, &root
, transcmp
);
695 __libc_rwlock_unlock (tree_lock
);
698 || __builtin_expect (*foundp
!= newp
, 0))
699 /* The insert failed. */
705 /* We can update the existing entry. */
706 (*foundp
)->counter
= _nl_msg_cat_cntr
;
707 (*foundp
)->domain
= domain
;
708 (*foundp
)->translation
= retval
;
709 (*foundp
)->translation_length
= retlen
;
712 __set_errno (saved_errno
);
714 /* Now deal with plural. */
716 retval
= plural_lookup (domain
, n
, retval
, retlen
);
718 __libc_rwlock_unlock (_nl_state_lock
);
729 _nl_find_msg (domain_file
, domainbinding
, msgid
, convert
, lengthp
)
730 struct loaded_l10nfile
*domain_file
;
731 struct binding
*domainbinding
;
736 struct loaded_domain
*domain
;
742 if (domain_file
->decided
<= 0)
743 _nl_load_domain (domain_file
, domainbinding
);
745 if (domain_file
->data
== NULL
)
748 domain
= (struct loaded_domain
*) domain_file
->data
;
750 nstrings
= domain
->nstrings
;
752 /* Locate the MSGID and its translation. */
753 if (domain
->hash_tab
!= NULL
)
755 /* Use the hashing table. */
756 nls_uint32 len
= strlen (msgid
);
757 nls_uint32 hash_val
= __hash_string (msgid
);
758 nls_uint32 idx
= hash_val
% domain
->hash_size
;
759 nls_uint32 incr
= 1 + (hash_val
% (domain
->hash_size
- 2));
764 W (domain
->must_swap_hash_tab
, domain
->hash_tab
[idx
]);
767 /* Hash table entry is empty. */
772 /* Compare msgid with the original string at index nstr.
773 We compare the lengths with >=, not ==, because plural entries
774 are represented by strings with an embedded NUL. */
776 ? W (domain
->must_swap
, domain
->orig_tab
[nstr
].length
) >= len
778 domain
->data
+ W (domain
->must_swap
,
779 domain
->orig_tab
[nstr
].offset
))
781 : domain
->orig_sysdep_tab
[nstr
- nstrings
].length
> len
783 domain
->orig_sysdep_tab
[nstr
- nstrings
].pointer
)
790 if (idx
>= domain
->hash_size
- incr
)
791 idx
-= domain
->hash_size
- incr
;
799 /* Try the default method: binary search in the sorted array of
809 act
= (bottom
+ top
) / 2;
810 cmp_val
= strcmp (msgid
, (domain
->data
811 + W (domain
->must_swap
,
812 domain
->orig_tab
[act
].offset
)));
815 else if (cmp_val
> 0)
820 /* No translation was found. */
825 /* The translation was found at index ACT. If we have to convert the
826 string to use a different character set, this is the time. */
830 (domain
->data
+ W (domain
->must_swap
, domain
->trans_tab
[act
].offset
));
831 resultlen
= W (domain
->must_swap
, domain
->trans_tab
[act
].length
) + 1;
835 result
= (char *) domain
->trans_sysdep_tab
[act
- nstrings
].pointer
;
836 resultlen
= domain
->trans_sysdep_tab
[act
- nstrings
].length
;
839 #if defined _LIBC || HAVE_ICONV
842 /* We are supposed to do a conversion. */
843 const char *encoding
= get_output_charset (domainbinding
);
845 /* Search whether a table with converted translations for this
846 encoding has already been allocated. */
847 size_t nconversions
= domain
->nconversions
;
848 struct converted_domain
*convd
= NULL
;
851 for (i
= nconversions
; i
> 0; )
854 if (strcmp (domain
->conversions
[i
].encoding
, encoding
) == 0)
856 convd
= &domain
->conversions
[i
];
863 /* Allocate a table for the converted translations for this
865 struct converted_domain
*new_conversions
=
866 (struct converted_domain
*)
867 (domain
->conversions
!= NULL
868 ? realloc (domain
->conversions
,
869 (nconversions
+ 1) * sizeof (struct converted_domain
))
870 : malloc ((nconversions
+ 1) * sizeof (struct converted_domain
)));
872 if (__builtin_expect (new_conversions
== NULL
, 0))
873 /* Nothing we can do, no more memory. */
875 domain
->conversions
= new_conversions
;
877 /* Copy the 'encoding' string to permanent storage. */
878 encoding
= strdup (encoding
);
879 if (__builtin_expect (encoding
== NULL
, 0))
880 /* Nothing we can do, no more memory. */
883 convd
= &new_conversions
[nconversions
];
884 convd
->encoding
= encoding
;
886 /* Find out about the character set the file is encoded with.
887 This can be found (in textual form) in the entry "". If this
888 entry does not exist or if this does not contain the 'charset='
889 information, we will assume the charset matches the one the
890 current locale and we don't have to perform any conversion. */
892 convd
->conv
= (__gconv_t
) -1;
895 convd
->conv
= (iconv_t
) -1;
902 /* Get the header entry. This is a recursion, but it doesn't
903 reallocate domain->conversions because we pass convert = 0. */
905 _nl_find_msg (domain_file
, domainbinding
, "", 0, &nullentrylen
);
907 if (nullentry
!= NULL
)
909 const char *charsetstr
;
911 charsetstr
= strstr (nullentry
, "charset=");
912 if (charsetstr
!= NULL
)
916 const char *outcharset
;
918 charsetstr
+= strlen ("charset=");
919 len
= strcspn (charsetstr
, " \t\n");
921 charset
= (char *) alloca (len
+ 1);
922 # if defined _LIBC || HAVE_MEMPCPY
923 *((char *) mempcpy (charset
, charsetstr
, len
)) = '\0';
925 memcpy (charset
, charsetstr
, len
);
929 outcharset
= encoding
;
932 /* We always want to use transliteration. */
933 outcharset
= norm_add_slashes (outcharset
, "TRANSLIT");
934 charset
= norm_add_slashes (charset
, "");
935 if (__gconv_open (outcharset
, charset
, &convd
->conv
,
938 convd
->conv
= (__gconv_t
) -1;
941 /* When using GNU libc >= 2.2 or GNU libiconv >= 1.5,
942 we want to use transliteration. */
943 # if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2) || __GLIBC__ > 2 \
944 || _LIBICONV_VERSION >= 0x0105
945 if (strchr (outcharset
, '/') == NULL
)
949 len
= strlen (outcharset
);
950 tmp
= (char *) alloca (len
+ 10 + 1);
951 memcpy (tmp
, outcharset
, len
);
952 memcpy (tmp
+ len
, "//TRANSLIT", 10 + 1);
955 convd
->conv
= iconv_open (outcharset
, charset
);
961 convd
->conv
= iconv_open (outcharset
, charset
);
969 convd
->conv_tab
= NULL
;
970 /* Here domain->conversions is still == new_conversions. */
971 domain
->nconversions
++;
976 convd
->conv
!= (__gconv_t
) -1
979 convd
->conv
!= (iconv_t
) -1
984 /* We are supposed to do a conversion. First allocate an
985 appropriate table with the same structure as the table
986 of translations in the file, where we can put the pointers
987 to the converted strings in.
988 There is a slight complication with plural entries. They
989 are represented by consecutive NUL terminated strings. We
990 handle this case by converting RESULTLEN bytes, including
993 if (convd
->conv_tab
== NULL
994 && ((convd
->conv_tab
=
995 (char **) calloc (nstrings
+ domain
->n_sysdep_strings
,
998 /* Mark that we didn't succeed allocating a table. */
999 convd
->conv_tab
= (char **) -1;
1001 if (__builtin_expect (convd
->conv_tab
== (char **) -1, 0))
1002 /* Nothing we can do, no more memory. */
1005 if (convd
->conv_tab
[act
] == NULL
)
1007 /* We haven't used this string so far, so it is not
1008 translated yet. Do this now. */
1009 /* We use a bit more efficient memory handling.
1010 We allocate always larger blocks which get used over
1011 time. This is faster than many small allocations. */
1012 __libc_lock_define_initialized (static, lock
)
1013 # define INITIAL_BLOCK_SIZE 4080
1014 static unsigned char *freemem
;
1015 static size_t freemem_size
;
1017 const unsigned char *inbuf
;
1018 unsigned char *outbuf
;
1021 transmem_block_t
*transmem_list
= NULL
;
1024 __libc_lock_lock (lock
);
1026 inbuf
= (const unsigned char *) result
;
1027 outbuf
= freemem
+ sizeof (size_t);
1032 transmem_block_t
*newmem
;
1034 size_t non_reversible
;
1037 if (freemem_size
< sizeof (size_t))
1038 goto resize_freemem
;
1040 res
= __gconv (convd
->conv
,
1041 &inbuf
, inbuf
+ resultlen
,
1043 outbuf
+ freemem_size
- sizeof (size_t),
1046 if (res
== __GCONV_OK
|| res
== __GCONV_EMPTY_INPUT
)
1049 if (res
!= __GCONV_FULL_OUTPUT
)
1051 __libc_lock_unlock (lock
);
1055 inbuf
= (const unsigned char *) result
;
1058 const char *inptr
= (const char *) inbuf
;
1059 size_t inleft
= resultlen
;
1060 char *outptr
= (char *) outbuf
;
1063 if (freemem_size
< sizeof (size_t))
1064 goto resize_freemem
;
1066 outleft
= freemem_size
- sizeof (size_t);
1067 if (iconv (convd
->conv
,
1068 (ICONV_CONST
char **) &inptr
, &inleft
,
1072 outbuf
= (unsigned char *) outptr
;
1077 __libc_lock_unlock (lock
);
1084 /* We must allocate a new buffer or resize the old one. */
1085 if (malloc_count
> 0)
1088 freemem_size
= malloc_count
* INITIAL_BLOCK_SIZE
;
1089 newmem
= (transmem_block_t
*) realloc (transmem_list
,
1093 transmem_list
= transmem_list
->next
;
1096 struct transmem_list
*old
= transmem_list
;
1098 transmem_list
= transmem_list
->next
;
1106 freemem_size
= INITIAL_BLOCK_SIZE
;
1107 newmem
= (transmem_block_t
*) malloc (freemem_size
);
1109 if (__builtin_expect (newmem
== NULL
, 0))
1113 __libc_lock_unlock (lock
);
1118 /* Add the block to the list of blocks we have to free
1120 newmem
->next
= transmem_list
;
1121 transmem_list
= newmem
;
1123 freemem
= (unsigned char *) newmem
->data
;
1124 freemem_size
-= offsetof (struct transmem_list
, data
);
1126 transmem_list
= newmem
;
1130 outbuf
= freemem
+ sizeof (size_t);
1133 /* We have now in our buffer a converted string. Put this
1134 into the table of conversions. */
1135 *(size_t *) freemem
= outbuf
- freemem
- sizeof (size_t);
1136 convd
->conv_tab
[act
] = (char *) freemem
;
1137 /* Shrink freemem, but keep it aligned. */
1138 freemem_size
-= outbuf
- freemem
;
1140 freemem
+= freemem_size
& (alignof (size_t) - 1);
1141 freemem_size
= freemem_size
& ~ (alignof (size_t) - 1);
1143 __libc_lock_unlock (lock
);
1146 /* Now convd->conv_tab[act] contains the translation of all
1147 the plural variants. */
1148 result
= convd
->conv_tab
[act
] + sizeof (size_t);
1149 resultlen
= *(size_t *) convd
->conv_tab
[act
];
1154 /* The result string is converted. */
1156 #endif /* _LIBC || HAVE_ICONV */
1158 *lengthp
= resultlen
;
1163 /* Look up a plural variant. */
1166 plural_lookup (domain
, n
, translation
, translation_len
)
1167 struct loaded_l10nfile
*domain
;
1168 unsigned long int n
;
1169 const char *translation
;
1170 size_t translation_len
;
1172 struct loaded_domain
*domaindata
= (struct loaded_domain
*) domain
->data
;
1173 unsigned long int index
;
1176 index
= plural_eval (domaindata
->plural
, n
);
1177 if (index
>= domaindata
->nplurals
)
1178 /* This should never happen. It means the plural expression and the
1179 given maximum value do not match. */
1182 /* Skip INDEX strings at TRANSLATION. */
1187 p
= __rawmemchr (p
, '\0');
1189 p
= strchr (p
, '\0');
1191 /* And skip over the NUL byte. */
1194 if (p
>= translation
+ translation_len
)
1195 /* This should never happen. It means the plural expression
1196 evaluated to a value larger than the number of variants
1197 available for MSGID1. */
1198 return (char *) translation
;
1204 /* Return string representation of locale CATEGORY. */
1207 category_to_name (category
)
1216 retval
= "LC_COLLATE";
1221 retval
= "LC_CTYPE";
1226 retval
= "LC_MONETARY";
1231 retval
= "LC_NUMERIC";
1241 retval
= "LC_MESSAGES";
1246 retval
= "LC_RESPONSE";
1251 /* This might not make sense but is perhaps better than any other
1257 /* If you have a better idea for a default value let me know. */
1265 /* Guess value of current locale from value of the environment variables. */
1268 guess_category_value (category
, categoryname
)
1270 const char *categoryname
;
1272 const char *language
;
1275 /* The highest priority value is the `LANGUAGE' environment
1276 variable. But we don't use the value if the currently selected
1277 locale is the C locale. This is a GNU extension. */
1278 language
= getenv ("LANGUAGE");
1279 if (language
!= NULL
&& language
[0] == '\0')
1282 /* We have to proceed with the POSIX methods of looking to `LC_ALL',
1283 `LC_xxx', and `LANG'. On some systems this can be done by the
1284 `setlocale' function itself. */
1286 retval
= __current_locale_name (category
);
1288 retval
= _nl_locale_name (category
, categoryname
);
1291 return language
!= NULL
&& strcmp (retval
, "C") != 0 ? language
: retval
;
1294 #if defined _LIBC || HAVE_ICONV
1295 /* Returns the output charset. */
1298 get_output_charset (domainbinding
)
1299 struct binding
*domainbinding
;
1301 /* The output charset should normally be determined by the locale. But
1302 sometimes the locale is not used or not correctly set up, so we provide
1303 a possibility for the user to override this: the OUTPUT_CHARSET
1304 environment variable. Moreover, the value specified through
1305 bind_textdomain_codeset overrides both. */
1306 if (domainbinding
!= NULL
&& domainbinding
->codeset
!= NULL
)
1307 return domainbinding
->codeset
;
1310 /* For speed reasons, we look at the value of OUTPUT_CHARSET only
1311 once. This is a user variable that is not supposed to change
1312 during a program run. */
1313 static char *output_charset_cache
;
1314 static int output_charset_cached
;
1316 if (!output_charset_cached
)
1318 const char *value
= getenv ("OUTPUT_CHARSET");
1320 if (value
!= NULL
&& value
[0] != '\0')
1322 size_t len
= strlen (value
) + 1;
1323 char *value_copy
= (char *) malloc (len
);
1325 if (value_copy
!= NULL
)
1326 memcpy (value_copy
, value
, len
);
1327 output_charset_cache
= value_copy
;
1329 output_charset_cached
= 1;
1332 if (output_charset_cache
!= NULL
)
1333 return output_charset_cache
;
1337 return _NL_CURRENT (LC_CTYPE
, CODESET
);
1340 extern const char *locale_charset
PARAMS ((void);
1341 return locale_charset ();
1349 /* @@ begin of epilog @@ */
1351 /* We don't want libintl.a to depend on any other library. So we
1352 avoid the non-standard function stpcpy. In GNU C Library this
1353 function is available, though. Also allow the symbol HAVE_STPCPY
1355 #if !_LIBC && !HAVE_STPCPY
1361 while ((*dest
++ = *src
++) != '\0')
1367 #if !_LIBC && !HAVE_MEMPCPY
1369 mempcpy (dest
, src
, n
)
1374 return (void *) ((char *) memcpy (dest
, src
, n
) + n
);
1380 /* If we want to free all resources we have to do some work at
1382 libc_freeres_fn (free_mem
)
1386 while (_nl_domain_bindings
!= NULL
)
1388 struct binding
*oldp
= _nl_domain_bindings
;
1389 _nl_domain_bindings
= _nl_domain_bindings
->next
;
1390 if (oldp
->dirname
!= _nl_default_dirname
)
1391 /* Yes, this is a pointer comparison. */
1392 free (oldp
->dirname
);
1393 free (oldp
->codeset
);
1397 if (_nl_current_default_domain
!= _nl_default_default_domain
)
1398 /* Yes, again a pointer comparison. */
1399 free ((char *) _nl_current_default_domain
);
1401 /* Remove the search tree with the known translations. */
1402 __tdestroy (root
, free
);
1405 while (transmem_list
!= NULL
)
1407 old
= transmem_list
;
1408 transmem_list
= transmem_list
->next
;