about summary refs log tree commit diff
path: root/iconvdata
diff options
context:
space:
mode:
Diffstat (limited to 'iconvdata')
-rw-r--r--iconvdata/8bit-gap.c49
-rw-r--r--iconvdata/8bit-generic.c21
-rw-r--r--iconvdata/ansi_x3.110.c72
-rw-r--r--iconvdata/big5.c52
-rw-r--r--iconvdata/big5hkscs.c52
-rw-r--r--iconvdata/euc-cn.c49
-rw-r--r--iconvdata/euc-jp.c47
-rw-r--r--iconvdata/euc-kr.c34
-rw-r--r--iconvdata/gbgbk.c26
-rw-r--r--iconvdata/gbk.c57
-rw-r--r--iconvdata/iso-2022-cn.c49
-rw-r--r--iconvdata/iso-2022-jp.c86
-rw-r--r--iconvdata/iso-2022-kr.c65
-rw-r--r--iconvdata/iso646.c32
-rw-r--r--iconvdata/iso8859-1.c14
-rw-r--r--iconvdata/iso_6937-2.c60
-rw-r--r--iconvdata/iso_6937.c60
-rw-r--r--iconvdata/johab.c96
-rw-r--r--iconvdata/sjis.c80
-rw-r--r--iconvdata/t.61.c55
-rw-r--r--iconvdata/uhc.c72
-rw-r--r--iconvdata/unicode.c18
-rw-r--r--iconvdata/utf-16.c48
23 files changed, 923 insertions, 271 deletions
diff --git a/iconvdata/8bit-gap.c b/iconvdata/8bit-gap.c
index b633c475b8..c805d5e57c 100644
--- a/iconvdata/8bit-gap.c
+++ b/iconvdata/8bit-gap.c
@@ -51,12 +51,20 @@ struct gap
     if (HAS_HOLES && ch == L'\0' && *inptr != '\0')			      \
       {									      \
 	/* This is an illegal character.  */				      \
-	result = __GCONV_ILLEGAL_INPUT;					      \
-	break;								      \
+	if (! ignore_errors_p ())					      \
+	  {								      \
+	    result = __GCONV_ILLEGAL_INPUT;				      \
+	    break;							      \
+	  }								      \
+									      \
+	++*converted; 							      \
+      }									      \
+    else								      \
+      {									      \
+	put32 (outptr, ch);						      \
+	outptr += 4;							      \
       }									      \
 									      \
-    put32 (outptr, ch);							      \
-    outptr += 4;							      \
     ++inptr;								      \
   }
 #include <iconv/loop.c>
@@ -75,24 +83,45 @@ struct gap
     if (ch >= 0xffff)							      \
       {									      \
 	/* This is an illegal character.  */				      \
-	result = __GCONV_ILLEGAL_INPUT;					      \
-	break;								      \
+	if (! ignore_errors_p ())					      \
+	  {								      \
+	    result = __GCONV_ILLEGAL_INPUT;				      \
+	    break;							      \
+	  }								      \
+									      \
+	++*converted; 							      \
+	inptr += 4;							      \
+	continue;							      \
       }									      \
     while (ch > rp->end)						      \
       ++rp;								      \
     if (ch < rp->start)							      \
       {									      \
 	/* This is an illegal character.  */				      \
-	result = __GCONV_ILLEGAL_INPUT;					      \
-	break;								      \
+	if (! ignore_errors_p ())					      \
+	  {								      \
+	    result = __GCONV_ILLEGAL_INPUT;				      \
+	    break;							      \
+	  }								      \
+									      \
+	++*converted; 							      \
+	inptr += 4;							      \
+	continue;							      \
       }									      \
 									      \
     res = from_ucs4[ch + rp->idx];					      \
     if (ch != 0 && res == '\0')						      \
       {									      \
 	/* This is an illegal character.  */				      \
-	result = __GCONV_ILLEGAL_INPUT;					      \
-	break;								      \
+	if (! ignore_errors_p ())					      \
+	  {								      \
+	    result = __GCONV_ILLEGAL_INPUT;				      \
+	    break;							      \
+	  }								      \
+									      \
+	++*converted; 							      \
+	inptr += 4;							      \
+	continue;							      \
       }									      \
 									      \
     *outptr++ = res;							      \
diff --git a/iconvdata/8bit-generic.c b/iconvdata/8bit-generic.c
index 3543bdf004..3b6b47abb1 100644
--- a/iconvdata/8bit-generic.c
+++ b/iconvdata/8bit-generic.c
@@ -37,8 +37,13 @@
     if (HAS_HOLES && ch == L'\0' && *inptr != '\0')			      \
       {									      \
 	/* This is an illegal character.  */				      \
-	result = __GCONV_ILLEGAL_INPUT;					      \
-	break;								      \
+	if (! ignore_errors_p ())					      \
+	  {								      \
+	    result = __GCONV_ILLEGAL_INPUT;				      \
+	    break;							      \
+	  }								      \
+									      \
+	++*converted; 							      \
       }									      \
 									      \
     put32 (outptr, ch);							      \
@@ -60,11 +65,17 @@
 	|| (ch != 0 && from_ucs4[ch] == '\0'))				      \
       {									      \
 	/* This is an illegal character.  */				      \
-	result = __GCONV_ILLEGAL_INPUT;					      \
-	break;								      \
+	if (! ignore_errors_p ())					      \
+	  {								      \
+	    result = __GCONV_ILLEGAL_INPUT;				      \
+	    break;							      \
+	  }								      \
+									      \
+	++*converted; 							      \
       }									      \
+    else								      \
+      *outptr++ = from_ucs4[ch];					      \
 									      \
-    *outptr++ = from_ucs4[ch];						      \
     inptr += 4;								      \
   }
 #include <iconv/loop.c>
diff --git a/iconvdata/ansi_x3.110.c b/iconvdata/ansi_x3.110.c
index 1dd214bbe5..94bd2e620e 100644
--- a/iconvdata/ansi_x3.110.c
+++ b/iconvdata/ansi_x3.110.c
@@ -419,13 +419,20 @@ static const char from_ucs4[][2] =
 	if (ch2 < 0x20 || ch2 >= 0x80)					      \
 	  {								      \
 	    /* This is illegal.  */					      \
-	    result = __GCONV_ILLEGAL_INPUT;				      \
-	    break;							      \
-	  }								      \
-									      \
-	ch = to_ucs4_comb[ch - 0xc1][ch2 - 0x20];			      \
+	    if (! ignore_errors_p ())					      \
+	      {								      \
+		result = __GCONV_ILLEGAL_INPUT;				      \
+		break;							      \
+	      }								      \
 									      \
-	incr = 2;							      \
+	    ++*converted;						      \
+	    incr = 1;							      \
+	  }								      \
+	else								      \
+	  {								      \
+	    ch = to_ucs4_comb[ch - 0xc1][ch2 - 0x20];			      \
+	    incr = 2;							      \
+	  }								      \
       }									      \
     else								      \
       {									      \
@@ -436,13 +443,19 @@ static const char from_ucs4[][2] =
     if (ch == 0 && *inptr != '\0')					      \
       {									      \
 	/* This is an illegal character.  */				      \
-	result = __GCONV_ILLEGAL_INPUT;					      \
-	break;								      \
+	if (! ignore_errors_p ())					      \
+	  {								      \
+	    result = __GCONV_ILLEGAL_INPUT;				      \
+	    break;							      \
+	  }								      \
+      }									      \
+    else								      \
+      {									      \
+	put32 (outptr, ch);						      \
+	outptr += 4;							      \
       }									      \
 									      \
     inptr += incr;							      \
-    put32 (outptr, ch);							      \
-    outptr += 4;							      \
   }
 #include <iconv/loop.c>
 
@@ -480,8 +493,15 @@ static const char from_ucs4[][2] =
 	    if (tmp[0] == '\0')						      \
 	      {								      \
 		/* Illegal characters.  */				      \
-		result = __GCONV_ILLEGAL_INPUT;				      \
-		break;							      \
+		if (! ignore_errors_p ())				      \
+		  {							      \
+		    result = __GCONV_ILLEGAL_INPUT;			      \
+		    break;						      \
+		  }							      \
+									      \
+		++*converted; 						      \
+		inptr += 4;						      \
+		continue;						      \
 	      }								      \
 	    tmp[1] = '\0';						      \
 	    cp = tmp;							      \
@@ -504,13 +524,13 @@ static const char from_ucs4[][2] =
 	  cp = "\xd7";							      \
 	else if (ch == 0x253c)						      \
 	  cp = "\xe5";							      \
-	else if (ch >= 0x2571 && ch <= 0x2572) 				      \
+	else if (ch >= 0x2571 && ch <= 0x2572)				      \
 	  {								      \
 	    tmp[0] = 0xd8 + ch - 0x2571;				      \
 	    tmp[1] = '\0';						      \
 	    cp = tmp;							      \
 	  }								      \
-	else if (ch >= 0x25e2 && ch <= 0x25e3) 				      \
+	else if (ch >= 0x25e2 && ch <= 0x25e3)				      \
 	  {								      \
 	    tmp[0] = 0xda + ch - 0x25e2;				      \
 	    tmp[1] = '\0';						      \
@@ -521,8 +541,15 @@ static const char from_ucs4[][2] =
 	else								      \
 	  {								      \
 	    /* Illegal characters.  */					      \
-	    result = __GCONV_ILLEGAL_INPUT;				      \
-	    break;							      \
+	    if (! ignore_errors_p ())					      \
+	      {								      \
+		result = __GCONV_ILLEGAL_INPUT;				      \
+		break;							      \
+	      }								      \
+									      \
+	    ++*converted;						      \
+	    inptr += 4;							      \
+	    continue;							      \
 	  }								      \
       }									      \
     else								      \
@@ -531,9 +558,16 @@ static const char from_ucs4[][2] =
 									      \
 	if (cp[0] == '\0' && ch != 0)					      \
 	  {								      \
-	    /* Illegal.  */						      \
-	    result = __GCONV_ILLEGAL_INPUT;				      \
-	    break;							      \
+	    /* Illegal characters.  */					      \
+	    if (! ignore_errors_p ())					      \
+	      {								      \
+		result = __GCONV_ILLEGAL_INPUT;				      \
+		break;							      \
+	      }								      \
+									      \
+	    ++*converted;						      \
+	    inptr += 4;							      \
+	    continue;							      \
 	  }								      \
       }									      \
 									      \
diff --git a/iconvdata/big5.c b/iconvdata/big5.c
index de15ad6239..0e4ca7464a 100644
--- a/iconvdata/big5.c
+++ b/iconvdata/big5.c
@@ -8455,8 +8455,15 @@ static const char from_ucs4_tab13[][2] =
 	else								      \
 	  {								      \
 	    /* This is illegal.  */					      \
-	    result = __GCONV_ILLEGAL_INPUT;				      \
-	    break;							      \
+	    if (! ignore_errors_p ())					      \
+	      {								      \
+		result = __GCONV_ILLEGAL_INPUT;				      \
+		break;							      \
+	      }								      \
+									      \
+	    ++inptr;							      \
+	    ++*converted;						      \
+	    continue;							      \
 	  }								      \
 									      \
 	/* Get the value from the table.  */				      \
@@ -8466,8 +8473,15 @@ static const char from_ucs4_tab13[][2] =
 	if (ch == 0 && *inptr != '\0')					      \
 	  {								      \
 	    /* This is an illegal character.  */			      \
-	    result = __GCONV_ILLEGAL_INPUT;				      \
-	    break;							      \
+	    if (! ignore_errors_p ())					      \
+	      {								      \
+		result = __GCONV_ILLEGAL_INPUT;				      \
+		break;							      \
+	      }								      \
+									      \
+	    inptr += 2;							      \
+	    ++*converted;						      \
+	    continue;							      \
 	  }								      \
 									      \
 	inptr += 2;							      \
@@ -8567,21 +8581,29 @@ static const char from_ucs4_tab13[][2] =
     if (cp[0] == '\0' && ch != 0)					      \
       {									      \
 	/* Illegal character.  */					      \
-	result = __GCONV_ILLEGAL_INPUT;					      \
-	break;								      \
-      }									      \
+	if (! ignore_errors_p ())					      \
+	  {								      \
+	    result = __GCONV_ILLEGAL_INPUT;				      \
+	    break;							      \
+	  }								      \
 									      \
-    /* See whether there is enough room for the second byte we write.  */     \
-    if (NEED_LENGTH_TEST && cp[1] != '\0' && outptr + 1 >= outend)	      \
+	++*converted;							      \
+      }									      \
+    else								      \
       {									      \
-	/* We have not enough room.  */					      \
-	result = __GCONV_FULL_OUTPUT;					      \
-	break;								      \
+	/* See whether there is enough room for the second byte we write.  */ \
+	if (NEED_LENGTH_TEST && cp[1] != '\0' && outptr + 1 >= outend)	      \
+	  {								      \
+	    /* We have not enough room.  */				      \
+	    result = __GCONV_FULL_OUTPUT;				      \
+	    break;							      \
+	  }								      \
+									      \
+	*outptr++ = cp[0];						      \
+	if (cp[1] != '\0')						      \
+	  *outptr++ = cp[1];						      \
       }									      \
 									      \
-    *outptr++ = cp[0];							      \
-    if (cp[1] != '\0')							      \
-      *outptr++ = cp[1];						      \
     inptr += 4;								      \
   }
 #include <iconv/loop.c>
diff --git a/iconvdata/big5hkscs.c b/iconvdata/big5hkscs.c
index 7e1999ec03..09974d5523 100644
--- a/iconvdata/big5hkscs.c
+++ b/iconvdata/big5hkscs.c
@@ -12609,8 +12609,15 @@ static const char from_ucs4_tab14[][2] =
 	else								      \
 	  {								      \
 	    /* This is illegal.  */					      \
-	    result = __GCONV_ILLEGAL_INPUT;				      \
-	    break;							      \
+	    if (! ignore_errors_p ())					      \
+	      {								      \
+		result = __GCONV_ILLEGAL_INPUT;				      \
+		break;							      \
+	      }								      \
+									      \
+	    ++inptr;							      \
+	    ++*converted;						      \
+	    continue;							      \
 	  }								      \
 									      \
 	/* Get the value from the table.  */				      \
@@ -12620,8 +12627,15 @@ static const char from_ucs4_tab14[][2] =
 	if (ch == 0 && *inptr != '\0')					      \
 	  {								      \
 	    /* This is an illegal character.  */			      \
-	    result = __GCONV_ILLEGAL_INPUT;				      \
-	    break;							      \
+	    if (! ignore_errors_p ())					      \
+	      {								      \
+		result = __GCONV_ILLEGAL_INPUT;				      \
+		break;							      \
+	      }								      \
+									      \
+	    inptr += 2;							      \
+	    ++*converted;						      \
+	    continue;							      \
 	  }								      \
 									      \
 	inptr += 2;							      \
@@ -12724,21 +12738,29 @@ static const char from_ucs4_tab14[][2] =
     if (cp[0] == '\0' && ch != 0)					      \
       {									      \
 	/* Illegal character.  */					      \
-	result = __GCONV_ILLEGAL_INPUT;					      \
-	break;								      \
-      }									      \
+	if (! ignore_errors_p ())					      \
+	  {								      \
+	    result = __GCONV_ILLEGAL_INPUT;				      \
+	    break;							      \
+	  }								      \
 									      \
-    /* See whether there is enough room for the second byte we write.  */     \
-    if (NEED_LENGTH_TEST && cp[1] != '\0' && outptr + 1 >= outend)	      \
+	++*converted;							      \
+      }									      \
+    else								      \
       {									      \
-	/* We have not enough room.  */					      \
-	result = __GCONV_FULL_OUTPUT;					      \
-	break;								      \
+	/* See whether there is enough room for the second byte we write.  */ \
+	if (NEED_LENGTH_TEST && cp[1] != '\0' && outptr + 1 >= outend)	      \
+	  {								      \
+	    /* We have not enough room.  */				      \
+	    result = __GCONV_FULL_OUTPUT;				      \
+	    break;							      \
+	  }								      \
+									      \
+	*outptr++ = cp[0];						      \
+	if (cp[1] != '\0')						      \
+	  *outptr++ = cp[1];						      \
       }									      \
 									      \
-    *outptr++ = cp[0];							      \
-    if (cp[1] != '\0')							      \
-      *outptr++ = cp[1];						      \
     inptr += 4;								      \
   }
 #include <iconv/loop.c>
diff --git a/iconvdata/euc-cn.c b/iconvdata/euc-cn.c
index 61601e7615..3211b57642 100644
--- a/iconvdata/euc-cn.c
+++ b/iconvdata/euc-cn.c
@@ -44,11 +44,18 @@
     if (ch <= 0x7f)							      \
       ++inptr;								      \
     else								      \
-      if ((ch <= 0xa0 || ch > 0xfe) && ch != 0x8e && ch != 0x8f)	      \
+      if ((ch <= 0xa0 && ch != 0x8e && ch != 0x8f) || ch > 0xfe)	      \
 	{								      \
 	  /* This is illegal.  */					      \
-	  result = __GCONV_ILLEGAL_INPUT;				      \
-	  break;							      \
+	  if (! ignore_errors_p ())					      \
+	    {								      \
+	      result = __GCONV_ILLEGAL_INPUT;				      \
+	      break;							      \
+	    }								      \
+									      \
+	  ++inptr;							      \
+	  ++*converted;							      \
+	  continue;							      \
 	}								      \
       else								      \
 	{								      \
@@ -69,9 +76,16 @@
 	  /* All second bytes of a multibyte character must be >= 0xa1. */    \
 	  if (ch < 0xa1)						      \
 	    {								      \
-	      /* This is an illegal character.  */			      \
-	      result = __GCONV_ILLEGAL_INPUT;				      \
-	      break;							      \
+	      if (! ignore_errors_p ())					      \
+		{							      \
+		  /* This is an illegal character.  */			      \
+		  result = __GCONV_ILLEGAL_INPUT;			      \
+		  break;						      \
+		}							      \
+									      \
+	      ++inptr;							      \
+	      ++*converted;						      \
+	      continue;							      \
 	    }								      \
 									      \
 	  /* This is code set 1: GB 2312-80.  */			      \
@@ -81,8 +95,16 @@
 	  if (ch == __UNKNOWN_10646_CHAR)				      \
 	    {								      \
 	      /* This is an illegal character.  */			      \
-	      result = __GCONV_ILLEGAL_INPUT;				      \
-	      break;							      \
+	      if (! ignore_errors_p ())					      \
+		{							      \
+		  /* This is an illegal character.  */			      \
+		  result = __GCONV_ILLEGAL_INPUT;			      \
+		  break;						      \
+		}							      \
+									      \
+	      inptr += 2;						      \
+	      ++*converted;						      \
+	      continue;							      \
 	    }								      \
 									      \
 	  inptr += 2;							      \
@@ -118,8 +140,15 @@
 	    if (found == __UNKNOWN_10646_CHAR)				      \
 	      {								      \
 		/* Illegal character.  */				      \
-		result = __GCONV_ILLEGAL_INPUT;				      \
-		break;							      \
+		if (! ignore_errors_p ())				      \
+		  {							      \
+		    result = __GCONV_ILLEGAL_INPUT;			      \
+		    break;						      \
+		  }							      \
+									      \
+		inptr += 4;						      \
+		++*converted;						      \
+		continue;						      \
 	      }								      \
 									      \
 	    /* It's a GB 2312 character, adjust it for EUC-CN.  */	      \
diff --git a/iconvdata/euc-jp.c b/iconvdata/euc-jp.c
index 2c25d7afda..240d76037f 100644
--- a/iconvdata/euc-jp.c
+++ b/iconvdata/euc-jp.c
@@ -46,11 +46,18 @@
 									      \
     if (ch <= 0x7f)							      \
       ++inptr;								      \
-    else if ((ch <= 0xa0 || ch > 0xfe) && ch != 0x8e && ch != 0x8f)	      \
+    else if ((ch <= 0xa0 && ch != 0x8e && ch != 0x8f) || ch > 0xfe)	      \
       {									      \
 	/* This is illegal.  */						      \
-	result = __GCONV_ILLEGAL_INPUT;					      \
-	break;								      \
+	if (! ignore_errors_p ())					      \
+	  {								      \
+	    result = __GCONV_ILLEGAL_INPUT;				      \
+	    break;							      \
+	  }								      \
+									      \
+	++inptr;							      \
+	++*converted;							      \
+	continue;							      \
       }									      \
     else								      \
       {									      \
@@ -72,8 +79,15 @@
 	if (ch2 < 0xa1)							      \
 	  {								      \
 	    /* This is an illegal character.  */			      \
-	    result = __GCONV_ILLEGAL_INPUT;				      \
-	    break;							      \
+	    if (! ignore_errors_p ())					      \
+	      {								      \
+		result = __GCONV_ILLEGAL_INPUT;				      \
+		break;							      \
+	      }								      \
+									      \
+	    ++inptr;							      \
+	    ++*converted;						      \
+	    continue;							      \
 	  }								      \
 									      \
 	if (ch == 0x8e)							      \
@@ -114,8 +128,16 @@
 	    if (ch == __UNKNOWN_10646_CHAR)				      \
 	      {								      \
 		/* Illegal character.  */				      \
-		result = __GCONV_ILLEGAL_INPUT;				      \
-		break;							      \
+		if (! ignore_errors_p ())				      \
+		  {							      \
+		    /* This is an illegal character.  */		      \
+		    result = __GCONV_ILLEGAL_INPUT;			      \
+		    break;						      \
+		  }							      \
+									      \
+		inptr += 2;						      \
+		++*converted;						      \
+		continue;						      \
 	      }								      \
 	    inptr = endp;						      \
 	  }								      \
@@ -198,8 +220,15 @@
 		else							      \
 		  {							      \
 		    /* Illegal character.  */				      \
-		    result = __GCONV_ILLEGAL_INPUT;			      \
-		    break;						      \
+		    if (! ignore_errors_p ())				      \
+		      {							      \
+			result = __GCONV_ILLEGAL_INPUT;			      \
+			break;						      \
+		      }							      \
+									      \
+		    inptr += 4;						      \
+		    ++*converted;					      \
+		    continue;						      \
 		  }							      \
 	      }								      \
 	  }								      \
diff --git a/iconvdata/euc-kr.c b/iconvdata/euc-kr.c
index 19516b62eb..d84e72ca5d 100644
--- a/iconvdata/euc-kr.c
+++ b/iconvdata/euc-kr.c
@@ -81,8 +81,15 @@ euckr_from_ucs4 (uint32_t ch, unsigned char *cp)
     else if (ch <= 0xa0 || ch > 0xfe || ch == 0xc9)			      \
       {									      \
 	/* This is illegal.  */						      \
-	result = __GCONV_ILLEGAL_INPUT;					      \
-	break;								      \
+	if (! ignore_errors_p ())					      \
+	  {								      \
+	    result = __GCONV_ILLEGAL_INPUT;				      \
+	    break;							      \
+	  }								      \
+									      \
+	++inptr;							      \
+	++*converted;							      \
+	continue;							      \
       }									      \
     else								      \
       {									      \
@@ -99,8 +106,16 @@ euckr_from_ucs4 (uint32_t ch, unsigned char *cp)
 	if (ch == __UNKNOWN_10646_CHAR)					      \
 	  {								      \
 	    /* This is an illegal character.  */			      \
-	    result = __GCONV_ILLEGAL_INPUT;				      \
-	    break;							      \
+	    if (! ignore_errors_p ())					      \
+	      {								      \
+		/* This is an illegal character.  */			      \
+		result = __GCONV_ILLEGAL_INPUT;				      \
+		break;							      \
+	      }								      \
+									      \
+	    inptr += 2;							      \
+	    ++*converted;						      \
+	    continue;							      \
 	  }								      \
       }									      \
 									      \
@@ -127,8 +142,15 @@ euckr_from_ucs4 (uint32_t ch, unsigned char *cp)
     if (cp[0] == '\0' && ch != 0)					      \
       {									      \
 	/* Illegal character.  */					      \
-	result = __GCONV_ILLEGAL_INPUT;					      \
-	break;								      \
+	if (! ignore_errors_p ())					      \
+	  {								      \
+	    result = __GCONV_ILLEGAL_INPUT;				      \
+	    break;							      \
+	  }								      \
+									      \
+	inptr += 4;							      \
+	++*converted;							      \
+	continue;							      \
       }									      \
 									      \
     *outptr++ = cp[0];							      \
diff --git a/iconvdata/gbgbk.c b/iconvdata/gbgbk.c
index 64da7a4634..88617ae6c0 100644
--- a/iconvdata/gbgbk.c
+++ b/iconvdata/gbgbk.c
@@ -89,28 +89,28 @@
 	ch = (ch << 8) | inptr[1];					      \
 									      \
 	/* Now determine whether the character is valid.  */		      \
-	if (ch >= 0xa1a1 && ch <= 0xf7fe && inptr[1] >= 0xa1)		      \
+	if (ch < 0xa1a1 || ch > 0xf7fe || inptr[1] < 0xa1		      \
+	    /* Now test the exceptions.  */				      \
+	    || (ch >= 0xa2a1 && ch <= 0xa2aa)				      \
+	    || (ch >= 0xa6e0 && ch <= 0xa6f5)				      \
+	    || (ch >= 0xa8bb && ch <= 0xa8c0))				      \
 	  {								      \
-	    /* So far so good.  Now test the exceptions.  */		      \
-	    if ((ch >= 0xa2a1 && ch <= 0xa2aa)				      \
-		|| (ch >= 0xa6e0 && ch <= 0xa6f5)			      \
-		|| (ch >= 0xa8bb && ch <= 0xa8c0))			      \
+	    /* One of the characters we cannot map.  */			      \
+	    if (! ignore_errors_p ())					      \
 	      {								      \
-		/* One of the exceptions.  */				      \
 		result = __GCONV_ILLEGAL_INPUT;				      \
 		break;							      \
 	      }								      \
+									      \
+	    inptr += 2;							      \
+	    ++*converted;						      \
 	  }								      \
 	else								      \
 	  {								      \
-	    /* One of the characters we cannot map.  */			      \
-	    result = __GCONV_ILLEGAL_INPUT;				      \
-	    break;							      \
+	    /* Copy the two bytes.  */					      \
+	    *outptr++ = *inptr++;					      \
+	    *outptr++ = *inptr++;					      \
 	  }								      \
-									      \
-	/* Copy the two bytes.  */					      \
-	*outptr++ = *inptr++;						      \
-	*outptr++ = *inptr++;						      \
       }									      \
   }
 #include <iconv/loop.c>
diff --git a/iconvdata/gbk.c b/iconvdata/gbk.c
index 9956ea36cf..c120df08a1 100644
--- a/iconvdata/gbk.c
+++ b/iconvdata/gbk.c
@@ -13124,8 +13124,15 @@ static const char __gbk_from_ucs4_tab12[][2] =
       if (ch <= 0x80 || ch > 0xfe)					      \
 	{								      \
 	  /* This is illegal.  */					      \
-	  result = __GCONV_ILLEGAL_INPUT;				      \
-	  break;							      \
+	  if (! ignore_errors_p ())					      \
+	    {								      \
+	      result = __GCONV_ILLEGAL_INPUT;				      \
+	      break;							      \
+	    }								      \
+									      \
+	  ++inptr;							      \
+	  ++*converted;							      \
+	  continue;							      \
 	}								      \
       else								      \
 	{								      \
@@ -13148,8 +13155,16 @@ static const char __gbk_from_ucs4_tab12[][2] =
 	  if (ch2 < 0x40)						      \
 	    {								      \
 	      /* This is an illegal character.  */			      \
-	      result = __GCONV_ILLEGAL_INPUT;				      \
-	      break;							      \
+	      if (! ignore_errors_p ())					      \
+		{							      \
+		  /* This is an illegal character.  */			      \
+		  result = __GCONV_ILLEGAL_INPUT;			      \
+		  break;						      \
+		}							      \
+									      \
+	      ++inptr;							      \
+	      ++*converted;						      \
+	      continue;							      \
 	    }								      \
 									      \
 	  /* This is code set 1: GBK.  */				      \
@@ -13160,8 +13175,16 @@ static const char __gbk_from_ucs4_tab12[][2] =
 	  if (ch == 0 && *inptr != '\0')				      \
 	    {								      \
 	      /* This is an illegal character.  */			      \
-	      result = __GCONV_ILLEGAL_INPUT;				      \
-	      break;							      \
+	      if (! ignore_errors_p ())					      \
+		{							      \
+		  /* This is an illegal character.  */			      \
+		  result = __GCONV_ILLEGAL_INPUT;			      \
+		  break;						      \
+		}							      \
+									      \
+	      inptr += 2;						      \
+	      ++*converted;						      \
+	      continue;							      \
 	    }								      \
 									      \
 	  inptr += 2;							      \
@@ -13426,21 +13449,27 @@ static const char __gbk_from_ucs4_tab12[][2] =
       if (cp == NULL || (cp[0] == '\0' && ch != 0))			      \
 	{								      \
 	  /* Illegal character.  */					      \
-	  result = __GCONV_ILLEGAL_INPUT;				      \
-	  break;							      \
-	}								      \
+	  if (! ignore_errors_p ())					      \
+	    {								      \
+	      result = __GCONV_ILLEGAL_INPUT;				      \
+	      break;							      \
+	    }								      \
 									      \
+	  ++*converted;							      \
+	}								      \
       /* See whether there is enough room for the second byte we write.  */   \
-      if (NEED_LENGTH_TEST && cp[1] != '\0' && outptr + 1 >= outend)	      \
+      else if (NEED_LENGTH_TEST && cp[1] != '\0' && outptr + 1 >= outend)     \
 	{								      \
 	  /* We have not enough room.  */				      \
 	  result = __GCONV_FULL_OUTPUT;					      \
 	  break;							      \
 	}								      \
-									      \
-      *outptr++ = cp[0];						      \
-      if (cp[1] != '\0')						      \
-	*outptr++ = cp[1];						      \
+      else								      \
+	{								      \
+	  *outptr++ = cp[0];						      \
+	  if (cp[1] != '\0')						      \
+	    *outptr++ = cp[1];						      \
+	}								      \
     }									      \
 									      \
     inptr += 4;                                                               \
diff --git a/iconvdata/iso-2022-cn.c b/iconvdata/iso-2022-cn.c
index 5ffbfa565e..c89fc5776e 100644
--- a/iconvdata/iso-2022-cn.c
+++ b/iconvdata/iso-2022-cn.c
@@ -93,7 +93,7 @@ enum
 	    {								      \
 	      /* Write out the shift sequence.  */			      \
 	      *outbuf++ = SI;						      \
-	      if (data->__is_last)					      \
+	      if (data->__flags & __GCONV_IS_LAST)			      \
 		*written += 1;						      \
 	      data->__outbuf = outbuf;					      \
 	      data->__statep->__count = ASCII_set;			      \
@@ -123,8 +123,15 @@ enum
     /* This is a 7bit character set, disallow all 8bit characters.  */	      \
     if (ch > 0x7f)							      \
       {									      \
-	result = __GCONV_ILLEGAL_INPUT;					      \
-	break;								      \
+	if (! ignore_errors_p ())					      \
+	  {								      \
+	    result = __GCONV_ILLEGAL_INPUT;				      \
+	    break;							      \
+	  }								      \
+									      \
+	++inptr;							      \
+	++*converted;							      \
+	continue;							      \
       }									      \
 									      \
     /* Recognize escape sequences.  */					      \
@@ -187,9 +194,16 @@ enum
 	ch = cns11643l2_to_ucs4 (&inptr, 2, 0);				      \
 	if (ch == __UNKNOWN_10646_CHAR)					      \
 	  {								      \
-	    inptr -= 2;							      \
-	    result = __GCONV_ILLEGAL_INPUT;				      \
-	    break;							      \
+	    if (! ignore_errors_p ())					      \
+	      {								      \
+		/* This is an illegal character.  */			      \
+	        inptr -= 2;						      \
+		result = __GCONV_ILLEGAL_INPUT;				      \
+		break;							      \
+	      }								      \
+									      \
+	    ++*converted;						      \
+	    continue;							      \
 	  }								      \
       }									      \
     else if (set == ASCII_set)						      \
@@ -217,8 +231,16 @@ enum
 	  }								      \
 	else if (ch == __UNKNOWN_10646_CHAR)				      \
 	  {								      \
-	    result = __GCONV_ILLEGAL_INPUT;				      \
-	    break;							      \
+	    if (! ignore_errors_p ())					      \
+	      {								      \
+		/* This is an illegal character.  */			      \
+		result = __GCONV_ILLEGAL_INPUT;				      \
+		break;							      \
+	      }								      \
+									      \
+	    ++inptr;							      \
+	    ++*converted;						      \
+	    continue;							      \
 	  }								      \
       }									      \
 									      \
@@ -305,8 +327,15 @@ enum
 		else							      \
 		  {							      \
 		    /* Even this does not work.  Error.  */		      \
-		    result = __GCONV_ILLEGAL_INPUT;			      \
-		    break;						      \
+		    if (! ignore_errors_p ())				      \
+		      {							      \
+			result = __GCONV_ILLEGAL_INPUT;			      \
+			break;						      \
+		      }							      \
+									      \
+		    inptr += 4;						      \
+		    ++*converted;					      \
+		    continue;						      \
 		  }							      \
 	      }								      \
 	  }								      \
diff --git a/iconvdata/iso-2022-jp.c b/iconvdata/iso-2022-jp.c
index 105fd4753b..51420fb43f 100644
--- a/iconvdata/iso-2022-jp.c
+++ b/iconvdata/iso-2022-jp.c
@@ -217,7 +217,7 @@ gconv_end (struct __gconv_step *data)
 	      *outbuf++ = ESC;						      \
 	      *outbuf++ = '(';						      \
 	      *outbuf++ = 'B';						      \
-	      if (data->__is_last)					      \
+	      if (data->__flags & __GCONV_IS_LAST)			      \
 	        *written += 3;						      \
 	      data->__outbuf = outbuf;					      \
 	      /* Note that this also clears the G2 designation.  */	      \
@@ -362,21 +362,42 @@ gconv_end (struct __gconv_step *data)
 	    /* We use the table from the ISO 8859-7 module.  */		      \
 	    if (inptr[2] < 0x20 || inptr[2] > 0x80)			      \
 	      {								      \
-		result = __GCONV_ILLEGAL_INPUT;				      \
-		break;							      \
+		if (! ignore_errors_p ())				      \
+		  {							      \
+		    result = __GCONV_ILLEGAL_INPUT;			      \
+		    break;						      \
+		  }							      \
+									      \
+		++inptr;						      \
+		++*converted;						      \
+		continue;						      \
 	      }								      \
 	    ch = iso88597_to_ucs4[inptr[2] - 0x20];			      \
 	    if (ch == 0)						      \
 	      {								      \
-		result = __GCONV_ILLEGAL_INPUT;				      \
-		break;							      \
+		if (! ignore_errors_p ())				      \
+		  {							      \
+		    result = __GCONV_ILLEGAL_INPUT;			      \
+		    break;						      \
+		  }							      \
+									      \
+		inptr += 3;						      \
+		++*converted;						      \
+		continue;						      \
 	      }								      \
 	    inptr += 3;							      \
 	  }								      \
 	else								      \
 	  {								      \
-	    result = __GCONV_ILLEGAL_INPUT;				      \
-	    break;							      \
+	    if (! ignore_errors_p ())					      \
+	      {								      \
+		result = __GCONV_ILLEGAL_INPUT;				      \
+		break;							      \
+	      }								      \
+									      \
+	    ++inptr;							      \
+	    ++*converted;						      \
+	    continue;							      \
 	  }								      \
       }									      \
     else if (set == ASCII_set || (ch < 0x21 || ch == 0x7f))		      \
@@ -388,8 +409,15 @@ gconv_end (struct __gconv_step *data)
 	ch = jisx0201_to_ucs4 (ch);					      \
 	if (ch == __UNKNOWN_10646_CHAR)					      \
 	  {								      \
-	    result = __GCONV_ILLEGAL_INPUT;				      \
-	    break;							      \
+	    if (! ignore_errors_p ())					      \
+	      {								      \
+		result = __GCONV_ILLEGAL_INPUT;				      \
+		break;							      \
+	      }								      \
+									      \
+	    ++inptr;							      \
+	    ++*converted;						      \
+	    continue;							      \
 	  }								      \
 	++inptr;							      \
       }									      \
@@ -399,8 +427,15 @@ gconv_end (struct __gconv_step *data)
 	ch = jisx0201_to_ucs4 (ch + 0x80);				      \
 	if (ch == __UNKNOWN_10646_CHAR)					      \
 	  {								      \
-	    result = __GCONV_ILLEGAL_INPUT;				      \
-	    break;							      \
+	    if (! ignore_errors_p ())					      \
+	      {								      \
+		result = __GCONV_ILLEGAL_INPUT;				      \
+		break;							      \
+	      }								      \
+									      \
+	    ++inptr;							      \
+	    ++*converted;						      \
+	    continue;							      \
 	  }								      \
 	++inptr;							      \
       }									      \
@@ -437,8 +472,15 @@ gconv_end (struct __gconv_step *data)
 	  }								      \
 	else if (ch == __UNKNOWN_10646_CHAR)				      \
 	  {								      \
-	    result = __GCONV_ILLEGAL_INPUT;				      \
-	    break;							      \
+	    if (! ignore_errors_p ())					      \
+	      {								      \
+		result = __GCONV_ILLEGAL_INPUT;				      \
+		break;							      \
+	      }								      \
+									      \
+	    ++inptr;							      \
+	    ++*converted;						      \
+	    continue;							      \
 	  }								      \
       }									      \
 									      \
@@ -672,8 +714,13 @@ gconv_end (struct __gconv_step *data)
 		else if (var == iso2022jp)				      \
 		  {							      \
 		    /* We have no other choice.  */			      \
-		    result = __GCONV_ILLEGAL_INPUT;			      \
-		    break;						      \
+		    if (! ignore_errors_p ())				      \
+		      {							      \
+			result = __GCONV_ILLEGAL_INPUT;			      \
+			break;						      \
+		      }							      \
+									      \
+		    ++*converted;					      \
 		  }							      \
 		else							      \
 		  {							      \
@@ -839,8 +886,13 @@ gconv_end (struct __gconv_step *data)
 				      }					      \
 				    else				      \
 				      {					      \
-					result = __GCONV_ILLEGAL_INPUT;	      \
-					break;				      \
+					if (! ignore_errors_p ())	      \
+					  {				      \
+					     result = __GCONV_ILLEGAL_INPUT;  \
+					     break;			      \
+					  }				      \
+									      \
+					++*converted;			      \
 				      }					      \
 				  }					      \
 			      }						      \
diff --git a/iconvdata/iso-2022-kr.c b/iconvdata/iso-2022-kr.c
index ab03472f26..e6db8c441a 100644
--- a/iconvdata/iso-2022-kr.c
+++ b/iconvdata/iso-2022-kr.c
@@ -95,7 +95,7 @@ enum
 	    {								      \
 	      /* Write out the shift sequence.  */			      \
 	      *outbuf++ = SI;						      \
-	      if (data->__is_last)					      \
+	      if (data->__flags & __GCONV_IS_LAST)			      \
 		*written += 1;						      \
 	      data->__outbuf = outbuf;					      \
 	      data->__statep->__count = ASCII_set;			      \
@@ -125,8 +125,15 @@ enum
     /* This is a 7bit character set, disallow all 8bit characters.  */	      \
     if (ch > 0x7f)							      \
       {									      \
-	result = __GCONV_ILLEGAL_INPUT;					      \
-	break;								      \
+	if (! ignore_errors_p ())					      \
+	  {								      \
+	    result = __GCONV_ILLEGAL_INPUT;				      \
+	    break;							      \
+	  }								      \
+									      \
+	++inptr;							      \
+	++*converted;							      \
+	continue;							      \
       }									      \
 									      \
     /* Recognize escape sequences.  */					      \
@@ -187,8 +194,16 @@ enum
 	  }								      \
 	else if (ch == __UNKNOWN_10646_CHAR)				      \
 	  {								      \
-	    result = __GCONV_ILLEGAL_INPUT;				      \
-	    break;							      \
+	    if (! ignore_errors_p ())					      \
+	      {								      \
+		/* This is an illegal character.  */			      \
+		result = __GCONV_ILLEGAL_INPUT;				      \
+		break;							      \
+	      }								      \
+									      \
+	    ++*converted;						      \
+	    ++inptr;							      \
+	    continue;							      \
 	  }								      \
       }									      \
 									      \
@@ -240,26 +255,34 @@ enum
 	if (written == __UNKNOWN_10646_CHAR)				      \
 	  {								      \
 	    /* Illegal character.  */					      \
-	    result = __GCONV_ILLEGAL_INPUT;				      \
-	    break;							      \
-	  }								      \
-	assert (written == 2);						      \
+	    if (! ignore_errors_p ())					      \
+	      {								      \
+		result = __GCONV_ILLEGAL_INPUT;				      \
+		break;							      \
+	      }								      \
 									      \
-	/* We use KSC 5601.  */						      \
-	if (set != KSC5601_set)						      \
-	  {								      \
-	    *outptr++ = SO;						      \
-	    set = KSC5601_set;						      \
+	    ++*converted;						      \
 	  }								      \
-									      \
-	if (NEED_LENGTH_TEST && outptr + 2 > outend)			      \
+	else								      \
 	  {								      \
-	    result = __GCONV_FULL_OUTPUT;				      \
-	    break;							      \
-	  }								      \
+	    assert (written == 2);					      \
+									      \
+	    /* We use KSC 5601.  */					      \
+	    if (set != KSC5601_set)					      \
+	      {								      \
+		*outptr++ = SO;						      \
+		set = KSC5601_set;					      \
+	      }								      \
+									      \
+	    if (NEED_LENGTH_TEST && outptr + 2 > outend)		      \
+	      {								      \
+		result = __GCONV_FULL_OUTPUT;				      \
+		break;							      \
+	      }								      \
 									      \
-	*outptr++ = buf[0];						      \
-	*outptr++ = buf[1];						      \
+	    *outptr++ = buf[0];						      \
+	    *outptr++ = buf[1];						      \
+	  }								      \
       }									      \
 									      \
     /* Now that we wrote the output increment the input pointer.  */	      \
diff --git a/iconvdata/iso646.c b/iconvdata/iso646.c
index c8d0a02121..ba0addcd78 100644
--- a/iconvdata/iso646.c
+++ b/iconvdata/iso646.c
@@ -406,12 +406,20 @@ gconv_end (struct __gconv_step *data)
        when we reach the default case in the `switch' statement.  */	      \
     if (failure == __GCONV_ILLEGAL_INPUT)				      \
       {									      \
-	/* Exit the loop with an error.  */				      \
-	result = failure;						      \
-	break;								      \
+	if (! ignore_errors_p ())					      \
+	  {								      \
+	    /* Exit the loop with an error.  */				      \
+	    result = __GCONV_ILLEGAL_INPUT;				      \
+	    break;							      \
+	  }								      \
+									      \
+	++*converted;							      \
+      }									      \
+    else								      \
+      {									      \
+	put32 (outptr, ch);						      \
+	outptr += 4;							      \
       }									      \
-    put32 (outptr, ch);							      \
-    outptr += 4;							      \
     ++inptr;								      \
   }
 #define EXTRA_LOOP_DECLS	, enum variant var
@@ -875,11 +883,17 @@ gconv_end (struct __gconv_step *data)
 									      \
     if (failure == __GCONV_ILLEGAL_INPUT)				      \
       {									      \
-	/* Exit the loop with an error.  */				      \
-	result = failure;						      \
-	break;								      \
+	if (! ignore_errors_p ())					      \
+	  {								      \
+	    /* Exit the loop with an error.  */				      \
+	    result = __GCONV_ILLEGAL_INPUT;				      \
+	    break;							      \
+	  }								      \
+									      \
+	++*converted;							      \
       }									      \
-    *outptr++ = (unsigned char) ch;					      \
+    else								      \
+      *outptr++ = (unsigned char) ch;					      \
     inptr += 4;								      \
   }
 #define EXTRA_LOOP_DECLS	, enum variant var
diff --git a/iconvdata/iso8859-1.c b/iconvdata/iso8859-1.c
index 06eeda5664..4949991711 100644
--- a/iconvdata/iso8859-1.c
+++ b/iconvdata/iso8859-1.c
@@ -1,5 +1,5 @@
 /* Conversion to and from ISO 8859-1.
-   Copyright (C) 1997, 1998, 1999 Free Software Foundation, Inc.
+   Copyright (C) 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
 
@@ -48,10 +48,16 @@
     if (ch > 0xff)							      \
       {									      \
 	/* We have an illegal character.  */				      \
-	result = __GCONV_ILLEGAL_INPUT;					      \
-	break;								      \
+	if (! ignore_errors_p ())					      \
+	  {								      \
+	    result = __GCONV_ILLEGAL_INPUT;				      \
+	    break;							      \
+	  }								      \
+									      \
+	++*converted;							      \
       }									      \
-    *outptr++ = (unsigned char) ch;					      \
+    else								      \
+      *outptr++ = (unsigned char) ch;					      \
     inptr += 4;								      \
   }
 #include <iconv/loop.c>
diff --git a/iconvdata/iso_6937-2.c b/iconvdata/iso_6937-2.c
index a688b7c695..f58ebe4ff5 100644
--- a/iconvdata/iso_6937-2.c
+++ b/iconvdata/iso_6937-2.c
@@ -418,8 +418,16 @@ static const char from_ucs4[][2] =
 	if (ch2 < 0x20 || ch2 >= 0x80)					      \
 	  {								      \
 	    /* This is illegal.  */					      \
-	    result = __GCONV_ILLEGAL_INPUT;				      \
-	    break;							      \
+	    if (! ignore_errors_p ())					      \
+	      {								      \
+	        /* This is an illegal character.  */			      \
+	        result = __GCONV_ILLEGAL_INPUT;				      \
+	        break;							      \
+	      }								      \
+									      \
+	    ++inptr;							      \
+	    ++*converted;						      \
+	    continue;							      \
 	  }								      \
 									      \
 	ch = to_ucs4_comb[ch - 0xc1][ch2 - 0x20];			      \
@@ -427,8 +435,16 @@ static const char from_ucs4[][2] =
 	if (ch == 0)							      \
 	  {								      \
 	    /* Illegal character.  */					      \
-	    result = __GCONV_ILLEGAL_INPUT;				      \
-	    break;							      \
+	    if (! ignore_errors_p ())					      \
+	      {								      \
+	        /* This is an illegal character.  */			      \
+	        result = __GCONV_ILLEGAL_INPUT;				      \
+	        break;							      \
+	      }								      \
+									      \
+	    inptr += 2;							      \
+	    ++*converted;						      \
+	    continue;							      \
 	  }								      \
 									      \
 	inptr += 2;							      \
@@ -440,8 +456,16 @@ static const char from_ucs4[][2] =
 	if (ch == 0 && *inptr != '\0')					      \
 	  {								      \
 	    /* This is an illegal character.  */			      \
-	    result = __GCONV_ILLEGAL_INPUT;				      \
-	    break;							      \
+	    if (! ignore_errors_p ())					      \
+	      {								      \
+	        /* This is an illegal character.  */			      \
+	        result = __GCONV_ILLEGAL_INPUT;				      \
+	        break;							      \
+	      }								      \
+									      \
+	    ++inptr;							      \
+	    ++*converted;						      \
+	    continue;							      \
 	  }								      \
 	++inptr;							      \
       }									      \
@@ -543,15 +567,30 @@ static const char from_ucs4[][2] =
 	if (fail)							      \
 	  {								      \
 	    /* Illegal characters.  */					      \
-	    result = __GCONV_ILLEGAL_INPUT;				      \
-	    break;							      \
+	    if (! ignore_errors_p ())					      \
+	      {								      \
+	        /* This is an illegal character.  */			      \
+		result = __GCONV_ILLEGAL_INPUT;				      \
+		break;							      \
+	      }								      \
+									      \
+	    inptr += 4;							      \
+	    ++*converted;						      \
+	    continue;							      \
 	  }								      \
       }									      \
     else if (from_ucs4[ch][0] == '\0' && ch != 0)			      \
       {									      \
 	/* Illegal characters.  */					      \
-	result = __GCONV_ILLEGAL_INPUT;					      \
-	break;								      \
+	if (! ignore_errors_p ())					      \
+	  {								      \
+	    result = __GCONV_ILLEGAL_INPUT;				      \
+	    break;							      \
+	  }								      \
+									      \
+	++*converted;							      \
+	inptr += 4;							      \
+	continue;							      \
       }									      \
     else								      \
       cp = from_ucs4[ch];						      \
@@ -563,6 +602,7 @@ static const char from_ucs4[][2] =
 	if (NEED_LENGTH_TEST && outptr >= outend)			      \
 	  {								      \
 	    /* The result does not fit into the buffer.  */		      \
+	    --outptr;							      \
 	    result = __GCONV_FULL_OUTPUT;				      \
 	    break;							      \
 	  }								      \
diff --git a/iconvdata/iso_6937.c b/iconvdata/iso_6937.c
index 81e5d0c867..f6581cfbd8 100644
--- a/iconvdata/iso_6937.c
+++ b/iconvdata/iso_6937.c
@@ -410,8 +410,16 @@ static const char from_ucs4[][2] =
 	if (ch2 < 0x20 || ch2 >= 0x80)					      \
 	  {								      \
 	    /* This is illegal.  */					      \
-	    result = __GCONV_ILLEGAL_INPUT;				      \
-	    break;							      \
+	    if (! ignore_errors_p ())					      \
+	      {								      \
+	        /* This is an illegal character.  */			      \
+	        result = __GCONV_ILLEGAL_INPUT;				      \
+	        break;							      \
+	      }								      \
+									      \
+	    ++inptr;							      \
+	    ++*converted;						      \
+	    continue;							      \
 	  }								      \
 									      \
 	ch = to_ucs4_comb[ch - 0xc1][ch2 - 0x20];			      \
@@ -419,8 +427,16 @@ static const char from_ucs4[][2] =
 	if (ch == 0)							      \
 	  {								      \
 	    /* Illegal character.  */					      \
-	    result = __GCONV_ILLEGAL_INPUT;				      \
-	    break;							      \
+	    if (! ignore_errors_p ())					      \
+	      {								      \
+	        /* This is an illegal character.  */			      \
+	        result = __GCONV_ILLEGAL_INPUT;				      \
+	        break;							      \
+	      }								      \
+									      \
+	    inptr += 2;							      \
+	    ++*converted;						      \
+	    continue;							      \
 	  }								      \
 									      \
 	inptr += 2;							      \
@@ -432,8 +448,16 @@ static const char from_ucs4[][2] =
 	if (ch == 0 && *inptr != '\0')					      \
 	  {								      \
 	    /* This is an illegal character.  */			      \
-	    result = __GCONV_ILLEGAL_INPUT;				      \
-	    break;							      \
+	    if (! ignore_errors_p ())					      \
+	      {								      \
+	        /* This is an illegal character.  */			      \
+	        result = __GCONV_ILLEGAL_INPUT;				      \
+	        break;							      \
+	      }								      \
+									      \
+	    ++inptr;							      \
+	    ++*converted;						      \
+	    continue;							      \
 	  }								      \
 	++inptr;							      \
       }									      \
@@ -514,15 +538,30 @@ static const char from_ucs4[][2] =
 	if (fail)							      \
 	  {								      \
 	    /* Illegal characters.  */					      \
-	    result = __GCONV_ILLEGAL_INPUT;				      \
-	    break;							      \
+	    if (! ignore_errors_p ())					      \
+	      {								      \
+	        /* This is an illegal character.  */			      \
+		result = __GCONV_ILLEGAL_INPUT;				      \
+		break;							      \
+	      }								      \
+									      \
+	    inptr += 4;							      \
+	    ++*converted;						      \
+	    continue;							      \
 	  }								      \
       }									      \
     else if (from_ucs4[ch][0] == '\0' && ch != 0)			      \
       {									      \
 	/* Illegal characters.  */					      \
-	result = __GCONV_ILLEGAL_INPUT;					      \
-	break;								      \
+	if (! ignore_errors_p ())					      \
+	  {								      \
+	    result = __GCONV_ILLEGAL_INPUT;				      \
+	    break;							      \
+	  }								      \
+									      \
+	++*converted;							      \
+	inptr += 4;							      \
+	continue;							      \
       }									      \
     else								      \
       cp = from_ucs4[ch];						      \
@@ -534,6 +573,7 @@ static const char from_ucs4[][2] =
 	if (NEED_LENGTH_TEST && outptr >= outend)			      \
 	  {								      \
 	    /* The result does not fit into the buffer.  */		      \
+	    --outptr;							      \
 	    result = __GCONV_FULL_OUTPUT;				      \
 	    break;							      \
 	  }								      \
diff --git a/iconvdata/johab.c b/iconvdata/johab.c
index 1822b0d491..ca4d053897 100644
--- a/iconvdata/johab.c
+++ b/iconvdata/johab.c
@@ -183,8 +183,16 @@ johab_sym_hanja_to_ucs (uint_fast32_t idx, uint_fast32_t c1, uint_fast32_t c2)
 	    || (ch > 0xd3 && ch < 0xd9))				      \
 	  {								      \
 	    /* These are illegal.  */					      \
-	    result = __GCONV_ILLEGAL_INPUT;				      \
-	    break;							      \
+	    if (! ignore_errors_p ())					      \
+	      {								      \
+	        /* This is an illegal character.  */			      \
+	        result = __GCONV_ILLEGAL_INPUT;				      \
+	        break;							      \
+	      }								      \
+									      \
+	    ++inptr;							      \
+	    ++*converted;						      \
+	    continue;							      \
 	  }								      \
 	else								      \
 	  {								      \
@@ -215,8 +223,16 @@ johab_sym_hanja_to_ucs (uint_fast32_t idx, uint_fast32_t c1, uint_fast32_t c2)
 		if (i == -1 || m == -1 || f == -1)			      \
 		  {							      \
 		    /* This is illegal.  */				      \
-		    result = __GCONV_ILLEGAL_INPUT;			      \
-		    break;						      \
+		    if (! ignore_errors_p ())				      \
+		      {							      \
+		        /* This is an illegal character.  */		      \
+		        result = __GCONV_ILLEGAL_INPUT;			      \
+		        break;						      \
+		      }							      \
+									      \
+		    ++inptr;						      \
+		    ++*converted;					      \
+		    continue;						      \
 		  }							      \
 		else if (i > 0 && m > 0)				      \
 		  ch = ((i - 1) * 21 + (m - 1)) * 28 + f + 0xac00;	      \
@@ -229,8 +245,16 @@ johab_sym_hanja_to_ucs (uint_fast32_t idx, uint_fast32_t c1, uint_fast32_t c2)
 		else							      \
 		  {							      \
 		    /* This is illegal.  */				      \
-		    result = __GCONV_ILLEGAL_INPUT;			      \
-		    break;						      \
+		    if (! ignore_errors_p ())				      \
+		      {							      \
+		        /* This is an illegal character.  */		      \
+		        result = __GCONV_ILLEGAL_INPUT;			      \
+		        break;						      \
+		      }							      \
+									      \
+		    ++inptr;						      \
+		    ++*converted;					      \
+		    continue;						      \
 		  }							      \
 	      }								      \
 	    else							      \
@@ -238,15 +262,31 @@ johab_sym_hanja_to_ucs (uint_fast32_t idx, uint_fast32_t c1, uint_fast32_t c2)
 		if (ch2 < 0x31 || (ch2 > 0x7e && ch2 < 0x91) || ch2 == 0xff)  \
 		  {							      \
 		    /* This is illegal.  */				      \
-		    result = __GCONV_ILLEGAL_INPUT;			      \
-		    break;						      \
+		    if (! ignore_errors_p ())				      \
+		      {							      \
+		        /* This is an illegal character.  */		      \
+		        result = __GCONV_ILLEGAL_INPUT;			      \
+		        break;						      \
+		      }							      \
+									      \
+		    ++inptr;						      \
+		    ++*converted;					      \
+		    continue;						      \
 		  }							      \
 		else if (ch == 0xda && ch2 > 0xa0 && ch2 < 0xd4)	      \
 		  {							      \
 		    /* This is illegal.  Modern Hangul Jaso is defined	      \
 		       elsewhere in Johab */				      \
-		    result = __GCONV_ILLEGAL_INPUT;			      \
-		    break;						      \
+		    if (! ignore_errors_p ())				      \
+		      {							      \
+		        /* This is an illegal character.  */		      \
+		        result = __GCONV_ILLEGAL_INPUT;			      \
+		        break;						      \
+		      }							      \
+									      \
+		    ++inptr;						      \
+		    ++*converted;					      \
+		    continue;						      \
 		  }							      \
 		else							      \
 		  {							      \
@@ -267,8 +307,16 @@ johab_sym_hanja_to_ucs (uint_fast32_t idx, uint_fast32_t c1, uint_fast32_t c2)
 	if (ch == 0)							      \
 	  {								      \
 	    /* This is an illegal character.  */			      \
-	    result = __GCONV_ILLEGAL_INPUT;				      \
-	    break;							      \
+	    if (! ignore_errors_p ())					      \
+	      {								      \
+	        /* This is an illegal character.  */			      \
+	        result = __GCONV_ILLEGAL_INPUT;				      \
+	        break;							      \
+	      }								      \
+									      \
+	    inptr += 2;							      \
+	    ++*converted;						      \
+	    continue;							      \
 	  }								      \
 									      \
 	inptr += 2;							      \
@@ -354,8 +402,16 @@ johab_sym_hanja_to_ucs (uint_fast32_t idx, uint_fast32_t c1, uint_fast32_t c2)
 	      }								      \
 	    if (written == __UNKNOWN_10646_CHAR)			      \
 	      {								      \
-		result = __GCONV_ILLEGAL_INPUT;				      \
-		break;							      \
+		if (! ignore_errors_p ())				      \
+		  {							      \
+		    /* This is an illegal character.  */		      \
+		    result = __GCONV_ILLEGAL_INPUT;			      \
+		    break;						      \
+		  }							      \
+									      \
+		inptr += 4;						      \
+		++*converted;						      \
+		continue;						      \
 	      }								      \
 									      \
 	    outptr[0] -= 0x4a;						      \
@@ -383,8 +439,16 @@ johab_sym_hanja_to_ucs (uint_fast32_t idx, uint_fast32_t c1, uint_fast32_t c2)
 	      }								      \
 	    if (written == __UNKNOWN_10646_CHAR)			      \
 	      {								      \
-		result = __GCONV_ILLEGAL_INPUT;				      \
-		break;							      \
+		if (! ignore_errors_p ())				      \
+		  {							      \
+		    /* This is an illegal character.  */		      \
+		    result = __GCONV_ILLEGAL_INPUT;			      \
+		    break;						      \
+		  }							      \
+									      \
+		inptr += 4;						      \
+		++*converted;						      \
+		continue;						      \
 	      }								      \
 									      \
 	    outptr[0] -= 0x4a;						      \
diff --git a/iconvdata/sjis.c b/iconvdata/sjis.c
index 4ca7ce985a..07f03f78d7 100644
--- a/iconvdata/sjis.c
+++ b/iconvdata/sjis.c
@@ -4354,11 +4354,19 @@ static const char from_ucs4_extra[0x100][2] =
 	ch = halfkana_to_ucs4[ch - 0xa1];				      \
 	++inptr;							      \
       }									      \
-    else if (ch > 0xea || ch == 0xa0 || ch == 0x7f || ch == 0x80)	      \
+    else if (ch > 0xea || ch == 0xa0 || ch <= 0x80)			      \
       {									      \
 	/* These are illegal.  */					      \
-	result = __GCONV_ILLEGAL_INPUT;					      \
-	break;								      \
+	if (! ignore_errors_p ())					      \
+	  {								      \
+	    /* This is an illegal character.  */			      \
+	    result = __GCONV_ILLEGAL_INPUT;				      \
+	    break;							      \
+	  }								      \
+									      \
+	++inptr;							      \
+	++*converted;							      \
+	continue;							      \
       }									      \
     else								      \
       {									      \
@@ -4382,8 +4390,16 @@ static const char from_ucs4_extra[0x100][2] =
 	    || (idx > 0x9ffc && idx < 0xe040) || idx > 0xeaa4)		      \
 	  {								      \
 	    /* This is illegal.  */					      \
-	    result = __GCONV_ILLEGAL_INPUT;				      \
-	    break;							      \
+	    if (! ignore_errors_p ())					      \
+	      {								      \
+	        /* This is an illegal character.  */			      \
+	        result = __GCONV_ILLEGAL_INPUT;				      \
+	        break;							      \
+	      }								      \
+									      \
+	    ++inptr;							      \
+	    ++*converted;						      \
+	    continue;							      \
 	  }								      \
 	else								      \
 	  {								      \
@@ -4405,8 +4421,16 @@ static const char from_ucs4_extra[0x100][2] =
 	if (ch == 0)							      \
 	  {								      \
 	    /* This is an illegal character.  */			      \
-	    result = __GCONV_ILLEGAL_INPUT;				      \
-	    break;							      \
+	    if (! ignore_errors_p ())					      \
+	      {								      \
+	        /* This is an illegal character.  */			      \
+	        result = __GCONV_ILLEGAL_INPUT;				      \
+	        break;							      \
+	      }								      \
+									      \
+	    inptr += 2;							      \
+	    ++*converted;						      \
+	    continue;							      \
 	  }								      \
       }									      \
 									      \
@@ -4437,8 +4461,16 @@ static const char from_ucs4_extra[0x100][2] =
 	else								      \
 	  {								      \
 	    /* Illegal character.  */					      \
-	    result = __GCONV_ILLEGAL_INPUT;				      \
-	    break;							      \
+	    if (! ignore_errors_p ())					      \
+	      {								      \
+	        /* This is an illegal character.  */			      \
+		result = __GCONV_ILLEGAL_INPUT;				      \
+		break;							      \
+	      }								      \
+									      \
+	    inptr += 4;							      \
+	    ++*converted;						      \
+	    continue;							      \
 	  }								      \
       }									      \
     else								      \
@@ -4447,21 +4479,29 @@ static const char from_ucs4_extra[0x100][2] =
     if (cp[0] == '\0' && ch != 0)					      \
       {									      \
 	/* Illegal character.  */					      \
-	result = __GCONV_ILLEGAL_INPUT;					      \
-	break;								      \
-      }									      \
+	if (! ignore_errors_p ())					      \
+	  {								      \
+	    /* This is an illegal character.  */			      \
+	    result = __GCONV_ILLEGAL_INPUT;				      \
+	    break;							      \
+	  }								      \
 									      \
-    *outptr++ = cp[0];							      \
-    /* Now test for a possible second byte and write this if possible.  */    \
-    if (cp[1] != '\0')							      \
+	++*converted;							      \
+      }									      \
+    else								      \
       {									      \
-	if (NEED_LENGTH_TEST && outptr >= outend)			      \
+	*outptr++ = cp[0];						      \
+	/* Now test for a possible second byte and write this if possible.  */\
+	if (cp[1] != '\0')						      \
 	  {								      \
-	    /* The result does not fit into the buffer.  */		      \
-	    result = __GCONV_FULL_OUTPUT;				      \
-	    break;							      \
+	    if (NEED_LENGTH_TEST && outptr >= outend)			      \
+	      {								      \
+		/* The result does not fit into the buffer.  */		      \
+		result = __GCONV_FULL_OUTPUT;				      \
+		break;							      \
+	      }								      \
+	    *outptr++ = cp[1];						      \
 	  }								      \
-	*outptr++ = cp[1];						      \
       }									      \
 									      \
     inptr += 4;								      \
diff --git a/iconvdata/t.61.c b/iconvdata/t.61.c
index 10a52a1f38..1623606496 100644
--- a/iconvdata/t.61.c
+++ b/iconvdata/t.61.c
@@ -401,8 +401,16 @@ static const char from_ucs4[][2] =
 	if (ch2 < 0x20 || ch2 >= 0x80)					      \
 	  {								      \
 	    /* This is illegal.  */					      \
-	    result = __GCONV_ILLEGAL_INPUT;				      \
-	    break;							      \
+	    if (! ignore_errors_p ())					      \
+	      {								      \
+		/* This is an illegal character.  */			      \
+		result = __GCONV_ILLEGAL_INPUT;				      \
+		break;							      \
+	      }								      \
+									      \
+	    ++inptr;							      \
+	    ++*converted;						      \
+	    continue;							      \
 	  }								      \
 									      \
 	ch = to_ucs4_comb[ch - 0xc1][ch2 - 0x20];			      \
@@ -418,12 +426,21 @@ static const char from_ucs4[][2] =
     if (ch == 0 && *inptr != '\0')					      \
       {									      \
 	/* This is an illegal character.  */				      \
-	result = __GCONV_ILLEGAL_INPUT;					      \
-	break;								      \
-      }									      \
+	if (! ignore_errors_p ())					      \
+	  {								      \
+	    /* This is an illegal character.  */			      \
+	    --inptr;							      \
+	    result = __GCONV_ILLEGAL_INPUT;				      \
+	    break;							      \
+	  }								      \
 									      \
-    put32 (outptr, ch);							      \
-    outptr += 4;							      \
+	++*converted;							      \
+      }									      \
+    else								      \
+      {									      \
+	put32 (outptr, ch);						      \
+	outptr += 4;							      \
+      }									      \
   }
 #include <iconv/loop.c>
 
@@ -448,8 +465,16 @@ static const char from_ucs4[][2] =
 	else if (ch < 0x2d8 || ch > 0x2dd || ch == 0x02dc)		      \
 	  {								      \
 	    /* Illegal characters.  */					      \
-	    result = __GCONV_ILLEGAL_INPUT;				      \
-	    break;							      \
+	    if (! ignore_errors_p ())					      \
+	      {								      \
+	        /* This is an illegal character.  */			      \
+		result = __GCONV_ILLEGAL_INPUT;				      \
+		break;							      \
+	      }								      \
+									      \
+	    inptr += 4;							      \
+	    ++*converted;						      \
+	    continue;							      \
 	  }								      \
 	else								      \
 	  {								      \
@@ -467,8 +492,16 @@ static const char from_ucs4[][2] =
 	if (cp[0] == '\0' && ch != 0)					      \
 	  {								      \
 	    /* Illegal.  */						      \
-	    result = __GCONV_ILLEGAL_INPUT;				      \
-	    break;							      \
+	    if (! ignore_errors_p ())					      \
+	      {								      \
+	        /* This is an illegal character.  */			      \
+		result = __GCONV_ILLEGAL_INPUT;				      \
+		break;							      \
+	      }								      \
+									      \
+	    inptr += 4;							      \
+	    ++*converted;						      \
+	    continue;							      \
 	  }								      \
       }									      \
 									      \
diff --git a/iconvdata/uhc.c b/iconvdata/uhc.c
index e42cb2e000..15faf1ea89 100644
--- a/iconvdata/uhc.c
+++ b/iconvdata/uhc.c
@@ -3066,8 +3066,16 @@ static const char uhc_hangul_from_ucs[11172][2] =
     else if (ch <= 0x80 || ch >= 0xfe || ch == 0xc9)			      \
       {									      \
 	/* This is illegal.  */						      \
-	result = __GCONV_ILLEGAL_INPUT;					      \
-	break;								      \
+	if (! ignore_errors_p ())					      \
+	  {								      \
+	    /* This is an illegal character.  */			      \
+	    result = __GCONV_ILLEGAL_INPUT;				      \
+	    break;							      \
+	  }								      \
+									      \
+	++inptr;							      \
+	++*converted;							      \
+	continue;							      \
       }									      \
     else								      \
       {									      \
@@ -3109,8 +3117,16 @@ static const char uhc_hangul_from_ucs[11172][2] =
 		|| (ch2 > 0x7a && ch2 < 0x81) || (ch == 0xc6 && ch2 > 0x52))  \
 	      {								      \
 		/* This is not legal.  */				      \
-		result = __GCONV_ILLEGAL_INPUT;				      \
-		break;							      \
+		if (! ignore_errors_p ())				      \
+		  {							      \
+		    /* This is an illegal character.  */		      \
+		    result = __GCONV_ILLEGAL_INPUT;			      \
+		    break;						      \
+		  }							      \
+									      \
+		++inptr;						      \
+		++*converted;						      \
+		continue;						      \
 	      }								      \
 									      \
 	    ch = uhc_extra_to_ucs[ch2 - 0x41				      \
@@ -3122,8 +3138,16 @@ static const char uhc_hangul_from_ucs[11172][2] =
 	    if (ch == 0)						      \
 	      {								      \
 		/* This is an illegal character.  */			      \
-		result = __GCONV_ILLEGAL_INPUT;				      \
-		break;							      \
+		if (! ignore_errors_p ())				      \
+		  {							      \
+		    /* This is an illegal character.  */		      \
+		    result = __GCONV_ILLEGAL_INPUT;			      \
+		    break;						      \
+		  }							      \
+									      \
+		inptr += 2;						      \
+		++*converted;						      \
+		continue;						      \
 	      }								      \
 									      \
 	    inptr += 2;							      \
@@ -3134,8 +3158,16 @@ static const char uhc_hangul_from_ucs[11172][2] =
 	    if (ch == __UNKNOWN_10646_CHAR)				      \
 	      {								      \
 		/* Illegal.  */						      \
-		result = __GCONV_ILLEGAL_INPUT;				      \
-		break;							      \
+		if (! ignore_errors_p ())				      \
+		  {							      \
+		    /* This is an illegal character.  */		      \
+		    result = __GCONV_ILLEGAL_INPUT;			      \
+		    break;						      \
+		  }							      \
+									      \
+		inptr += 2;						      \
+		++*converted;						      \
+		continue;						      \
 	      }								      \
 	  }								      \
       }									      \
@@ -3184,8 +3216,16 @@ static const char uhc_hangul_from_ucs[11172][2] =
 	  }								      \
 	if (written == __UNKNOWN_10646_CHAR)				      \
 	  {								      \
-	    result = __GCONV_ILLEGAL_INPUT;				      \
-	    break;							      \
+	    if (! ignore_errors_p ())					      \
+	      {								      \
+	        /* This is an illegal character.  */			      \
+		result = __GCONV_ILLEGAL_INPUT;				      \
+		break;							      \
+	      }								      \
+									      \
+	    inptr += 4;							      \
+	    ++*converted;						      \
+	    continue;							      \
 	  }								      \
 									      \
 	*outptr++ |= 0x80;						      \
@@ -3208,8 +3248,16 @@ static const char uhc_hangul_from_ucs[11172][2] =
 	  }								      \
 	if (written == __UNKNOWN_10646_CHAR)				      \
 	  {								      \
-	    result = __GCONV_ILLEGAL_INPUT;				      \
-	    break;							      \
+	    if (! ignore_errors_p ())					      \
+	      {								      \
+	        /* This is an illegal character.  */			      \
+		result = __GCONV_ILLEGAL_INPUT;				      \
+		break;							      \
+	      }								      \
+									      \
+	    inptr += 4;							      \
+	    ++*converted;						      \
+	    continue;							      \
 	  }								      \
 									      \
 	*outptr++ |= 0x80;						      \
diff --git a/iconvdata/unicode.c b/iconvdata/unicode.c
index 883e7b18da..7f2aca51b4 100644
--- a/iconvdata/unicode.c
+++ b/iconvdata/unicode.c
@@ -151,13 +151,21 @@ gconv_end (struct __gconv_step *data)
 									      \
     if (c >= 0x10000)							      \
       {									      \
-	result = __GCONV_ILLEGAL_INPUT;					      \
-	break;								      \
-      }									      \
+	if (! ignore_errors_p ())					      \
+	  {								      \
+	    /* This is an illegal character.  */			      \
+	    result = __GCONV_ILLEGAL_INPUT;				      \
+	    break;							      \
+	  }								      \
 									      \
-    put16 (outptr, c);							      \
+	++*converted;							      \
+      }									      \
+    else								      \
+      {									      \
+	put16 (outptr, c);						      \
+	outptr += 2;							      \
+      }									      \
 									      \
-    outptr += 2;							      \
     inptr += 4;								      \
   }
 #define EXTRA_LOOP_DECLS \
diff --git a/iconvdata/utf-16.c b/iconvdata/utf-16.c
index a7a01a8302..9ca2e0bc42 100644
--- a/iconvdata/utf-16.c
+++ b/iconvdata/utf-16.c
@@ -201,8 +201,16 @@ gconv_end (struct __gconv_step *data)
 	  {								      \
 	    if (c >= 0x110000)						      \
 	      {								      \
-		result = __GCONV_ILLEGAL_INPUT;				      \
-		break;							      \
+		if (! ignore_errors_p ())				      \
+		  {							      \
+		    /* This is an illegal character.  */		      \
+		    result = __GCONV_ILLEGAL_INPUT;			      \
+		    break;						      \
+		  }							      \
+									      \
+		++*converted;						      \
+		inptr += 4;						      \
+		continue;						      \
 	      }								      \
 									      \
 	    /* Generate a surrogate character.  */			      \
@@ -226,8 +234,16 @@ gconv_end (struct __gconv_step *data)
 	  {								      \
 	    if (c >= 0x110000)						      \
 	      {								      \
-		result = __GCONV_ILLEGAL_INPUT;				      \
-		break;							      \
+		if (! ignore_errors_p ())				      \
+		  {							      \
+		    /* This is an illegal character.  */		      \
+		    result = __GCONV_ILLEGAL_INPUT;			      \
+		    break;						      \
+		  }							      \
+									      \
+		++*converted;						      \
+		inptr += 4;						      \
+		continue;						      \
 	      }								      \
 									      \
 	    /* Generate a surrogate character.  */			      \
@@ -291,9 +307,15 @@ gconv_end (struct __gconv_step *data)
 	    if (u2 < 0xdc00 || u2 >= 0xdfff)				      \
 	      {								      \
 		/* This is no valid second word for a surrogate.  */	      \
-		result = __GCONV_ILLEGAL_INPUT;				      \
-		inptr -= 2;						      \
-		break;							      \
+		if (! ignore_errors_p ())				      \
+		  {							      \
+		    inptr -= 2;						      \
+		    result = __GCONV_ILLEGAL_INPUT;			      \
+		    break;						      \
+		  }							      \
+									      \
+		++*converted;						      \
+		continue;						      \
 	      }								      \
 									      \
 	    put32 (outptr, ((u1 - 0xd7c0) << 10) + (u2 - 0xdc00));	      \
@@ -327,9 +349,15 @@ gconv_end (struct __gconv_step *data)
 	    if (u2 < 0xdc00 || u2 >= 0xdfff)				      \
 	      {								      \
 		/* This is no valid second word for a surrogate.  */	      \
-		result = __GCONV_ILLEGAL_INPUT;				      \
-		inptr -= 2;						      \
-		break;							      \
+		if (! ignore_errors_p ())				      \
+		  {							      \
+		    inptr -= 2;						      \
+		    result = __GCONV_ILLEGAL_INPUT;			      \
+		    break;						      \
+		  }							      \
+									      \
+		++*converted;						      \
+		continue;						      \
 	      }								      \
 									      \
 	    put32 (outptr, ((u1 - 0xd7c0) << 10) + (u2 - 0xdc00));	      \