summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--intl/ChangeLog25
-rw-r--r--intl/bindtextdom.c4
-rw-r--r--intl/dcigettext.c21
-rw-r--r--intl/finddomain.c14
-rw-r--r--intl/gettextP.h16
-rw-r--r--intl/l10nflist.c7
-rw-r--r--intl/loadinfo.h9
-rw-r--r--intl/loadmsgcat.c232
8 files changed, 214 insertions, 114 deletions
diff --git a/intl/ChangeLog b/intl/ChangeLog
index 94a35a4..c40ec3c 100644
--- a/intl/ChangeLog
+++ b/intl/ChangeLog
@@ -1,3 +1,28 @@
+2001-04-07 Bruno Haible <haible@clisp.cons.org>
+
+ * gettextP.h (struct loaded_domain): Add codeset_cntr field.
+ (struct binding): Add codeset_cntr field.
+ (_nl_load_domain): Add domainbinding argument.
+ (_nl_init_domain_conv, _nl_free_domain_conv): New declarations.
+ (_nl_find_msg): New declaration, moved here from loadinfo.h.
+ * loadinfo.h (struct loaded_l10nfile): Remove domainbinding field.
+ (_nl_make_l10nflist): Remove domainbinding argument.
+ (_nl_find_msg): Move declaration to gettextP.h.
+ * bindtextdom.c (set_binding_values): Initialize ->codeset_cntr to 0.
+ Increment it when ->codeset is changed.
+ * dcigettext.c (DCIGETTEXT): Pass binding to _nl_find_msg.
+ (_nl_find_msg): Add domainbinding argument. Reinitialize the converter
+ if domainbinding->codeset_cntr has been incremented.
+ * finddomain.c (_nl_find_domain): Don't pass domainbinding to
+ _nl_make_l10nflist(). Pass it to _nl_load_domain() instead.
+ * l10nflist.c (_nl_make_l10nflist): Remove domainbinding argument.
+ * loadmsgcat.c (_nl_init_domain_conv): New function, extracted from
+ _nl_load_domain. Append //TRANSLIT also when using libiconv.
+ (_nl_free_domain_conv): New function, extracted from _nl_unload_domain.
+ (_nl_load_domain): Add domainbinding argument. Call
+ _nl_init_domain_conv.
+ (_nl_unload_domain): Call _nl_free_domain_conv.
+
2001-04-09 Bruno Haible <haible@clisp.cons.org>
* dcigettext.c (HAVE_LOCALE_NULL): Don't define if __GNU_LIBRARY__ < 2
diff --git a/intl/bindtextdom.c b/intl/bindtextdom.c
index 602a651..7e5a74a 100644
--- a/intl/bindtextdom.c
+++ b/intl/bindtextdom.c
@@ -202,6 +202,7 @@ set_binding_values (domainname, dirnamep, codesetp)
free (binding->codeset);
binding->codeset = result;
+ binding->codeset_cntr++;
modified = 1;
}
}
@@ -265,6 +266,8 @@ set_binding_values (domainname, dirnamep, codesetp)
/* The default value. */
new_binding->dirname = (char *) _nl_default_dirname;
+ new_binding->codeset_cntr = 0;
+
if (codesetp)
{
const char *codeset = *codesetp;
@@ -285,6 +288,7 @@ set_binding_values (domainname, dirnamep, codesetp)
memcpy (result, codeset, len);
#endif
codeset = result;
+ new_binding->codeset_cntr++;
}
*codesetp = codeset;
new_binding->codeset = (char *) codeset;
diff --git a/intl/dcigettext.c b/intl/dcigettext.c
index f364cf9..6ee9d17 100644
--- a/intl/dcigettext.c
+++ b/intl/dcigettext.c
@@ -584,7 +584,7 @@ DCIGETTEXT (domainname, msgid1, msgid2, plural, n, category)
if (domain != NULL)
{
- retval = _nl_find_msg (domain, msgid1, &retlen);
+ retval = _nl_find_msg (domain, binding, msgid1, &retlen);
if (retval == NULL)
{
@@ -592,8 +592,8 @@ DCIGETTEXT (domainname, msgid1, msgid2, plural, n, category)
for (cnt = 0; domain->successor[cnt] != NULL; ++cnt)
{
- retval = _nl_find_msg (domain->successor[cnt], msgid1,
- &retlen);
+ retval = _nl_find_msg (domain->successor[cnt], binding,
+ msgid1, &retlen);
if (retval != NULL)
{
@@ -662,8 +662,9 @@ DCIGETTEXT (domainname, msgid1, msgid2, plural, n, category)
char *
internal_function
-_nl_find_msg (domain_file, msgid, lengthp)
+_nl_find_msg (domain_file, domainbinding, msgid, lengthp)
struct loaded_l10nfile *domain_file;
+ struct binding *domainbinding;
const char *msgid;
size_t *lengthp;
{
@@ -673,7 +674,7 @@ _nl_find_msg (domain_file, msgid, lengthp)
size_t resultlen;
if (domain_file->decided == 0)
- _nl_load_domain (domain_file);
+ _nl_load_domain (domain_file, domainbinding);
if (domain_file->data == NULL)
return NULL;
@@ -752,6 +753,16 @@ _nl_find_msg (domain_file, msgid, lengthp)
resultlen = W (domain->must_swap, domain->trans_tab[act].length) + 1;
#if defined _LIBC || HAVE_ICONV
+ if (domain->codeset_cntr
+ != (domainbinding != NULL ? domainbinding->codeset_cntr : 0))
+ {
+ /* The domain's codeset has changed through bind_textdomain_codeset()
+ since the message catalog was initialized or last accessed. We
+ have to reinitialize the converter. */
+ _nl_free_domain_conv (domain);
+ _nl_init_domain_conv (domain_file, domain, domainbinding);
+ }
+
if (
# ifdef _LIBC
domain->conv != (__gconv_t) -1
diff --git a/intl/finddomain.c b/intl/finddomain.c
index fdcae62..4882554 100644
--- a/intl/finddomain.c
+++ b/intl/finddomain.c
@@ -89,15 +89,14 @@ _nl_find_domain (dirname, locale, domainname, domainbinding)
be one data set in the list of loaded domains. */
retval = _nl_make_l10nflist (&_nl_loaded_domains, dirname,
strlen (dirname) + 1, 0, locale, NULL, NULL,
- NULL, NULL, NULL, NULL, NULL, domainname,
- domainbinding, 0);
+ NULL, NULL, NULL, NULL, NULL, domainname, 0);
if (retval != NULL)
{
/* We know something about this locale. */
int cnt;
if (retval->decided == 0)
- _nl_load_domain (retval);
+ _nl_load_domain (retval, domainbinding);
if (retval->data != NULL)
return retval;
@@ -105,7 +104,7 @@ _nl_find_domain (dirname, locale, domainname, domainbinding)
for (cnt = 0; retval->successor[cnt] != NULL; ++cnt)
{
if (retval->successor[cnt]->decided == 0)
- _nl_load_domain (retval->successor[cnt]);
+ _nl_load_domain (retval->successor[cnt], domainbinding);
if (retval->successor[cnt]->data != NULL)
break;
@@ -146,21 +145,20 @@ _nl_find_domain (dirname, locale, domainname, domainbinding)
retval = _nl_make_l10nflist (&_nl_loaded_domains, dirname,
strlen (dirname) + 1, mask, language, territory,
codeset, normalized_codeset, modifier, special,
- sponsor, revision, domainname, domainbinding,
- 1);
+ sponsor, revision, domainname, 1);
if (retval == NULL)
/* This means we are out of core. */
return NULL;
if (retval->decided == 0)
- _nl_load_domain (retval);
+ _nl_load_domain (retval, domainbinding);
if (retval->data == NULL)
{
int cnt;
for (cnt = 0; retval->successor[cnt] != NULL; ++cnt)
{
if (retval->successor[cnt]->decided == 0)
- _nl_load_domain (retval->successor[cnt]);
+ _nl_load_domain (retval->successor[cnt], domainbinding);
if (retval->successor[cnt]->data != NULL)
break;
}
diff --git a/intl/gettextP.h b/intl/gettextP.h
index c7f4655..ee8ca48 100644
--- a/intl/gettextP.h
+++ b/intl/gettextP.h
@@ -128,6 +128,7 @@ struct loaded_domain
struct string_desc *trans_tab;
nls_uint32 hash_size;
nls_uint32 *hash_tab;
+ int codeset_cntr;
#ifdef _LIBC
__gconv_t conv;
#else
@@ -155,6 +156,7 @@ struct binding
{
struct binding *next;
char *dirname;
+ int codeset_cntr; /* Incremented each time codeset changes. */
char *codeset;
char domainname[ZERO];
};
@@ -169,10 +171,22 @@ struct loaded_l10nfile *_nl_find_domain PARAMS ((const char *__dirname,
const char *__domainname,
struct binding *__domainbinding))
internal_function;
-void _nl_load_domain PARAMS ((struct loaded_l10nfile *__domain))
+void _nl_load_domain PARAMS ((struct loaded_l10nfile *__domain,
+ struct binding *__domainbinding))
internal_function;
void _nl_unload_domain PARAMS ((struct loaded_domain *__domain))
internal_function;
+const char *_nl_init_domain_conv PARAMS ((struct loaded_l10nfile *__domain_file,
+ struct loaded_domain *__domain,
+ struct binding *__domainbinding))
+ internal_function;
+void _nl_free_domain_conv PARAMS ((struct loaded_domain *__domain))
+ internal_function;
+
+char *_nl_find_msg PARAMS ((struct loaded_l10nfile *domain_file,
+ struct binding *domainbinding,
+ const char *msgid, size_t *lengthp))
+ internal_function;
#ifdef _LIBC
extern char *__gettext PARAMS ((const char *__msgid));
diff --git a/intl/l10nflist.c b/intl/l10nflist.c
index 804492d..557253e 100644
--- a/intl/l10nflist.c
+++ b/intl/l10nflist.c
@@ -163,7 +163,7 @@ pop (x)
struct loaded_l10nfile *
_nl_make_l10nflist (l10nfile_list, dirlist, dirlist_len, mask, language,
territory, codeset, normalized_codeset, modifier, special,
- sponsor, revision, filename, domainbinding, do_allocate)
+ sponsor, revision, filename, do_allocate)
struct loaded_l10nfile **l10nfile_list;
const char *dirlist;
size_t dirlist_len;
@@ -177,7 +177,6 @@ _nl_make_l10nflist (l10nfile_list, dirlist, dirlist_len, mask, language,
const char *sponsor;
const char *revision;
const char *filename;
- struct binding *domainbinding;
int do_allocate;
{
char *abs_filename;
@@ -298,7 +297,6 @@ _nl_make_l10nflist (l10nfile_list, dirlist, dirlist_len, mask, language,
return NULL;
retval->filename = abs_filename;
- retval->domainbinding = domainbinding;
retval->decided = (__argz_count (dirlist, dirlist_len) != 1
|| ((mask & XPG_CODESET) != 0
&& (mask & XPG_NORM_CODESET) != 0));
@@ -334,8 +332,7 @@ _nl_make_l10nflist (l10nfile_list, dirlist, dirlist_len, mask, language,
= _nl_make_l10nflist (l10nfile_list, dir, strlen (dir) + 1, cnt,
language, territory, codeset,
normalized_codeset, modifier, special,
- sponsor, revision, filename, domainbinding,
- 1);
+ sponsor, revision, filename, 1);
}
retval->successor[entries] = NULL;
diff --git a/intl/loadinfo.h b/intl/loadinfo.h
index 31bf52a..5171a8f 100644
--- a/intl/loadinfo.h
+++ b/intl/loadinfo.h
@@ -63,7 +63,6 @@
struct loaded_l10nfile
{
const char *filename;
- struct binding *domainbinding;
int decided;
const void *data;
@@ -88,8 +87,7 @@ _nl_make_l10nflist PARAMS ((struct loaded_l10nfile **l10nfile_list,
const char *normalized_codeset,
const char *modifier, const char *special,
const char *sponsor, const char *revision,
- const char *filename,
- struct binding *domainbinding, int do_allocate));
+ const char *filename, int do_allocate));
extern const char *_nl_expand_alias PARAMS ((const char *name));
@@ -107,9 +105,4 @@ extern int _nl_explode_name PARAMS ((char *name, const char **language,
extern char *_nl_find_language PARAMS ((const char *name));
-
-extern char *_nl_find_msg PARAMS ((struct loaded_l10nfile *domain_file,
- const char *msgid, size_t *lengthp))
- internal_function;
-
#endif /* loadinfo.h */
diff --git a/intl/loadmsgcat.c b/intl/loadmsgcat.c
index 7ce3089..ec9ebf0 100644
--- a/intl/loadmsgcat.c
+++ b/intl/loadmsgcat.c
@@ -199,12 +199,146 @@ init_germanic_plural ()
#endif
+/* 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])->values[_NL_ITEM_INDEX (CODESET)].string;
+# else
+# if HAVE_ICONV
+ extern const char *locale_charset (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, NULL);
+ if (__gconv_open (outcharset, charset, &domain->conv,
+ GCONV_AVOID_NOCONV)
+ != __GCONV_OK)
+ domain->conv = (__gconv_t) -1;
+# else
+# if HAVE_ICONV
+ /* When using GNU libiconv, we want to use transliteration. */
+# if _LIBICONV_VERSION
+ len = strlen (outcharset);
+ {
+ char *tmp = (char *) alloca (len + 10 + 1);
+ memcpy (tmp, outcharset, len);
+ memcpy (tmp + len, "//TRANSLIT", 10 + 1);
+ outcharset = tmp;
+ }
+# endif
+ domain->conv = iconv_open (outcharset, charset);
+# if _LIBICONV_VERSION
+ freea (outcharset);
+# endif
+# 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
internal_function
-_nl_load_domain (domain_file)
+_nl_load_domain (domain_file, domainbinding)
struct loaded_l10nfile *domain_file;
+ struct binding *domainbinding;
{
int fd;
size_t size;
@@ -216,12 +350,15 @@ _nl_load_domain (domain_file)
struct mo_file_header *data = (struct mo_file_header *) -1;
int use_mmap = 0;
struct loaded_domain *domain;
- char *nullentry;
- size_t nullentrylen;
+ const char *nullentry;
domain_file->decided = 1;
domain_file->data = NULL;
+ /* Note that it would be useless to store domainbinding in domain_file
+ because domainbinding might be == NULL now but != NULL later (after
+ a call to bind_textdomain_codeset). */
+
/* If the record does not represent a valid locale the FILENAME
might be NULL. This can happen when according to the given
specification the locale file name is different for XPG and CEN
@@ -347,85 +484,10 @@ _nl_load_domain (domain_file)
return;
}
- /* Now 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
- domain->conv = (__gconv_t) -1;
-#else
-# if HAVE_ICONV
- domain->conv = (iconv_t) -1;
-# endif
-#endif
- domain->conv_tab = NULL;
- nullentry = _nl_find_msg (domain_file, "", &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 (domain_file->domainbinding != NULL
- && domain_file->domainbinding->codeset != NULL)
- outcharset = domain_file->domainbinding->codeset;
- else
- {
- outcharset = getenv ("OUTPUT_CHARSET");
- if (outcharset == NULL || outcharset[0] == '\0')
- {
-# ifdef _LIBC
- outcharset = (*_nl_current[LC_CTYPE])->values[_NL_ITEM_INDEX (CODESET)].string;
-# else
-# if HAVE_ICONV
- extern const char *locale_charset (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, NULL);
- if (__gconv_open (outcharset, charset, &domain->conv,
- GCONV_AVOID_NOCONV)
- != __GCONV_OK)
- domain->conv = (__gconv_t) -1;
-# else
-# if HAVE_ICONV
- domain->conv = iconv_open (outcharset, charset);
-# endif
-# endif
-
- freea (charset);
- }
-#endif /* _LIBC || HAVE_ICONV */
- }
+ /* 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);
/* Also look for a plural specification. */
if (nullentry != NULL)
@@ -490,11 +552,7 @@ _nl_unload_domain (domain)
if (domain->plural != &germanic_plural)
__gettext_free_exp (domain->plural);
- if (domain->conv_tab != NULL && domain->conv_tab != (char **) -1)
- free (domain->conv_tab);
-
- if (domain->conv != (__gconv_t) -1)
- __gconv_close (domain->conv);
+ _nl_free_domain_conv (domain);
# ifdef _POSIX_MAPPED_FILES
if (domain->use_mmap)