aboutsummaryrefslogtreecommitdiffstats
path: root/intl/dcigettext.c
diff options
context:
space:
mode:
Diffstat (limited to 'intl/dcigettext.c')
-rw-r--r--intl/dcigettext.c478
1 files changed, 264 insertions, 214 deletions
diff --git a/intl/dcigettext.c b/intl/dcigettext.c
index 5839768..be2dceb 100644
--- a/intl/dcigettext.c
+++ b/intl/dcigettext.c
@@ -1,20 +1,18 @@
/* Implementation of the internal dcigettext function.
- Copyright (C) 1995-1999, 2000-2006 Free Software Foundation, Inc.
+ Copyright (C) 1995-1999, 2000-2010, 2012 Free Software Foundation, Inc.
- This program is free software; you can redistribute it and/or modify it
- under the terms of the GNU Library General Public License as published
- by the Free Software Foundation; either version 2, or (at your option)
- any later version.
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
+ (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
- You should have received a copy of the GNU Library General Public
- License along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
- USA. */
+ You should have received a copy of the GNU Lesser General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
/* Tell glibc's <string.h> to provide a prototype for mempcpy().
This must come before <config.h> because <config.h> may include
@@ -27,9 +25,6 @@
# include <config.h>
#endif
-/* NL_LOCALE_NAME does not work in glibc-2.4. Ignore it. */
-#undef HAVE_NL_LOCALE_NAME
-
#include <sys/types.h>
#ifdef __GNUC__
@@ -90,8 +85,8 @@ extern int errno;
# include <sys/param.h>
#endif
-#if !defined _LIBC && HAVE_NL_LOCALE_NAME
-# include <langinfo.h>
+#if !defined _LIBC
+# include "localcharset.h"
#endif
#include "gettextP.h"
@@ -125,16 +120,6 @@ extern int errno;
((int) &((struct { char dummy1; TYPE dummy2; } *) 0)->dummy2)
#endif
-/* The internal variables in the standalone libintl.a must have different
- names than the internal variables in GNU libc, otherwise programs
- using libintl.a cannot be linked statically. */
-#if !defined _LIBC
-# define _nl_default_default_domain libintl_nl_default_default_domain
-# define _nl_current_default_domain libintl_nl_current_default_domain
-# define _nl_default_dirname libintl_nl_default_dirname
-# define _nl_domain_bindings libintl_nl_domain_bindings
-#endif
-
/* Some compilers, like SunOS4 cc, don't have offsetof in <stddef.h>. */
#ifndef offsetof
# define offsetof(type,ident) ((size_t)&(((type*)0)->ident))
@@ -170,6 +155,22 @@ static void *mempcpy (void *dest, const void *src, size_t n);
# endif
#endif
+/* Use a replacement if the system does not provide the `tsearch' function
+ family. */
+#if HAVE_TSEARCH || defined _LIBC
+# include <search.h>
+#else
+# define tsearch libintl_tsearch
+# define tfind libintl_tfind
+# define tdelete libintl_tdelete
+# define twalk libintl_twalk
+# include "tsearch.h"
+#endif
+
+#ifdef _LIBC
+# define tsearch __tsearch
+#endif
+
/* Amount to increase buffer size by in each try. */
#define PATH_INCR 32
@@ -225,7 +226,7 @@ static void *mempcpy (void *dest, const void *src, size_t n);
#endif
/* Whether to support different locales in different threads. */
-#if defined _LIBC || HAVE_NL_LOCALE_NAME || (HAVE_STRUCT___LOCALE_STRUCT___NAMES && defined USE_IN_GETTEXT_TESTS) || defined IN_LIBGLOCALE
+#if defined _LIBC || HAVE_USELOCALE || defined IN_LIBGLOCALE
# define HAVE_PER_THREAD_LOCALE
#endif
@@ -260,22 +261,19 @@ struct known_translation_t
size_t translation_length;
/* Pointer to the string in question. */
- char msgid[ZERO];
+ union
+ {
+ char appended[ZERO]; /* used if domain != NULL */
+ const char *ptr; /* used if domain == NULL */
+ }
+ msgid;
};
-/* Root of the search tree with known translations. We can use this
- only if the system provides the `tsearch' function family. */
-#if defined HAVE_TSEARCH || defined _LIBC
-# include <search.h>
-
gl_rwlock_define_initialized (static, tree_lock)
+/* Root of the search tree with known translations. */
static void *root;
-# ifdef _LIBC
-# define tsearch __tsearch
-# endif
-
/* Function to compare two entries in the table of known translations. */
static int
transcmp (const void *p1, const void *p2)
@@ -287,7 +285,8 @@ transcmp (const void *p1, const void *p2)
s1 = (const struct known_translation_t *) p1;
s2 = (const struct known_translation_t *) p2;
- result = strcmp (s1->msgid, s2->msgid);
+ result = strcmp (s1->domain != NULL ? s1->msgid.appended : s1->msgid.ptr,
+ s2->domain != NULL ? s2->msgid.appended : s2->msgid.ptr);
if (result == 0)
{
result = strcmp (s1->domainname, s2->domainname);
@@ -312,7 +311,6 @@ transcmp (const void *p1, const void *p2)
return result;
}
-#endif
/* Name of the default domain used for gettext(3) prior any call to
textdomain(3). The default value for this is "messages". */
@@ -374,7 +372,7 @@ static const char *get_output_charset (struct binding *domainbinding)
#endif
-/* For those loosing systems which don't have `alloca' we have to add
+/* For those losing systems which don't have `alloca' we have to add
some additional code emulating it. */
#ifdef HAVE_ALLOCA
/* Nothing has to be done. */
@@ -501,13 +499,10 @@ DCIGETTEXT (const char *domainname, const char *msgid1, const char *msgid2,
char *retval;
size_t retlen;
int saved_errno;
-#if defined HAVE_TSEARCH || defined _LIBC
- struct known_translation_t *search;
+ struct known_translation_t search;
struct known_translation_t **foundp = NULL;
- size_t msgid_len;
-# if defined HAVE_PER_THREAD_LOCALE && !defined IN_LIBGLOCALE
+#if defined HAVE_PER_THREAD_LOCALE && !defined IN_LIBGLOCALE
const char *localename;
-# endif
#endif
size_t domainname_len;
@@ -524,6 +519,14 @@ DCIGETTEXT (const char *domainname, const char *msgid1, const char *msgid2,
: n == 1 ? (char *) msgid1 : (char *) msgid2);
#endif
+ /* Preserve the `errno' value. */
+ saved_errno = errno;
+
+#ifdef _LIBC
+ __libc_rwlock_define (extern, __libc_setlocale_lock attribute_hidden)
+ __libc_rwlock_rdlock (__libc_setlocale_lock);
+#endif
+
gl_rwlock_rdlock (_nl_state_lock);
/* If DOMAINNAME is NULL, we are interested in the default domain. If
@@ -538,54 +541,37 @@ DCIGETTEXT (const char *domainname, const char *msgid1, const char *msgid2,
category = LC_MESSAGES;
#endif
-#if defined HAVE_TSEARCH || defined _LIBC
- msgid_len = strlen (msgid1) + 1;
-
/* Try to find the translation among those which we found at
some time. */
- search = (struct known_translation_t *)
- alloca (offsetof (struct known_translation_t, msgid) + msgid_len);
- memcpy (search->msgid, msgid1, msgid_len);
- search->domainname = domainname;
- search->category = category;
-# ifdef HAVE_PER_THREAD_LOCALE
-# ifndef IN_LIBGLOCALE
-# ifdef _LIBC
- localename = __current_locale_name (category);
-# else
-# if HAVE_NL_LOCALE_NAME
- /* NL_LOCALE_NAME is public glibc API introduced in glibc-2.4. */
- localename = nl_langinfo (NL_LOCALE_NAME (category));
-# else
-# if HAVE_STRUCT___LOCALE_STRUCT___NAMES && defined USE_IN_GETTEXT_TESTS
- /* The __names field is not public glibc API and must therefore not be used
- in code that is installed in public locations. */
- {
- locale_t thread_locale = uselocale (NULL);
- if (thread_locale != LC_GLOBAL_LOCALE)
- localename = thread_locale->__names[category];
- else
- localename = "";
- }
-# endif
-# endif
-# endif
-# endif
- search->localename = localename;
-# ifdef IN_LIBGLOCALE
- search->encoding = encoding;
+ search.domain = NULL;
+ search.msgid.ptr = msgid1;
+ search.domainname = domainname;
+ search.category = category;
+#ifdef HAVE_PER_THREAD_LOCALE
+# ifndef IN_LIBGLOCALE
+# ifdef _LIBC
+ localename = _strdupa (_current_locale_name (category));
+# else
+ categoryname = category_to_name (category);
+# define CATEGORYNAME_INITIALIZED
+ localename = _nl_locale_name_thread_unsafe (category, categoryname);
+ if (localename == NULL)
+ localename = "";
# endif
# endif
+ search.localename = localename;
+# ifdef IN_LIBGLOCALE
+ search.encoding = encoding;
+# endif
/* Since tfind/tsearch manage a balanced tree, concurrent tfind and
tsearch calls can be fatal. */
gl_rwlock_rdlock (tree_lock);
- foundp = (struct known_translation_t **) tfind (search, &root, transcmp);
+ foundp = (struct known_translation_t **) tfind (&search, &root, transcmp);
gl_rwlock_unlock (tree_lock);
- freea (search);
if (foundp != NULL && (*foundp)->counter == _nl_msg_cat_cntr)
{
/* Now deal with plural. */
@@ -596,13 +582,14 @@ DCIGETTEXT (const char *domainname, const char *msgid1, const char *msgid2,
retval = (char *) (*foundp)->translation;
gl_rwlock_unlock (_nl_state_lock);
+# ifdef _LIBC
+ __libc_rwlock_unlock (__libc_setlocale_lock);
+# endif
+ __set_errno (saved_errno);
return retval;
}
#endif
- /* Preserve the `errno' value. */
- saved_errno = errno;
-
/* See whether this is a SUID binary or not. */
DETERMINE_SECURE;
@@ -671,7 +658,9 @@ DCIGETTEXT (const char *domainname, const char *msgid1, const char *msgid2,
#endif
/* Now determine the symbolic name of CATEGORY and its value. */
+#ifndef CATEGORYNAME_INITIALIZED
categoryname = category_to_name (category);
+#endif
#ifdef IN_LIBGLOCALE
categoryvalue = guess_category_value (category, categoryname, localename);
#else
@@ -683,8 +672,8 @@ DCIGETTEXT (const char *domainname, const char *msgid1, const char *msgid2,
+ domainname_len + 5);
ADD_BLOCK (block_list, xdomainname);
- stpcpy (mempcpy (stpcpy (stpcpy (xdomainname, categoryname), "/"),
- domainname, domainname_len),
+ stpcpy ((char *) mempcpy (stpcpy (stpcpy (xdomainname, categoryname), "/"),
+ domainname, domainname_len),
".mo");
/* Creating working area. */
@@ -773,40 +762,43 @@ DCIGETTEXT (const char *domainname, const char *msgid1, const char *msgid2,
/* Found the translation of MSGID1 in domain DOMAIN:
starting at RETVAL, RETLEN bytes. */
FREE_BLOCKS (block_list);
-#if defined HAVE_TSEARCH || defined _LIBC
if (foundp == NULL)
{
/* Create a new entry and add it to the search tree. */
+ size_t msgid_len;
size_t size;
struct known_translation_t *newp;
+ msgid_len = strlen (msgid1) + 1;
size = offsetof (struct known_translation_t, msgid)
+ msgid_len + domainname_len + 1;
-# ifdef HAVE_PER_THREAD_LOCALE
+#ifdef HAVE_PER_THREAD_LOCALE
size += strlen (localename) + 1;
-# endif
+#endif
newp = (struct known_translation_t *) malloc (size);
if (newp != NULL)
{
char *new_domainname;
-# ifdef HAVE_PER_THREAD_LOCALE
+#ifdef HAVE_PER_THREAD_LOCALE
char *new_localename;
-# endif
+#endif
- new_domainname = mempcpy (newp->msgid, msgid1, msgid_len);
+ new_domainname =
+ (char *) mempcpy (newp->msgid.appended, msgid1,
+ msgid_len);
memcpy (new_domainname, domainname, domainname_len + 1);
-# ifdef HAVE_PER_THREAD_LOCALE
+#ifdef HAVE_PER_THREAD_LOCALE
new_localename = new_domainname + domainname_len + 1;
strcpy (new_localename, localename);
-# endif
+#endif
newp->domainname = new_domainname;
newp->category = category;
-# ifdef HAVE_PER_THREAD_LOCALE
+#ifdef HAVE_PER_THREAD_LOCALE
newp->localename = new_localename;
-# endif
-# ifdef IN_LIBGLOCALE
+#endif
+#ifdef IN_LIBGLOCALE
newp->encoding = encoding;
-# endif
+#endif
newp->counter = _nl_msg_cat_cntr;
newp->domain = domain;
newp->translation = retval;
@@ -834,7 +826,7 @@ DCIGETTEXT (const char *domainname, const char *msgid1, const char *msgid2,
(*foundp)->translation = retval;
(*foundp)->translation_length = retlen;
}
-#endif
+
__set_errno (saved_errno);
/* Now deal with plural. */
@@ -842,6 +834,9 @@ DCIGETTEXT (const char *domainname, const char *msgid1, const char *msgid2,
retval = plural_lookup (domain, n, retval, retlen);
gl_rwlock_unlock (_nl_state_lock);
+#ifdef _LIBC
+ __libc_rwlock_unlock (__libc_setlocale_lock);
+#endif
return retval;
}
}
@@ -851,6 +846,9 @@ DCIGETTEXT (const char *domainname, const char *msgid1, const char *msgid2,
/* Return the untranslated MSGID. */
FREE_BLOCKS (block_list);
gl_rwlock_unlock (_nl_state_lock);
+#ifdef _LIBC
+ __libc_rwlock_unlock (__libc_setlocale_lock);
+#endif
#ifndef _LIBC
if (!ENABLE_SECURE)
{
@@ -1005,12 +1003,17 @@ _nl_find_msg (struct loaded_l10nfile *domain_file,
# ifndef IN_LIBGLOCALE
const char *encoding = get_output_charset (domainbinding);
# endif
+ size_t nconversions;
+ struct converted_domain *convd;
+ size_t i;
+
+ /* Protect against reallocation of the table. */
+ gl_rwlock_rdlock (domain->conversions_lock);
/* Search whether a table with converted translations for this
encoding has already been allocated. */
- size_t nconversions = domain->nconversions;
- struct converted_domain *convd = NULL;
- size_t i;
+ nconversions = domain->nconversions;
+ convd = NULL;
for (i = nconversions; i > 0; )
{
@@ -1022,134 +1025,166 @@ _nl_find_msg (struct loaded_l10nfile *domain_file,
}
}
+ gl_rwlock_unlock (domain->conversions_lock);
+
if (convd == NULL)
{
- /* Allocate a table for the converted translations for this
- encoding. */
- struct converted_domain *new_conversions =
- (struct converted_domain *)
- (domain->conversions != NULL
- ? realloc (domain->conversions,
- (nconversions + 1) * sizeof (struct converted_domain))
- : malloc ((nconversions + 1) * sizeof (struct converted_domain)));
-
- if (__builtin_expect (new_conversions == NULL, 0))
- /* Nothing we can do, no more memory. We cannot use the
- translation because it might be encoded incorrectly. */
- return (char *) -1;
+ /* We have to allocate a new conversions table. */
+ gl_rwlock_wrlock (domain->conversions_lock);
+ nconversions = domain->nconversions;
- domain->conversions = new_conversions;
+ /* Maybe in the meantime somebody added the translation.
+ Recheck. */
+ for (i = nconversions; i > 0; )
+ {
+ i--;
+ if (strcmp (domain->conversions[i].encoding, encoding) == 0)
+ {
+ convd = &domain->conversions[i];
+ goto found_convd;
+ }
+ }
- /* Copy the 'encoding' string to permanent storage. */
- encoding = strdup (encoding);
- if (__builtin_expect (encoding == NULL, 0))
- /* Nothing we can do, no more memory. We cannot use the
- translation because it might be encoded incorrectly. */
- return (char *) -1;
+ {
+ /* Allocate a table for the converted translations for this
+ encoding. */
+ struct converted_domain *new_conversions =
+ (struct converted_domain *)
+ (domain->conversions != NULL
+ ? realloc (domain->conversions,
+ (nconversions + 1) * sizeof (struct converted_domain))
+ : malloc ((nconversions + 1) * sizeof (struct converted_domain)));
+
+ if (__builtin_expect (new_conversions == NULL, 0))
+ {
+ /* Nothing we can do, no more memory. We cannot use the
+ translation because it might be encoded incorrectly. */
+ unlock_fail:
+ gl_rwlock_unlock (domain->conversions_lock);
+ return (char *) -1;
+ }
+
+ domain->conversions = new_conversions;
- convd = &new_conversions[nconversions];
- convd->encoding = encoding;
+ /* Copy the 'encoding' string to permanent storage. */
+ encoding = strdup (encoding);
+ if (__builtin_expect (encoding == NULL, 0))
+ /* Nothing we can do, no more memory. We cannot use the
+ translation because it might be encoded incorrectly. */
+ goto unlock_fail;
- /* Find out about the character set the file is encoded with.
- This can be found (in textual form) in the entry "". If this
- entry does not exist or if this does not contain the 'charset='
- information, we will assume the charset matches the one the
- current locale and we don't have to perform any conversion. */
+ convd = &new_conversions[nconversions];
+ convd->encoding = encoding;
+
+ /* Find out about the character set the file is encoded with.
+ This can be found (in textual form) in the entry "". If this
+ entry does not exist or if this does not contain the 'charset='
+ information, we will assume the charset matches the one the
+ current locale and we don't have to perform any conversion. */
# ifdef _LIBC
- convd->conv = (__gconv_t) -1;
+ convd->conv = (__gconv_t) -1;
# else
# if HAVE_ICONV
- convd->conv = (iconv_t) -1;
+ convd->conv = (iconv_t) -1;
# endif
# endif
- {
- char *nullentry;
- size_t nullentrylen;
+ {
+ char *nullentry;
+ size_t nullentrylen;
- /* Get the header entry. This is a recursion, but it doesn't
- reallocate domain->conversions because we pass
- encoding = NULL or convert = 0, respectively. */
- nullentry =
+ /* Get the header entry. This is a recursion, but it doesn't
+ reallocate domain->conversions because we pass
+ encoding = NULL or convert = 0, respectively. */
+ nullentry =
# ifdef IN_LIBGLOCALE
- _nl_find_msg (domain_file, domainbinding, NULL, "",
- &nullentrylen);
+ _nl_find_msg (domain_file, domainbinding, NULL, "",
+ &nullentrylen);
# else
- _nl_find_msg (domain_file, domainbinding, "", 0, &nullentrylen);
+ _nl_find_msg (domain_file, domainbinding, "", 0, &nullentrylen);
# endif
- if (nullentry != NULL)
- {
- const char *charsetstr;
+ if (nullentry != NULL)
+ {
+ const char *charsetstr;
- charsetstr = strstr (nullentry, "charset=");
- if (charsetstr != NULL)
- {
- size_t len;
- char *charset;
- const char *outcharset;
+ charsetstr = strstr (nullentry, "charset=");
+ if (charsetstr != NULL)
+ {
+ size_t len;
+ char *charset;
+ const char *outcharset;
- charsetstr += strlen ("charset=");
- len = strcspn (charsetstr, " \t\n");
+ charsetstr += strlen ("charset=");
+ len = strcspn (charsetstr, " \t\n");
- charset = (char *) alloca (len + 1);
+ charset = (char *) alloca (len + 1);
# if defined _LIBC || HAVE_MEMPCPY
- *((char *) mempcpy (charset, charsetstr, len)) = '\0';
+ *((char *) mempcpy (charset, charsetstr, len)) = '\0';
# else
- memcpy (charset, charsetstr, len);
- charset[len] = '\0';
+ memcpy (charset, charsetstr, len);
+ charset[len] = '\0';
# endif
- outcharset = encoding;
+ outcharset = encoding;
# ifdef _LIBC
- /* We always want to use transliteration. */
- outcharset = norm_add_slashes (outcharset, "TRANSLIT");
- charset = norm_add_slashes (charset, "");
- int r = __gconv_open (outcharset, charset, &convd->conv,
- GCONV_AVOID_NOCONV);
- if (__builtin_expect (r != __GCONV_OK, 0))
- {
- /* If the output encoding is the same there is
- nothing to do. Otherwise do not use the
- translation at all. */
- if (__builtin_expect (r != __GCONV_NOCONV, 1))
- return NULL;
-
- convd->conv = (__gconv_t) -1;
- }
+ /* We always want to use transliteration. */
+ outcharset = norm_add_slashes (outcharset, "TRANSLIT");
+ charset = norm_add_slashes (charset, "");
+ int r = __gconv_open (outcharset, charset, &convd->conv,
+ GCONV_AVOID_NOCONV);
+ if (__builtin_expect (r != __GCONV_OK, 0))
+ {
+ /* If the output encoding is the same there is
+ nothing to do. Otherwise do not use the
+ translation at all. */
+ if (__builtin_expect (r != __GCONV_NULCONV, 1))
+ {
+ gl_rwlock_unlock (domain->conversions_lock);
+ free ((char *) encoding);
+ return NULL;
+ }
+
+ convd->conv = (__gconv_t) -1;
+ }
# else
# if HAVE_ICONV
- /* When using GNU libc >= 2.2 or GNU libiconv >= 1.5,
- we want to use transliteration. */
-# if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2) || __GLIBC__ > 2 \
+ /* When using GNU libc >= 2.2 or GNU libiconv >= 1.5,
+ we want to use transliteration. */
+# if (((__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2) || __GLIBC__ > 2) \
+ && !defined __UCLIBC__) \
|| _LIBICONV_VERSION >= 0x0105
- if (strchr (outcharset, '/') == NULL)
- {
- char *tmp;
+ if (strchr (outcharset, '/') == NULL)
+ {
+ char *tmp;
- len = strlen (outcharset);
- tmp = (char *) alloca (len + 10 + 1);
- memcpy (tmp, outcharset, len);
- memcpy (tmp + len, "//TRANSLIT", 10 + 1);
- outcharset = tmp;
+ len = strlen (outcharset);
+ tmp = (char *) alloca (len + 10 + 1);
+ memcpy (tmp, outcharset, len);
+ memcpy (tmp + len, "//TRANSLIT", 10 + 1);
+ outcharset = tmp;
- convd->conv = iconv_open (outcharset, charset);
+ convd->conv = iconv_open (outcharset, charset);
- freea (outcharset);
- }
- else
+ freea (outcharset);
+ }
+ else
# endif
- convd->conv = iconv_open (outcharset, charset);
+ convd->conv = iconv_open (outcharset, charset);
# endif
# endif
- freea (charset);
- }
- }
+ freea (charset);
+ }
+ }
+ }
+ convd->conv_tab = NULL;
+ /* Here domain->conversions is still == new_conversions. */
+ domain->nconversions++;
}
- convd->conv_tab = NULL;
- /* Here domain->conversions is still == new_conversions. */
- domain->nconversions++;
+
+ found_convd:
+ gl_rwlock_unlock (domain->conversions_lock);
}
if (
@@ -1171,13 +1206,29 @@ _nl_find_msg (struct loaded_l10nfile *domain_file,
handle this case by converting RESULTLEN bytes, including
NULs. */
- if (convd->conv_tab == NULL
- && ((convd->conv_tab =
+ /* This lock primarily protects the memory management variables
+ freemem, freemem_size. It also protects write accesses to
+ convd->conv_tab. It's not worth using a separate lock (such
+ as domain->conversions_lock) for this purpose, because when
+ modifying convd->conv_tab, we also need to lock freemem,
+ freemem_size for most of the time. */
+ __libc_lock_define_initialized (static, lock)
+
+ if (__builtin_expect (convd->conv_tab == NULL, 0))
+ {
+ __libc_lock_lock (lock);
+ if (convd->conv_tab == NULL)
+ {
+ convd->conv_tab =
(char **) calloc (nstrings + domain->n_sysdep_strings,
- sizeof (char *)))
- == NULL))
- /* Mark that we didn't succeed allocating a table. */
- convd->conv_tab = (char **) -1;
+ sizeof (char *));
+ if (convd->conv_tab != NULL)
+ goto not_translated_yet;
+ /* Mark that we didn't succeed allocating a table. */
+ convd->conv_tab = (char **) -1;
+ }
+ __libc_lock_unlock (lock);
+ }
if (__builtin_expect (convd->conv_tab == (char **) -1, 0))
/* Nothing we can do, no more memory. We cannot use the
@@ -1191,7 +1242,6 @@ _nl_find_msg (struct loaded_l10nfile *domain_file,
/* We use a bit more efficient memory handling.
We allocate always larger blocks which get used over
time. This is faster than many small allocations. */
- __libc_lock_define_initialized (static, lock)
# define INITIAL_BLOCK_SIZE 4080
static unsigned char *freemem;
static size_t freemem_size;
@@ -1200,13 +1250,17 @@ _nl_find_msg (struct loaded_l10nfile *domain_file,
unsigned char *outbuf;
int malloc_count;
# ifndef _LIBC
- transmem_block_t *transmem_list = NULL;
+ transmem_block_t *transmem_list;
# endif
__libc_lock_lock (lock);
+ not_translated_yet:
inbuf = (const unsigned char *) result;
outbuf = freemem + sizeof (size_t);
+# ifndef _LIBC
+ transmem_list = NULL;
+# endif
malloc_count = 0;
while (1)
@@ -1483,20 +1537,13 @@ guess_category_value (int category, const char *categoryname)
# ifdef _LIBC
locale = __current_locale_name (category);
# else
-# if HAVE_STRUCT___LOCALE_STRUCT___NAMES && defined USE_IN_GETTEXT_TESTS
- /* The __names field is not public glibc API and must therefore not be used
- in code that is installed in public locations. */
- locale_t thread_locale = uselocale (NULL);
- if (thread_locale != LC_GLOBAL_LOCALE)
- {
- locale = thread_locale->__names[category];
- locale_defaulted = 0;
- }
- else
+ locale_defaulted = 0;
+# if HAVE_USELOCALE
+ locale = _nl_locale_name_thread_unsafe (category, categoryname);
+ if (locale == NULL)
# endif
{
locale = _nl_locale_name_posix (category, categoryname);
- locale_defaulted = 0;
if (locale == NULL)
{
locale = _nl_locale_name_default ();
@@ -1584,7 +1631,6 @@ get_output_charset (struct binding *domainbinding)
return _NL_CURRENT (LC_CTYPE, CODESET);
# else
# if HAVE_ICONV
- extern const char *locale_charset (void);
return locale_charset ();
# endif
# endif
@@ -1617,6 +1663,10 @@ mempcpy (void *dest, const void *src, size_t n)
}
#endif
+#if !_LIBC && !HAVE_TSEARCH
+# include "tsearch.c"
+#endif
+
#ifdef _LIBC
/* If we want to free all resources we have to do some work at