summaryrefslogtreecommitdiff
path: root/intl/loadmsgcat.c
diff options
context:
space:
mode:
Diffstat (limited to 'intl/loadmsgcat.c')
-rw-r--r--intl/loadmsgcat.c172
1 files changed, 149 insertions, 23 deletions
diff --git a/intl/loadmsgcat.c b/intl/loadmsgcat.c
index 1f55531097..efefc69a43 100644
--- a/intl/loadmsgcat.c
+++ b/intl/loadmsgcat.c
@@ -1,5 +1,5 @@
/* Load needed message catalogs.
- Copyright (C) 1995-2005 Free Software Foundation, Inc.
+ Copyright (C) 1995-2004 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -752,6 +752,146 @@ get_sysdep_segment_value (name)
return NULL;
}
+/* Initialize the codeset dependent parts of an opened message catalog.
+ Return the header entry. */
+const char *
+internal_function
+_nl_init_domain_conv (domain_file, domain, domainbinding)
+ struct loaded_l10nfile *domain_file;
+ struct loaded_domain *domain;
+ struct binding *domainbinding;
+{
+ /* 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. */
+ char *nullentry;
+ size_t nullentrylen;
+
+ /* Preinitialize fields, to avoid recursion during _nl_find_msg. */
+ domain->codeset_cntr =
+ (domainbinding != NULL ? domainbinding->codeset_cntr : 0);
+#ifdef _LIBC
+ domain->conv = (__gconv_t) -1;
+#else
+# if HAVE_ICONV
+ domain->conv = (iconv_t) -1;
+# endif
+#endif
+ domain->conv_tab = NULL;
+
+ /* Get the header entry. */
+ nullentry = _nl_find_msg (domain_file, domainbinding, "", &nullentrylen);
+
+ if (nullentry != NULL)
+ {
+#if defined _LIBC || HAVE_ICONV
+ const char *charsetstr;
+
+ charsetstr = strstr (nullentry, "charset=");
+ if (charsetstr != NULL)
+ {
+ size_t len;
+ char *charset;
+ const char *outcharset;
+
+ charsetstr += strlen ("charset=");
+ len = strcspn (charsetstr, " \t\n");
+
+ charset = (char *) alloca (len + 1);
+# if defined _LIBC || HAVE_MEMPCPY
+ *((char *) mempcpy (charset, charsetstr, len)) = '\0';
+# else
+ memcpy (charset, charsetstr, len);
+ charset[len] = '\0';
+# endif
+
+ /* The output charset should normally be determined by the
+ locale. But sometimes the locale is not used or not correctly
+ set up, so we provide a possibility for the user to override
+ this. Moreover, the value specified through
+ bind_textdomain_codeset overrides both. */
+ if (domainbinding != NULL && domainbinding->codeset != NULL)
+ outcharset = domainbinding->codeset;
+ else
+ {
+ outcharset = getenv ("OUTPUT_CHARSET");
+ if (outcharset == NULL || outcharset[0] == '\0')
+ {
+# ifdef _LIBC
+ outcharset = _NL_CURRENT (LC_CTYPE, CODESET);
+# else
+# if HAVE_ICONV
+ extern const char *locale_charset PARAMS ((void));
+ outcharset = locale_charset ();
+# endif
+# endif
+ }
+ }
+
+# ifdef _LIBC
+ /* We always want to use transliteration. */
+ outcharset = norm_add_slashes (outcharset, "TRANSLIT");
+ charset = norm_add_slashes (charset, "");
+ if (__gconv_open (outcharset, charset, &domain->conv,
+ GCONV_AVOID_NOCONV)
+ != __GCONV_OK)
+ domain->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 \
+ || _LIBICONV_VERSION >= 0x0105
+ 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;
+
+ domain->conv = iconv_open (outcharset, charset);
+
+ freea (outcharset);
+ }
+ else
+# endif
+ domain->conv = iconv_open (outcharset, charset);
+# endif
+# endif
+
+ freea (charset);
+ }
+#endif /* _LIBC || HAVE_ICONV */
+ }
+
+ return nullentry;
+}
+
+/* Frees the codeset dependent parts of an opened message catalog. */
+void
+internal_function
+_nl_free_domain_conv (domain)
+ struct loaded_domain *domain;
+{
+ if (domain->conv_tab != NULL && domain->conv_tab != (char **) -1)
+ free (domain->conv_tab);
+
+#ifdef _LIBC
+ if (domain->conv != (__gconv_t) -1)
+ __gconv_close (domain->conv);
+#else
+# if HAVE_ICONV
+ if (domain->conv != (iconv_t) -1)
+ iconv_close (domain->conv);
+# endif
+#endif
+}
+
/* Load the message catalogs specified by FILENAME. If it is no valid
message catalog do nothing. */
void
@@ -773,7 +913,6 @@ _nl_load_domain (domain_file, domainbinding)
struct loaded_domain *domain;
int revision;
const char *nullentry;
- size_t nullentrylen;
__libc_lock_lock_recursive (lock);
if (domain_file->decided != 0)
@@ -781,8 +920,8 @@ _nl_load_domain (domain_file, domainbinding)
/* There are two possibilities:
+ is is the same thread calling again during this
- initialization via _nl_find_msg. We have initialized
- everything this call needs.
+ initialization via _nl_init_domain_conv and _nl_find_msg. We
+ have initialized everything this call needs.
+ this is another thread which tried to initialize this object.
Not necessary anymore since if the lock is available this
@@ -1249,12 +1388,12 @@ _nl_load_domain (domain_file, domainbinding)
goto out;
}
- /* No caches of converted translations so far. */
- domain->conversions = NULL;
- domain->nconversions = 0;
+ /* Now initialize the character set converter from the character set
+ the file is encoded with (found in the header entry) to the domain's
+ specified character set or the locale's character set. */
+ nullentry = _nl_init_domain_conv (domain_file, domain, domainbinding);
- /* Get the header entry and look for a plural specification. */
- nullentry = _nl_find_msg (domain_file, domainbinding, "", 0, &nullentrylen);
+ /* Also look for a plural specification. */
EXTRACT_PLURAL_EXPRESSION (nullentry, &domain->plural, &domain->nplurals);
out:
@@ -1273,23 +1412,10 @@ internal_function __libc_freeres_fn_section
_nl_unload_domain (domain)
struct loaded_domain *domain;
{
- size_t i;
-
if (domain->plural != &__gettext_germanic_plural)
__gettext_free_exp (domain->plural);
- for (i = 0; i < domain->nconversions; i++)
- {
- struct converted_domain *convd = &domain->conversions[i];
-
- free ((char *) convd->encoding);
- if (convd->conv_tab != NULL && convd->conv_tab != (char **) -1)
- free (convd->conv_tab);
- if (convd->conv != (__gconv_t) -1)
- __gconv_close (convd->conv);
- }
- if (domain->conversions != NULL)
- free (domain->conversions);
+ _nl_free_domain_conv (domain);
if (domain->malloced)
free (domain->malloced);