]> git.ipfire.org Git - thirdparty/gettext.git/commitdiff
Fix bind_textdomain_codeset to have an effect also on catalogs that have
authorBruno Haible <bruno@clisp.org>
Mon, 9 Apr 2001 19:57:05 +0000 (19:57 +0000)
committerBruno Haible <bruno@clisp.org>
Mon, 9 Apr 2001 19:57:05 +0000 (19:57 +0000)
already been opened.

intl/ChangeLog
intl/bindtextdom.c
intl/dcigettext.c
intl/finddomain.c
intl/gettextP.h
intl/l10nflist.c
intl/loadinfo.h
intl/loadmsgcat.c

index 94a35a4fef59d0c7ed2875864010f1791d6acb9a..c40ec3cf3cb4c0a90e9eea5cb694c7c0c317e1f5 100644 (file)
@@ -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
index 602a6513f5815fa747c8d515a63dcec799f779bf..7e5a74a43bf2ae94182246249274291269a30f0e 100644 (file)
@@ -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;
index f364cf9a3641d3947e992ceac0af5db0854534af..6ee9d17e3935645d1b2bc52a756809392b092433 100644 (file)
@@ -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
index fdcae6230ac81bbb09779b94ccbde9415afdc738..4882554fc911f6bfe355f0147f2a56334678be4a 100644 (file)
@@ -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;
        }
index c7f465549dd9de1f74314b6b7d60ae2dd7db4eb1..ee8ca48e95a2a61956a34c87cdb0913ab434af10 100644 (file)
@@ -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));
index 804492d20137a50b38f60401c931db5a33b56e29..557253eb985164c1b022a9c0c2cb447e368c2ecf 100644 (file)
@@ -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;
 
index 31bf52acc6fe8d8c9947cf3f194f97139f040c7e..5171a8f63b7f0f7dc93ec8908ed1fab3c51859ba 100644 (file)
@@ -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 */
index 7ce30892c9bb69404e7c73088cae82a4760fe20f..ec9ebf0782514a9915e00110e95c6bac200b1806 100644 (file)
@@ -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)