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 /* This is the type used for the search tree where known translations
177 struct known_translation_t
179 /* Domain in which to search. */
180 const char *domainname
;
185 /* State of the catalog counter at the point the string was found. */
188 /* Catalog where the string was found. */
189 struct loaded_l10nfile
*domain
;
191 /* And finally the translation. */
192 const char *translation
;
193 size_t translation_length
;
195 /* Pointer to the string in question. */
199 /* Root of the search tree with known translations. We can use this
200 only if the system provides the `tsearch' function family. */
201 #if defined HAVE_TSEARCH || defined _LIBC
207 # define tsearch __tsearch
210 /* Function to compare two entries in the table of known translations. */
211 static int transcmp
PARAMS ((const void *p1
, const void *p2
));
217 const struct known_translation_t
*s1
;
218 const struct known_translation_t
*s2
;
221 s1
= (const struct known_translation_t
*) p1
;
222 s2
= (const struct known_translation_t
*) p2
;
224 result
= strcmp (s1
->msgid
, s2
->msgid
);
227 result
= strcmp (s1
->domainname
, s2
->domainname
);
229 /* We compare the category last (though this is the cheapest
230 operation) since it is hopefully always the same (namely
232 result
= s1
->category
- s2
->category
;
239 /* Name of the default domain used for gettext(3) prior any call to
240 textdomain(3). The default value for this is "messages". */
241 const char _nl_default_default_domain
[] attribute_hidden
= "messages";
243 /* Value used as the default domain for gettext(3). */
244 const char *_nl_current_default_domain attribute_hidden
245 = _nl_default_default_domain
;
247 /* Contains the default location of the message catalogs. */
250 extern const char _nl_default_dirname
[];
251 libc_hidden_proto (_nl_default_dirname
)
253 const char _nl_default_dirname
[] = LOCALEDIR
;
255 libc_hidden_data_def (_nl_default_dirname
)
258 /* List with bindings of specific domains created by bindtextdomain()
260 struct binding
*_nl_domain_bindings
;
262 /* Prototypes for local functions. */
263 static char *plural_lookup
PARAMS ((struct loaded_l10nfile
*domain
,
265 const char *translation
,
266 size_t translation_len
))
268 static const char *guess_category_value
PARAMS ((int category
,
269 const char *categoryname
))
272 # include "../locale/localeinfo.h"
273 # define category_to_name(category) _nl_category_names[category]
275 static const char *category_to_name
PARAMS ((int category
)) internal_function
;
279 /* For those loosing systems which don't have `alloca' we have to add
280 some additional code emulating it. */
282 /* Nothing has to be done. */
283 # define freea(p) /* nothing */
284 # define ADD_BLOCK(list, address) /* nothing */
285 # define FREE_BLOCKS(list) /* nothing */
290 struct block_list
*next
;
292 # define ADD_BLOCK(list, addr) \
294 struct block_list *newp = (struct block_list *) malloc (sizeof (*newp)); \
295 /* If we cannot get a free block we cannot add the new element to \
297 if (newp != NULL) { \
298 newp->address = (addr); \
299 newp->next = (list); \
303 # define FREE_BLOCKS(list) \
305 while (list != NULL) { \
306 struct block_list *old = list; \
308 free (old->address); \
313 # define alloca(size) (malloc (size))
314 # define freea(p) free (p)
315 #endif /* have alloca */
319 /* List of blocks allocated for translations. */
320 typedef struct transmem_list
322 struct transmem_list
*next
;
325 static struct transmem_list
*transmem_list
;
327 typedef unsigned char transmem_block_t
;
329 #if defined _LIBC || HAVE_ICONV
330 static const char *get_output_charset
PARAMS ((struct binding
*domainbinding
))
335 /* Names for the libintl functions are a problem. They must not clash
336 with existing names and they should follow ANSI C. But this source
337 code is also used in GNU C Library where the names have a __
338 prefix. So we have to make a difference here. */
340 # define DCIGETTEXT __dcigettext
342 # define DCIGETTEXT libintl_dcigettext
345 /* Lock variable to protect the global data in the gettext implementation. */
347 __libc_rwlock_define_initialized (, _nl_state_lock attribute_hidden
)
350 /* Checking whether the binaries runs SUID must be done and glibc provides
351 easier methods therefore we make a difference here. */
353 # define ENABLE_SECURE __libc_enable_secure
354 # define DETERMINE_SECURE
362 # ifndef HAVE_GETEUID
363 # define geteuid() getuid()
365 # ifndef HAVE_GETEGID
366 # define getegid() getgid()
368 static int enable_secure
;
369 # define ENABLE_SECURE (enable_secure == 1)
370 # define DETERMINE_SECURE \
371 if (enable_secure == 0) \
373 if (getuid () != geteuid () || getgid () != getegid ()) \
376 enable_secure = -1; \
380 /* Get the function to evaluate the plural expression. */
381 #include "plural-eval.c"
383 /* Look up MSGID in the DOMAINNAME message catalog for the current
384 CATEGORY locale and, if PLURAL is nonzero, search over string
385 depending on the plural form determined by N. */
387 DCIGETTEXT (domainname
, msgid1
, msgid2
, plural
, n
, category
)
388 const char *domainname
;
396 struct block_list
*block_list
= NULL
;
398 struct loaded_l10nfile
*domain
;
399 struct binding
*binding
;
400 const char *categoryname
;
401 const char *categoryvalue
;
402 char *dirname
, *xdomainname
;
407 #if defined HAVE_TSEARCH || defined _LIBC
408 struct known_translation_t
*search
;
409 struct known_translation_t
**foundp
= NULL
;
412 size_t domainname_len
;
414 /* If no real MSGID is given return NULL. */
419 if (category
< 0 || category
>= __LC_LAST
|| category
== LC_ALL
)
423 /* Use the Germanic plural rule. */
424 : n
== 1 ? (char *) msgid1
: (char *) msgid2
);
427 __libc_rwlock_rdlock (_nl_state_lock
);
429 /* If DOMAINNAME is NULL, we are interested in the default domain. If
430 CATEGORY is not LC_MESSAGES this might not make much sense but the
431 definition left this undefined. */
432 if (domainname
== NULL
)
433 domainname
= _nl_current_default_domain
;
435 #if defined HAVE_TSEARCH || defined _LIBC
436 msgid_len
= strlen (msgid1
) + 1;
438 /* Try to find the translation among those which we found at
440 search
= (struct known_translation_t
*)
441 alloca (offsetof (struct known_translation_t
, msgid
) + msgid_len
);
442 memcpy (search
->msgid
, msgid1
, msgid_len
);
443 search
->domainname
= domainname
;
444 search
->category
= category
;
446 /* Since tfind/tsearch manage a balanced tree, concurrent tfind and
447 tsearch calls can be fatal. */
448 __libc_rwlock_define_initialized (static, tree_lock
);
449 __libc_rwlock_rdlock (tree_lock
);
451 foundp
= (struct known_translation_t
**) tfind (search
, &root
, transcmp
);
453 __libc_rwlock_unlock (tree_lock
);
456 if (foundp
!= NULL
&& (*foundp
)->counter
== _nl_msg_cat_cntr
)
458 /* Now deal with plural. */
460 retval
= plural_lookup ((*foundp
)->domain
, n
, (*foundp
)->translation
,
461 (*foundp
)->translation_length
);
463 retval
= (char *) (*foundp
)->translation
;
465 __libc_rwlock_unlock (_nl_state_lock
);
470 /* Preserve the `errno' value. */
473 /* See whether this is a SUID binary or not. */
476 /* First find matching binding. */
477 for (binding
= _nl_domain_bindings
; binding
!= NULL
; binding
= binding
->next
)
479 int compare
= strcmp (domainname
, binding
->domainname
);
485 /* It is not in the list. */
492 dirname
= (char *) _nl_default_dirname
;
493 else if (binding
->dirname
[0] == '/')
494 dirname
= binding
->dirname
;
497 /* We have a relative path. Make it absolute now. */
498 size_t dirname_len
= strlen (binding
->dirname
) + 1;
502 path_max
= (unsigned int) PATH_MAX
;
503 path_max
+= 2; /* The getcwd docs say to do this. */
507 dirname
= (char *) alloca (path_max
+ dirname_len
);
508 ADD_BLOCK (block_list
, dirname
);
511 ret
= getcwd (dirname
, path_max
);
512 if (ret
!= NULL
|| errno
!= ERANGE
)
515 path_max
+= path_max
/ 2;
516 path_max
+= PATH_INCR
;
521 /* We cannot get the current working directory. Don't signal an
522 error but simply return the default string. */
523 FREE_BLOCKS (block_list
);
524 __libc_rwlock_unlock (_nl_state_lock
);
525 __set_errno (saved_errno
);
528 /* Use the Germanic plural rule. */
529 : n
== 1 ? (char *) msgid1
: (char *) msgid2
);
532 stpcpy (stpcpy (strchr (dirname
, '\0'), "/"), binding
->dirname
);
535 /* Now determine the symbolic name of CATEGORY and its value. */
536 categoryname
= category_to_name (category
);
537 categoryvalue
= guess_category_value (category
, categoryname
);
539 domainname_len
= strlen (domainname
);
540 xdomainname
= (char *) alloca (strlen (categoryname
)
541 + domainname_len
+ 5);
542 ADD_BLOCK (block_list
, xdomainname
);
544 stpcpy (mempcpy (stpcpy (stpcpy (xdomainname
, categoryname
), "/"),
545 domainname
, domainname_len
),
548 /* Creating working area. */
549 single_locale
= (char *) alloca (strlen (categoryvalue
) + 1);
550 ADD_BLOCK (block_list
, single_locale
);
553 /* Search for the given string. This is a loop because we perhaps
554 got an ordered list of languages to consider for the translation. */
557 /* Make CATEGORYVALUE point to the next element of the list. */
558 while (categoryvalue
[0] != '\0' && categoryvalue
[0] == ':')
560 if (categoryvalue
[0] == '\0')
562 /* The whole contents of CATEGORYVALUE has been searched but
563 no valid entry has been found. We solve this situation
564 by implicitly appending a "C" entry, i.e. no translation
566 single_locale
[0] = 'C';
567 single_locale
[1] = '\0';
571 char *cp
= single_locale
;
572 while (categoryvalue
[0] != '\0' && categoryvalue
[0] != ':')
573 *cp
++ = *categoryvalue
++;
576 /* When this is a SUID binary we must not allow accessing files
577 outside the dedicated directories. */
578 if (ENABLE_SECURE
&& strchr (single_locale
, '/') != NULL
)
579 /* Ingore this entry. */
583 /* If the current locale value is C (or POSIX) we don't load a
584 domain. Return the MSGID. */
585 if (strcmp (single_locale
, "C") == 0
586 || strcmp (single_locale
, "POSIX") == 0)
588 FREE_BLOCKS (block_list
);
589 __libc_rwlock_unlock (_nl_state_lock
);
590 __set_errno (saved_errno
);
593 /* Use the Germanic plural rule. */
594 : n
== 1 ? (char *) msgid1
: (char *) msgid2
);
598 /* Find structure describing the message catalog matching the
599 DOMAINNAME and CATEGORY. */
600 domain
= _nl_find_domain (dirname
, single_locale
, xdomainname
, binding
);
604 retval
= _nl_find_msg (domain
, binding
, msgid1
, 1, &retlen
);
610 for (cnt
= 0; domain
->successor
[cnt
] != NULL
; ++cnt
)
612 retval
= _nl_find_msg (domain
->successor
[cnt
], binding
,
617 domain
= domain
->successor
[cnt
];
625 /* Found the translation of MSGID1 in domain DOMAIN:
626 starting at RETVAL, RETLEN bytes. */
627 FREE_BLOCKS (block_list
);
628 #if defined HAVE_TSEARCH || defined _LIBC
631 /* Create a new entry and add it to the search tree. */
632 struct known_translation_t
*newp
;
634 newp
= (struct known_translation_t
*)
635 malloc (offsetof (struct known_translation_t
, msgid
)
636 + msgid_len
+ domainname_len
+ 1);
639 char *new_domainname
;
641 new_domainname
= mempcpy (newp
->msgid
, msgid1
, msgid_len
);
642 memcpy (new_domainname
, domainname
, domainname_len
+ 1);
643 newp
->domainname
= new_domainname
;
644 newp
->category
= category
;
645 newp
->counter
= _nl_msg_cat_cntr
;
646 newp
->domain
= domain
;
647 newp
->translation
= retval
;
648 newp
->translation_length
= retlen
;
650 __libc_rwlock_wrlock (tree_lock
);
652 /* Insert the entry in the search tree. */
653 foundp
= (struct known_translation_t
**)
654 tsearch (newp
, &root
, transcmp
);
656 __libc_rwlock_unlock (tree_lock
);
659 || __builtin_expect (*foundp
!= newp
, 0))
660 /* The insert failed. */
666 /* We can update the existing entry. */
667 (*foundp
)->counter
= _nl_msg_cat_cntr
;
668 (*foundp
)->domain
= domain
;
669 (*foundp
)->translation
= retval
;
670 (*foundp
)->translation_length
= retlen
;
673 __set_errno (saved_errno
);
675 /* Now deal with plural. */
677 retval
= plural_lookup (domain
, n
, retval
, retlen
);
679 __libc_rwlock_unlock (_nl_state_lock
);
690 _nl_find_msg (domain_file
, domainbinding
, msgid
, convert
, lengthp
)
691 struct loaded_l10nfile
*domain_file
;
692 struct binding
*domainbinding
;
697 struct loaded_domain
*domain
;
703 if (domain_file
->decided
<= 0)
704 _nl_load_domain (domain_file
, domainbinding
);
706 if (domain_file
->data
== NULL
)
709 domain
= (struct loaded_domain
*) domain_file
->data
;
711 nstrings
= domain
->nstrings
;
713 /* Locate the MSGID and its translation. */
714 if (domain
->hash_tab
!= NULL
)
716 /* Use the hashing table. */
717 nls_uint32 len
= strlen (msgid
);
718 nls_uint32 hash_val
= __hash_string (msgid
);
719 nls_uint32 idx
= hash_val
% domain
->hash_size
;
720 nls_uint32 incr
= 1 + (hash_val
% (domain
->hash_size
- 2));
725 W (domain
->must_swap_hash_tab
, domain
->hash_tab
[idx
]);
728 /* Hash table entry is empty. */
733 /* Compare msgid with the original string at index nstr.
734 We compare the lengths with >=, not ==, because plural entries
735 are represented by strings with an embedded NUL. */
737 ? W (domain
->must_swap
, domain
->orig_tab
[nstr
].length
) >= len
739 domain
->data
+ W (domain
->must_swap
,
740 domain
->orig_tab
[nstr
].offset
))
742 : domain
->orig_sysdep_tab
[nstr
- nstrings
].length
> len
744 domain
->orig_sysdep_tab
[nstr
- nstrings
].pointer
)
751 if (idx
>= domain
->hash_size
- incr
)
752 idx
-= domain
->hash_size
- incr
;
760 /* Try the default method: binary search in the sorted array of
770 act
= (bottom
+ top
) / 2;
771 cmp_val
= strcmp (msgid
, (domain
->data
772 + W (domain
->must_swap
,
773 domain
->orig_tab
[act
].offset
)));
776 else if (cmp_val
> 0)
781 /* No translation was found. */
786 /* The translation was found at index ACT. If we have to convert the
787 string to use a different character set, this is the time. */
791 (domain
->data
+ W (domain
->must_swap
, domain
->trans_tab
[act
].offset
));
792 resultlen
= W (domain
->must_swap
, domain
->trans_tab
[act
].length
) + 1;
796 result
= (char *) domain
->trans_sysdep_tab
[act
- nstrings
].pointer
;
797 resultlen
= domain
->trans_sysdep_tab
[act
- nstrings
].length
;
800 #if defined _LIBC || HAVE_ICONV
803 /* We are supposed to do a conversion. */
804 const char *encoding
= get_output_charset (domainbinding
);
806 /* Search whether a table with converted translations for this
807 encoding has already been allocated. */
808 size_t nconversions
= domain
->nconversions
;
809 struct converted_domain
*convd
= NULL
;
812 for (i
= nconversions
; i
> 0; )
815 if (strcmp (domain
->conversions
[i
].encoding
, encoding
) == 0)
817 convd
= &domain
->conversions
[i
];
824 /* Allocate a table for the converted translations for this
826 struct converted_domain
*new_conversions
=
827 (struct converted_domain
*)
828 (domain
->conversions
!= NULL
829 ? realloc (domain
->conversions
,
830 (nconversions
+ 1) * sizeof (struct converted_domain
))
831 : malloc ((nconversions
+ 1) * sizeof (struct converted_domain
)));
833 if (__builtin_expect (new_conversions
== NULL
, 0))
834 /* Nothing we can do, no more memory. */
836 domain
->conversions
= new_conversions
;
838 /* Copy the 'encoding' string to permanent storage. */
839 encoding
= strdup (encoding
);
840 if (__builtin_expect (encoding
== NULL
, 0))
841 /* Nothing we can do, no more memory. */
844 convd
= &new_conversions
[nconversions
];
845 convd
->encoding
= encoding
;
847 /* Find out about the character set the file is encoded with.
848 This can be found (in textual form) in the entry "". If this
849 entry does not exist or if this does not contain the 'charset='
850 information, we will assume the charset matches the one the
851 current locale and we don't have to perform any conversion. */
853 convd
->conv
= (__gconv_t
) -1;
856 convd
->conv
= (iconv_t
) -1;
863 /* Get the header entry. This is a recursion, but it doesn't
864 reallocate domain->conversions because we pass convert = 0. */
866 _nl_find_msg (domain_file
, domainbinding
, "", 0, &nullentrylen
);
868 if (nullentry
!= NULL
)
870 const char *charsetstr
;
872 charsetstr
= strstr (nullentry
, "charset=");
873 if (charsetstr
!= NULL
)
877 const char *outcharset
;
879 charsetstr
+= strlen ("charset=");
880 len
= strcspn (charsetstr
, " \t\n");
882 charset
= (char *) alloca (len
+ 1);
883 # if defined _LIBC || HAVE_MEMPCPY
884 *((char *) mempcpy (charset
, charsetstr
, len
)) = '\0';
886 memcpy (charset
, charsetstr
, len
);
890 outcharset
= encoding
;
893 /* We always want to use transliteration. */
894 outcharset
= norm_add_slashes (outcharset
, "TRANSLIT");
895 charset
= norm_add_slashes (charset
, "");
896 if (__gconv_open (outcharset
, charset
, &convd
->conv
,
899 convd
->conv
= (__gconv_t
) -1;
902 /* When using GNU libc >= 2.2 or GNU libiconv >= 1.5,
903 we want to use transliteration. */
904 # if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2) || __GLIBC__ > 2 \
905 || _LIBICONV_VERSION >= 0x0105
906 if (strchr (outcharset
, '/') == NULL
)
910 len
= strlen (outcharset
);
911 tmp
= (char *) alloca (len
+ 10 + 1);
912 memcpy (tmp
, outcharset
, len
);
913 memcpy (tmp
+ len
, "//TRANSLIT", 10 + 1);
916 convd
->conv
= iconv_open (outcharset
, charset
);
922 convd
->conv
= iconv_open (outcharset
, charset
);
930 convd
->conv_tab
= NULL
;
931 /* Here domain->conversions is still == new_conversions. */
932 domain
->nconversions
++;
937 convd
->conv
!= (__gconv_t
) -1
940 convd
->conv
!= (iconv_t
) -1
945 /* We are supposed to do a conversion. First allocate an
946 appropriate table with the same structure as the table
947 of translations in the file, where we can put the pointers
948 to the converted strings in.
949 There is a slight complication with plural entries. They
950 are represented by consecutive NUL terminated strings. We
951 handle this case by converting RESULTLEN bytes, including
954 if (convd
->conv_tab
== NULL
955 && ((convd
->conv_tab
=
956 (char **) calloc (nstrings
+ domain
->n_sysdep_strings
,
959 /* Mark that we didn't succeed allocating a table. */
960 convd
->conv_tab
= (char **) -1;
962 if (__builtin_expect (convd
->conv_tab
== (char **) -1, 0))
963 /* Nothing we can do, no more memory. */
966 if (convd
->conv_tab
[act
] == NULL
)
968 /* We haven't used this string so far, so it is not
969 translated yet. Do this now. */
970 /* We use a bit more efficient memory handling.
971 We allocate always larger blocks which get used over
972 time. This is faster than many small allocations. */
973 __libc_lock_define_initialized (static, lock
)
974 # define INITIAL_BLOCK_SIZE 4080
975 static unsigned char *freemem
;
976 static size_t freemem_size
;
978 const unsigned char *inbuf
;
979 unsigned char *outbuf
;
982 transmem_block_t
*transmem_list
= NULL
;
985 __libc_lock_lock (lock
);
987 inbuf
= (const unsigned char *) result
;
988 outbuf
= freemem
+ sizeof (size_t);
993 transmem_block_t
*newmem
;
995 size_t non_reversible
;
998 if (freemem_size
< sizeof (size_t))
1001 res
= __gconv (convd
->conv
,
1002 &inbuf
, inbuf
+ resultlen
,
1004 outbuf
+ freemem_size
- sizeof (size_t),
1007 if (res
== __GCONV_OK
|| res
== __GCONV_EMPTY_INPUT
)
1010 if (res
!= __GCONV_FULL_OUTPUT
)
1012 __libc_lock_unlock (lock
);
1016 inbuf
= (const unsigned char *) result
;
1019 const char *inptr
= (const char *) inbuf
;
1020 size_t inleft
= resultlen
;
1021 char *outptr
= (char *) outbuf
;
1024 if (freemem_size
< sizeof (size_t))
1025 goto resize_freemem
;
1027 outleft
= freemem_size
- sizeof (size_t);
1028 if (iconv (convd
->conv
,
1029 (ICONV_CONST
char **) &inptr
, &inleft
,
1033 outbuf
= (unsigned char *) outptr
;
1038 __libc_lock_unlock (lock
);
1045 /* We must allocate a new buffer or resize the old one. */
1046 if (malloc_count
> 0)
1049 freemem_size
= malloc_count
* INITIAL_BLOCK_SIZE
;
1050 newmem
= (transmem_block_t
*) realloc (transmem_list
,
1054 transmem_list
= transmem_list
->next
;
1057 struct transmem_list
*old
= transmem_list
;
1059 transmem_list
= transmem_list
->next
;
1067 freemem_size
= INITIAL_BLOCK_SIZE
;
1068 newmem
= (transmem_block_t
*) malloc (freemem_size
);
1070 if (__builtin_expect (newmem
== NULL
, 0))
1074 __libc_lock_unlock (lock
);
1079 /* Add the block to the list of blocks we have to free
1081 newmem
->next
= transmem_list
;
1082 transmem_list
= newmem
;
1084 freemem
= (unsigned char *) newmem
->data
;
1085 freemem_size
-= offsetof (struct transmem_list
, data
);
1087 transmem_list
= newmem
;
1091 outbuf
= freemem
+ sizeof (size_t);
1094 /* We have now in our buffer a converted string. Put this
1095 into the table of conversions. */
1096 *(size_t *) freemem
= outbuf
- freemem
- sizeof (size_t);
1097 convd
->conv_tab
[act
] = (char *) freemem
;
1098 /* Shrink freemem, but keep it aligned. */
1099 freemem_size
-= outbuf
- freemem
;
1101 freemem
+= freemem_size
& (alignof (size_t) - 1);
1102 freemem_size
= freemem_size
& ~ (alignof (size_t) - 1);
1104 __libc_lock_unlock (lock
);
1107 /* Now convd->conv_tab[act] contains the translation of all
1108 the plural variants. */
1109 result
= convd
->conv_tab
[act
] + sizeof (size_t);
1110 resultlen
= *(size_t *) convd
->conv_tab
[act
];
1115 /* The result string is converted. */
1117 #endif /* _LIBC || HAVE_ICONV */
1119 *lengthp
= resultlen
;
1124 /* Look up a plural variant. */
1127 plural_lookup (domain
, n
, translation
, translation_len
)
1128 struct loaded_l10nfile
*domain
;
1129 unsigned long int n
;
1130 const char *translation
;
1131 size_t translation_len
;
1133 struct loaded_domain
*domaindata
= (struct loaded_domain
*) domain
->data
;
1134 unsigned long int index
;
1137 index
= plural_eval (domaindata
->plural
, n
);
1138 if (index
>= domaindata
->nplurals
)
1139 /* This should never happen. It means the plural expression and the
1140 given maximum value do not match. */
1143 /* Skip INDEX strings at TRANSLATION. */
1148 p
= __rawmemchr (p
, '\0');
1150 p
= strchr (p
, '\0');
1152 /* And skip over the NUL byte. */
1155 if (p
>= translation
+ translation_len
)
1156 /* This should never happen. It means the plural expression
1157 evaluated to a value larger than the number of variants
1158 available for MSGID1. */
1159 return (char *) translation
;
1165 /* Return string representation of locale CATEGORY. */
1168 category_to_name (category
)
1177 retval
= "LC_COLLATE";
1182 retval
= "LC_CTYPE";
1187 retval
= "LC_MONETARY";
1192 retval
= "LC_NUMERIC";
1202 retval
= "LC_MESSAGES";
1207 retval
= "LC_RESPONSE";
1212 /* This might not make sense but is perhaps better than any other
1218 /* If you have a better idea for a default value let me know. */
1226 /* Guess value of current locale from value of the environment variables. */
1229 guess_category_value (category
, categoryname
)
1231 const char *categoryname
;
1233 const char *language
;
1236 /* The highest priority value is the `LANGUAGE' environment
1237 variable. But we don't use the value if the currently selected
1238 locale is the C locale. This is a GNU extension. */
1239 language
= getenv ("LANGUAGE");
1240 if (language
!= NULL
&& language
[0] == '\0')
1243 /* We have to proceed with the POSIX methods of looking to `LC_ALL',
1244 `LC_xxx', and `LANG'. On some systems this can be done by the
1245 `setlocale' function itself. */
1247 retval
= __current_locale_name (category
);
1249 retval
= _nl_locale_name (category
, categoryname
);
1252 return language
!= NULL
&& strcmp (retval
, "C") != 0 ? language
: retval
;
1255 #if defined _LIBC || HAVE_ICONV
1256 /* Returns the output charset. */
1259 get_output_charset (domainbinding
)
1260 struct binding
*domainbinding
;
1262 /* The output charset should normally be determined by the locale. But
1263 sometimes the locale is not used or not correctly set up, so we provide
1264 a possibility for the user to override this: the OUTPUT_CHARSET
1265 environment variable. Moreover, the value specified through
1266 bind_textdomain_codeset overrides both. */
1267 if (domainbinding
!= NULL
&& domainbinding
->codeset
!= NULL
)
1268 return domainbinding
->codeset
;
1271 /* For speed reasons, we look at the value of OUTPUT_CHARSET only
1272 once. This is a user variable that is not supposed to change
1273 during a program run. */
1274 static char *output_charset_cache
;
1275 static int output_charset_cached
;
1277 if (!output_charset_cached
)
1279 const char *value
= getenv ("OUTPUT_CHARSET");
1281 if (value
!= NULL
&& value
[0] != '\0')
1283 size_t len
= strlen (value
) + 1;
1284 char *value_copy
= (char *) malloc (len
);
1286 if (value_copy
!= NULL
)
1287 memcpy (value_copy
, value
, len
);
1288 output_charset_cache
= value_copy
;
1290 output_charset_cached
= 1;
1293 if (output_charset_cache
!= NULL
)
1294 return output_charset_cache
;
1298 return _NL_CURRENT (LC_CTYPE
, CODESET
);
1301 extern const char *locale_charset
PARAMS ((void);
1302 return locale_charset ();
1310 /* @@ begin of epilog @@ */
1312 /* We don't want libintl.a to depend on any other library. So we
1313 avoid the non-standard function stpcpy. In GNU C Library this
1314 function is available, though. Also allow the symbol HAVE_STPCPY
1316 #if !_LIBC && !HAVE_STPCPY
1322 while ((*dest
++ = *src
++) != '\0')
1328 #if !_LIBC && !HAVE_MEMPCPY
1330 mempcpy (dest
, src
, n
)
1335 return (void *) ((char *) memcpy (dest
, src
, n
) + n
);
1341 /* If we want to free all resources we have to do some work at
1343 libc_freeres_fn (free_mem
)
1347 while (_nl_domain_bindings
!= NULL
)
1349 struct binding
*oldp
= _nl_domain_bindings
;
1350 _nl_domain_bindings
= _nl_domain_bindings
->next
;
1351 if (oldp
->dirname
!= _nl_default_dirname
)
1352 /* Yes, this is a pointer comparison. */
1353 free (oldp
->dirname
);
1354 free (oldp
->codeset
);
1358 if (_nl_current_default_domain
!= _nl_default_default_domain
)
1359 /* Yes, again a pointer comparison. */
1360 free ((char *) _nl_current_default_domain
);
1362 /* Remove the search tree with the known translations. */
1363 __tdestroy (root
, free
);
1366 while (transmem_list
!= NULL
)
1368 old
= transmem_list
;
1369 transmem_list
= transmem_list
->next
;