about summary refs log tree commit diff
path: root/iconv
diff options
context:
space:
mode:
Diffstat (limited to 'iconv')
-rw-r--r--iconv/gconv_int.h11
-rw-r--r--iconv/gconv_open.c25
2 files changed, 27 insertions, 9 deletions
diff --git a/iconv/gconv_int.h b/iconv/gconv_int.h
index 34dff7d522..5bdf7143e6 100644
--- a/iconv/gconv_int.h
+++ b/iconv/gconv_int.h
@@ -102,18 +102,19 @@ extern struct gconv_module *__gconv_modules_db;
 
 /* The gconv functions expects the name to be in upper case and complete,
    including the trailing slashes if necessary.  */
-#define norm_add_slashes(str) \
+#define norm_add_slashes(str,suffix) \
   ({									      \
     const char *cp = (str);						      \
     char *result;							      \
     char *tmp;								      \
     size_t cnt = 0;							      \
+    size_t suffix_len = suffix == NULL ? 0 : strlen (suffix);		      \
 									      \
     while (*cp != '\0')							      \
       if (*cp++ == '/')							      \
 	++cnt;								      \
 									      \
-    tmp = result = alloca (cp - (str) + 3);				      \
+    tmp = result = alloca (cp - (str) + 3 + suffix_len);		      \
     cp = (str);								      \
     while (*cp != '\0')							      \
       *tmp++ = _toupper (*cp++);					      \
@@ -121,7 +122,11 @@ extern struct gconv_module *__gconv_modules_db;
       {									      \
 	*tmp++ = '/';							      \
 	if (cnt < 1)							      \
-	  *tmp++ = '/';							      \
+	  {								      \
+	    *tmp++ = '/';						      \
+	    if (suffix != NULL)						      \
+	      tmp = __mempcpy (tmp, suffix, suffix_len);		      \
+	  }								      \
       }									      \
     *tmp = '\0';							      \
     result;								      \
diff --git a/iconv/gconv_open.c b/iconv/gconv_open.c
index 14f1d5e0f9..d2963fa8ee 100644
--- a/iconv/gconv_open.c
+++ b/iconv/gconv_open.c
@@ -37,6 +37,7 @@ __gconv_open (const char *toset, const char *fromset, __gconv_t *handle,
   int res;
   int conv_flags = 0;
   const char *errhand;
+  const char *ignore;
 
   /* Find out whether any error handling method is specified.  */
   errhand = strchr (toset, '/');
@@ -44,7 +45,7 @@ __gconv_open (const char *toset, const char *fromset, __gconv_t *handle,
     errhand = strchr (errhand + 1, '/');
   if (__builtin_expect (errhand != NULL, 1))
     {
-      if (errhand[1] == '\0')
+      if (*++errhand == '\0')
 	errhand = NULL;
       else
 	{
@@ -56,7 +57,7 @@ __gconv_open (const char *toset, const char *fromset, __gconv_t *handle,
 
 	  flags = __GCONV_IGNORE_ERRORS;
 
-	  if (strcasecmp (errhand, "IGNORE") == 0)
+	  if (__strcasecmp (errhand, "IGNORE") == 0)
 	    {
 	      /* Found it.  This means we should ignore conversion errors.  */
 	      flags = __GCONV_IGNORE_ERRORS;
@@ -65,6 +66,18 @@ __gconv_open (const char *toset, const char *fromset, __gconv_t *handle,
 	}
     }
 
+  /* For the source character set we ignore the error handler specification.
+     XXX Is this really always the best?  */
+  ignore = strchr (fromset, '/');
+  if (ignore != NULL && (ignore = strchr (ignore + 1, '/')) != NULL
+      && *++ignore != '\0')
+    {
+      char *newfromset = (char *) alloca (ignore - fromset + 1);
+
+      newfromset[ignore - fromset] = '\0';
+      fromset = memcpy (newfromset, fromset, ignore - fromset);
+    }
+
   res = __gconv_find_transform (toset, fromset, &steps, &nsteps, flags);
   if (res == __GCONV_OK)
     {
@@ -78,7 +91,7 @@ __gconv_open (const char *toset, const char *fromset, __gconv_t *handle,
       if (errhand != NULL)
 	{
 	  /* Find the appropriate transliteration handling.  */
-	  if (strcasecmp (errhand, "TRANSLIT") == 0)
+	  if (__strcasecmp (errhand, "TRANSLIT") == 0)
 	    {
 	      /* It's the builtin transliteration handling.  We only
                  suport for it working on the internal encoding.  */
@@ -89,7 +102,7 @@ __gconv_open (const char *toset, const char *fromset, __gconv_t *handle,
 	      trans_fct = __gconv_transliterate;
 	      /* No context, init, or end function.  */
 	    }
-	  else if (strcasecmp (errhand, "WORK AROUND A GCC BUG") == 0)
+	  else if (__strcasecmp (errhand, "WORK AROUND A GCC BUG") == 0)
 	    {
 	      trans_init_fct = (__gconv_trans_init_fct) 1;
 	    }
@@ -151,7 +164,7 @@ __gconv_open (const char *toset, const char *fromset, __gconv_t *handle,
 	      /* Now see whether we can use the transliteration module
 		 for this step.  */
 	      for (n = 0; n < ncsnames; ++n)
-		if (strcasecmp (steps[cnt].__from_name, csnames[n]) == 0)
+		if (__strcasecmp (steps[cnt].__from_name, csnames[n]) == 0)
 		  {
 		    /* Match!  Now try the initializer.  */
 		    if (trans_init_fct == NULL
@@ -182,7 +195,7 @@ __gconv_open (const char *toset, const char *fromset, __gconv_t *handle,
 	  /* Now see whether we can use the transliteration module
 	     for this step.  */
 	  for (n = 0; n < ncsnames; ++n)
-	    if (strcasecmp (steps[cnt].__from_name, csnames[n]) == 0)
+	    if (__strcasecmp (steps[cnt].__from_name, csnames[n]) == 0)
 	      {
 		/* Match!  Now try the initializer.  */
 		if (trans_init_fct == NULL