summary refs log tree commit diff
path: root/iconv/gconv_trans.c
diff options
context:
space:
mode:
Diffstat (limited to 'iconv/gconv_trans.c')
-rw-r--r--iconv/gconv_trans.c35
1 files changed, 34 insertions, 1 deletions
diff --git a/iconv/gconv_trans.c b/iconv/gconv_trans.c
index 829ff5f981..0bb5f00c07 100644
--- a/iconv/gconv_trans.c
+++ b/iconv/gconv_trans.c
@@ -44,12 +44,13 @@ __gconv_transliterate (struct __gconv_step *step,
   uint32_t *winbufend;
   uint_fast32_t low;
   uint_fast32_t high;
+  uint32_t *default_missing;
 
   /* If there is no transliteration information in the locale don't do
      anything and return the error.  */
   size = _NL_CURRENT_WORD (LC_CTYPE, _NL_CTYPE_TRANSLIT_HASH_SIZE);
   if (size == 0)
-    return __GCONV_ILLEGAL_INPUT;
+    goto no_rules;
 
   /* Get the rest of the values.  */
   layers = _NL_CURRENT_WORD (LC_CTYPE, _NL_CTYPE_TRANSLIT_HASH_LAYERS);
@@ -141,6 +142,38 @@ __gconv_transliterate (struct __gconv_step *step,
 	high = idx;
     }
 
+  /* One last chance: use the default replacement.  */
+ no_rules:
+  default_missing = (uint32_t *)
+    _NL_CURRENT (LC_CTYPE, _NL_CTYPE_TRANSLIT_DEFAULT_MISSING);
+  if (default_missing[0] != L'\0')
+    {
+      const unsigned char *toinptr = (const unsigned char *) default_missing;
+      uint32_t len = _NL_CURRENT_WORD (LC_CTYPE,
+				       _NL_CTYPE_TRANSLIT_DEFAULT_MISSING_LEN);
+      int res;
+
+      res = DL_CALL_FCT (step->__fct,
+			 (step, step_data, &toinptr,
+			  (const unsigned char *) (default_missing + len),
+			  (unsigned char **) outbufstart,
+			  irreversible, 0, 0));
+
+      if (res != __GCONV_ILLEGAL_INPUT)
+	{
+	  /* If the conversion succeeds we have to increment the
+	     input buffer.  */
+	  if (res == __GCONV_EMPTY_INPUT)
+	    {
+	      /* We consuming one character.  */
+	      ++*inbufp;
+	      ++*irreversible;
+	    }
+
+	  return res;
+	}
+    }
+
   /* Haven't found a match.  */
   return __GCONV_ILLEGAL_INPUT;
 }