about summary refs log tree commit diff
path: root/intl
diff options
context:
space:
mode:
Diffstat (limited to 'intl')
-rw-r--r--intl/dcgettext.c28
-rw-r--r--intl/gettextP.h14
-rw-r--r--intl/loadmsgcat.c25
3 files changed, 49 insertions, 18 deletions
diff --git a/intl/dcgettext.c b/intl/dcgettext.c
index 0429cc904e..d482da39b8 100644
--- a/intl/dcgettext.c
+++ b/intl/dcgettext.c
@@ -479,8 +479,12 @@ _nl_find_msg (domain_file, msgid)
 				       domain->trans_tab[nstr - 1].offset);
 
 	  if (
-#if HAVE_ICONV || defined _LIBC
+#ifdef _LIBC
+	      domain->conv != (__gconv_t) -1
+#else
+# if HAVE_ICONV
 	      domain->conv != (iconv_t) -1
+# endif
 #endif
 	      )
 	    {
@@ -508,21 +512,23 @@ _nl_find_msg (domain_file, msgid)
 		     We allocate always larger blocks which get used over
 		     time.  This is faster than many small allocations.   */
 		  __libc_lock_define_initialized (static, lock)
-		  static char *freemem;
+		  static unsigned char *freemem;
 		  static size_t freemem_size;
 		  /* Note that we include the NUL byte.  */
 		  size_t resultlen = strlen (result) + 1;
-		  const char *inbuf = result;
-		  size_t inbytesleft = resultlen;
-		  char *outbuf = freemem;
-		  size_t outbytesleft = freemem_size;
+		  const unsigned char *inbuf = result;
+		  unsigned char *outbuf = freemem;
+		  size_t written;
+		  int res;
 
 		  __libc_lock_lock (lock);
 
-		  while (iconv (domain->conv, &inbuf, &inbytesleft, &outbuf,
-				&outbytesleft) == (size_t) -1L)
+		  while ((res = __gconv (domain->conv,
+					 &inbuf, inbuf + resultlen,
+					 &outbuf, outbuf + freemem_size,
+					 &written)) == __GCONV_OK)
 		    {
-		      if (errno != E2BIG)
+		      if (res != __GCONV_FULL_OUTPUT)
 			goto out;
 
 		      /* We must resize the buffer.  */
@@ -532,16 +538,14 @@ _nl_find_msg (domain_file, msgid)
 			goto out;
 
 		      inbuf = result;
-		      inbytesleft = resultlen;
 		      outbuf = freemem;
-		      outbytesleft = freemem_size;
 		    }
 
 		  /* We have now in our buffer a converted string.  Put this
 		     in the hash table  */
 		  domain->conv_tab[idx] = freemem;
+		  freemem_size -= outbuf - freemem;
 		  freemem = outbuf;
-		  freemem_size = outbytesleft;
 
 		out:
 		  __libc_lock_unlock (lock);
diff --git a/intl/gettextP.h b/intl/gettextP.h
index bea4404167..1b4dcb3e07 100644
--- a/intl/gettextP.h
+++ b/intl/gettextP.h
@@ -20,8 +20,12 @@
 #ifndef _GETTEXTP_H
 #define _GETTEXTP_H
 
-#if defined HAVE_ICONV || defined _LIBC
-# include <iconv.h>
+#ifdef _LIBC
+# include "../iconv/gconv_int.h"
+#else
+# if HAVE_ICONV
+#  include <iconv.h>
+# endif
 #endif
 
 #include "loadinfo.h"
@@ -71,8 +75,12 @@ struct loaded_domain
   struct string_desc *trans_tab;
   nls_uint32 hash_size;
   nls_uint32 *hash_tab;
-#if defined HAVE_ICONV || defined _LIBC
+#ifdef _LIBC
+  __gconv_t conv;
+#else
+# if HAVE_ICONV
   iconv_t conv;
+# endif
 #endif
   char **conv_tab;
 };
diff --git a/intl/loadmsgcat.c b/intl/loadmsgcat.c
index 23d738882b..ba818ce3b1 100644
--- a/intl/loadmsgcat.c
+++ b/intl/loadmsgcat.c
@@ -223,8 +223,12 @@ _nl_load_domain (domain_file)
      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.  */
-#if HAVE_ICONV || defined _LIBC
+#ifdef _LIBC
+  domain->conv = (__gconv_t) -1;
+#else
+# if HAVE_ICONV
   domain->conv = (iconv_t) -1;
+# endif
 #endif
   nullentry = _nl_find_msg (domain_file, "");
   if (nullentry != NULL)
@@ -235,6 +239,7 @@ _nl_load_domain (domain_file)
 	{
 	  size_t len;
 	  char *charset;
+	  const char *outcharset;
 
 	  charsetstr += strlen ("charset=");
 	  len = strcspn (charsetstr, " \t\n");
@@ -247,8 +252,22 @@ _nl_load_domain (domain_file)
 	  charset[len] = '\0';
 #endif
 
-#if HAVE_ICONV || defined _LIBC
-	  domain->conv = iconv_open ((*_nl_current[LC_CTYPE])->values[_NL_ITEM_INDEX (CODESET)].string, charset);
+	  /* 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 to override this.  */
+	  outcharset = getenv ("OUTPUT_CHARSET");
+	  if (outcharset == NULL || outcharset[0] == '\0')
+	    outcharset = (*_nl_current[LC_CTYPE])->values[_NL_ITEM_INDEX (CODESET)].string;
+
+#ifdef _LIBC
+	  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
 	}
     }