about summary refs log tree commit diff
path: root/iconvdata
diff options
context:
space:
mode:
Diffstat (limited to 'iconvdata')
-rw-r--r--iconvdata/ibm930.c137
-rw-r--r--iconvdata/ibm930.h77
-rw-r--r--iconvdata/ibm933.c127
-rw-r--r--iconvdata/ibm933.h79
-rw-r--r--iconvdata/ibm935.c131
-rw-r--r--iconvdata/ibm935.h77
-rw-r--r--iconvdata/ibm937.c97
-rw-r--r--iconvdata/ibm939.c111
-rw-r--r--iconvdata/ibm939.h77
-rw-r--r--iconvdata/testdata/IBM930bin59775 -> 59776 bytes
-rw-r--r--iconvdata/testdata/IBM933bin55021 -> 55022 bytes
-rw-r--r--iconvdata/testdata/IBM935bin47825 -> 47826 bytes
-rw-r--r--iconvdata/testdata/IBM937bin102085 -> 102087 bytes
-rw-r--r--iconvdata/testdata/IBM939bin59775 -> 59776 bytes
14 files changed, 518 insertions, 395 deletions
diff --git a/iconvdata/ibm930.c b/iconvdata/ibm930.c
index 11270ff4af..1a78b90e01 100644
--- a/iconvdata/ibm930.c
+++ b/iconvdata/ibm930.c
@@ -1,5 +1,5 @@
 /* Conversion from and to IBM930.
-   Copyright (C) 2000 Free Software Foundation, Inc.
+   Copyright (C) 2000, 2001 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Masahide Washizawa <washi@yamato.ibm.co.jp>, 2000.
 
@@ -32,42 +32,77 @@
 #define CHARSET_NAME	"IBM930//"
 #define FROM_LOOP	from_ibm930
 #define TO_LOOP		to_ibm930
+#define MIN_NEEDED_FROM	1
+#define MAX_NEEDED_FROM	2
+#define MIN_NEEDED_TO	4
+#define MAX_NEEDED_TO	4
+#define PREPARE_LOOP \
+  int save_curcs;							      \
+  int *curcsp = &data->__statep->__count;
+#define EXTRA_LOOP_ARGS		, curcsp
 
 /* Definitions of initialization and destructor function.  */
 #define DEFINE_INIT	1
 #define DEFINE_FINI	1
 
-#define MIN_NEEDED_FROM	1
-#define MIN_NEEDED_TO	4
+
+/* Since this is a stateful encoding we have to provide code which resets
+   the output state to the initial state.  This has to be done during the
+   flushing.  */
+#define EMIT_SHIFT_TO_INIT \
+  if ((data->__statep->__count & ~7) != sb)				      \
+    {									      \
+      if (FROM_DIRECTION)						      \
+	data->__statep->__count &= 7;					      \
+      else								      \
+	{								      \
+	  unsigned char *outbuf = data->__outbuf;			      \
+									      \
+	  /* We are not in the initial state.  To switch back we have	      \
+	     to emit `SI'.  */						      \
+	  if (__builtin_expect (outbuf >= data->__outbufend, 0))	      \
+	    /* We don't have enough room in the output buffer.  */	      \
+	    status = __GCONV_FULL_OUTPUT;				      \
+	  else								      \
+	    {								      \
+	      /* Write out the shift sequence.  */			      \
+	      *outbuf++ = SI;						      \
+	      data->__outbuf = outbuf;					      \
+	      data->__statep->__count &= 7;				      \
+	    }								      \
+	}								      \
+    }
+
+
+/* Since we might have to reset input pointer we must be able to save
+   and retore the state.  */
+#define SAVE_RESET_STATE(Save) \
+  if (Save)								      \
+    save_curcs = *curcsp;						      \
+  else									      \
+    *curcsp = save_curcs
+
 
 /* Current codeset type.  */
 enum
 {
-  init = 0,
-  sb,
-  db
+  sb = 0,
+  db = 64
 };
 
+
 /* First, define the conversion function from IBM-930 to UCS4.  */
 #define MIN_NEEDED_INPUT  	MIN_NEEDED_FROM
+#define MAX_NEEDED_INPUT  	MAX_NEEDED_FROM
 #define MIN_NEEDED_OUTPUT 	MIN_NEEDED_TO
-#define INIT_PARAMS 		int curcs = init;
 #define LOOPFCT 		FROM_LOOP
 #define BODY \
   {									      \
     uint32_t ch = *inptr;						      \
     uint32_t res;							      \
-    const struct gap *rp1 = __ibm930sb_to_ucs4_idx;			      \
-    const struct gap *rp2 = __ibm930db_to_ucs4_idx;			      \
 									      \
     if (__builtin_expect (ch, 0) == SO)					      \
       {									      \
-	if (__builtin_expect (inptr + 1 >= inend, 0))			      \
-	  {								      \
-	    result = __GCONV_INCOMPLETE_INPUT;				      \
-	    break;							      \
-	  }								      \
-									      \
 	/* Shift OUT, change to DBCS converter.  */			      \
 	if (curcs == db)						      \
 	  {								      \
@@ -76,16 +111,10 @@ enum
 	  }								      \
 	curcs = db;							      \
 	++inptr;							      \
-	ch = *inptr;							      \
+	continue;							      \
       }									      \
     else if (__builtin_expect (ch, 0) == SI)				      \
       {									      \
-	if (__builtin_expect (inptr + 1 >= inend, 0))			      \
-	  {								      \
-	    result = __GCONV_INCOMPLETE_INPUT;				      \
-	    break;							      \
-	  }								      \
-									      \
 	/* Shift IN, change to SBCS converter */			      \
 	if (curcs == sb)						      \
 	  {								      \
@@ -94,19 +123,14 @@ enum
 	  }								      \
 	curcs = sb;							      \
 	++inptr;							      \
-	ch = *inptr;							      \
+	continue;							      \
       }									      \
 									      \
-    if (curcs == sb || curcs == init)					      \
+    if (curcs == sb)							      \
       {									      \
 	/* Use the IBM930 table for single byte.  */			      \
-	while (ch > rp1->end)						      \
-	  ++rp1;							      \
-									      \
-	if (__builtin_expect (rp1 == NULL, 0)				      \
-	    || __builtin_expect (ch < rp1->start, 0)			      \
-	    || (res = __ibm930sb_to_ucs4[ch + rp1->idx],		      \
-		__builtin_expect (res, L'\1') == L'\0' && ch != '\0'))	      \
+	res = __ibm930sb_to_ucs4[ch];					      \
+	if (__builtin_expect (res, L'\1') == L'\0' && ch != '\0')	      \
 	  {								      \
 	    /* This is an illegal character.  */			      \
 	    if (! ignore_errors_p ())					      \
@@ -115,21 +139,21 @@ enum
 		break;							      \
 	      }								      \
 	    ++*irreversible;						      \
-	    ++inptr;							      \
-	    continue;							      \
 	  }								      \
 	else								      \
 	  {								      \
-	    if (res == 0xa5)						      \
-	      res = 0x5c;						      \
 	    put32 (outptr, res);					      \
 	    outptr += 4;						      \
-	    ++inptr;							      \
 	  }								      \
+	++inptr;							      \
       }									      \
-    else if (curcs == db)						      \
+    else								      \
       {									      \
 	/* Use the IBM930 table for double byte. */			      \
+	const struct gap *rp2 = __ibm930db_to_ucs4_idx;			      \
+									      \
+	assert (curcs == db);						      \
+									      \
 	if (__builtin_expect (inptr + 1 >= inend, 0))			      \
 	  {								      \
 	    /* The second character is not available.  Store the	      \
@@ -142,8 +166,7 @@ enum
 	while (ch > rp2->end)						      \
 	  ++rp2;							      \
 									      \
-	if (__builtin_expect (rp2 == NULL, 0)				      \
-	    || __builtin_expect (ch < rp2->start, 0)			      \
+	if (__builtin_expect (ch < rp2->start, 0)			      \
 	    || (res = __ibm930db_to_ucs4[ch + rp2->idx],		      \
 		__builtin_expect (res, L'\1') == L'\0' && ch != '\0'))	      \
 	  {								      \
@@ -154,24 +177,25 @@ enum
 		break;							      \
 	      }								      \
 	    ++*irreversible;						      \
-	    inptr += 2;							      \
-	    continue;							      \
 	  }								      \
 	else								      \
 	  {								      \
 	    put32 (outptr, res);					      \
 	    outptr += 4;						      \
-	    inptr += 2;							      \
 	  }								      \
+	inptr += 2;							      \
       }									      \
   }
 #define LOOP_NEED_FLAGS
+#define EXTRA_LOOP_DECLS	, int *curcsp
+#define INIT_PARAMS		int curcs = *curcsp & ~7
+#define UPDATE_PARAMS		*curcsp = curcs
 #include <iconv/loop.c>
 
 /* Next, define the other direction.  */
 #define MIN_NEEDED_INPUT	MIN_NEEDED_TO
 #define MIN_NEEDED_OUTPUT	MIN_NEEDED_FROM
-#define INIT_PARAMS 		int curcs = init;
+#define MAX_NEEDED_OUTPUT	MAX_NEEDED_FROM
 #define LOOPFCT			TO_LOOP
 #define BODY \
   {									      \
@@ -182,16 +206,21 @@ enum
 									      \
     if (__builtin_expect (ch, 0) >= 0xffff)				      \
       {									      \
-	rp1 = NULL;							      \
-	rp2 = NULL;							      \
+	if (! ignore_errors_p ())					      \
+	  {								      \
+	    result = __GCONV_ILLEGAL_INPUT;				      \
+	    break;							      \
+	  }								      \
+	++*irreversible;						      \
+	inptr += 4;							      \
+	continue;							      \
       }									      \
-    else								      \
-      while (ch > rp1->end)						      \
-	++rp1;								      \
+									      \
+    while (ch > rp1->end)						      \
+      ++rp1;								      \
 									      \
     /* Use the UCS4 table for single byte.  */				      \
-    if (__builtin_expect (rp1 == NULL, 0)				      \
-	|| __builtin_expect (ch < rp1->start, 0)			      \
+    if (__builtin_expect (ch < rp1->start, 0)			      \
 	|| (cp = __ucs4_to_ibm930sb[ch + rp1->idx],			      \
 	    __builtin_expect (cp[0], L'\1') == L'\0' && ch != '\0'))	      \
       {									      \
@@ -199,8 +228,7 @@ enum
 	while (ch > rp2->end)						      \
 	  ++rp2;							      \
 									      \
-	if (__builtin_expect (rp2 == NULL, 0)				      \
-	    || __builtin_expect (ch < rp2->start, 0)			      \
+	if (__builtin_expect (ch < rp2->start, 0)			      \
 	    || (cp = __ucs4_to_ibm930db[ch + rp2->idx],			      \
 		__builtin_expect (cp[0], L'\1')==L'\0' && ch != '\0'))	      \
 	  {								      \
@@ -214,7 +242,7 @@ enum
 	  }								      \
 	else								      \
 	  {								      \
-	    if (curcs == init || curcs == sb)				      \
+	    if (curcs == sb)						      \
 	      {								      \
 		if (__builtin_expect (outptr+1 > outend, 0))		      \
 		  {							      \
@@ -264,6 +292,9 @@ enum
     inptr += 4;								      \
   }
 #define LOOP_NEED_FLAGS
+#define EXTRA_LOOP_DECLS	, int *curcsp
+#define INIT_PARAMS		int curcs = *curcsp & ~7
+#define UPDATE_PARAMS		*curcsp = curcs
 #include <iconv/loop.c>
 
 /* Now define the toplevel functions.  */
diff --git a/iconvdata/ibm930.h b/iconvdata/ibm930.h
index 4ad6bb8f00..d7cca13f2e 100644
--- a/iconvdata/ibm930.h
+++ b/iconvdata/ibm930.h
@@ -1,5 +1,5 @@
 /* Tables for conversion from and to IBM930.
-   Copyright (C) 2000 Free Software Foundation, Inc.
+   Copyright (C) 2000, 2001 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Masahide Washizawa <washi@yamato.ibm.co.jp>, 2000.
 
@@ -32,49 +32,40 @@ struct gap
 };
 
 
-static const struct gap __ibm930sb_to_ucs4_idx[] =
+static const uint16_t __ibm930sb_to_ucs4[256] =
 {
-  { start: 0x0000, end: 0x0056, idx:     0 },
-  { start: 0x0058, end: 0x0058, idx:    -1 },
-  { start: 0x005a, end: 0x0069, idx:    -2 },
-  { start: 0x006b, end: 0x009b, idx:    -3 },
-  { start: 0x009d, end: 0x00c9, idx:    -4 },
-  { start: 0x00d0, end: 0x00d9, idx:   -10 },
-  { start: 0x00e0, end: 0x00e0, idx:   -16 },
-  { start: 0x00e2, end: 0x00e9, idx:   -17 },
-  { start: 0x00f0, end: 0x00f9, idx:   -23 },
-  { start: 0x00ff, end: 0x00ff, idx:   -28 },
-  { start: 0xffff, end: 0xffff, idx:     0 }
-};
-
-static const uint16_t __ibm930sb_to_ucs4[] =
-{
-  0x0000, 0x0001, 0x0002, 0x0003, 0x009C, 0x0009, 0x0086, 0x007F, 0x0097,
-  0x008D, 0x008E, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F, 0x0010, 0x0011,
-  0x0012, 0x0013, 0x009D, 0x0085, 0x0008, 0x0087, 0x0018, 0x0019, 0x0092,
-  0x008F, 0x001C, 0x001D, 0x001E, 0x001F, 0x0080, 0x0081, 0x0082, 0x0083,
-  0x0084, 0x000A, 0x0017, 0x001B, 0x0088, 0x0089, 0x008A, 0x008B, 0x008C,
-  0x0005, 0x0006, 0x0007, 0x0090, 0x0091, 0x0016, 0x0093, 0x0094, 0x0095,
-  0x0096, 0x0004, 0x0098, 0x0099, 0x009A, 0x009B, 0x0014, 0x0015, 0x009E,
-  0x001A, 0x0020, 0xFF61, 0xFF62, 0xFF63, 0xFF64, 0xFF65, 0xFF66, 0xFF67,
-  0xFF68, 0xFF69, 0x00A3, 0x002E, 0x003C, 0x0028, 0x002B, 0x007C, 0x0026,
-  0xFF6A, 0xFF6B, 0xFF6C, 0xFF6D, 0xFF6E, 0xFF6F, 0xFF70, 0x0021, 0x00A5,
-  0x002A, 0x0029, 0x003B, 0x00AC, 0x002D, 0x002F, 0x0061, 0x0062, 0x0063,
-  0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x002C, 0x0025, 0x005F, 0x003E,
-  0x003F, 0x005B, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F,
-  0x0070, 0x0060, 0x003A, 0x0023, 0x0040, 0x0027, 0x003D, 0x0022, 0x005D,
-  0xFF71, 0xFF72, 0xFF73, 0xFF74, 0xFF75, 0xFF76, 0xFF77, 0xFF78, 0xFF79,
-  0xFF7A, 0x0071, 0xFF7B, 0xFF7C, 0xFF7D, 0xFF7E, 0xFF7F, 0xFF80, 0xFF81,
-  0xFF82, 0xFF83, 0xFF84, 0xFF85, 0xFF86, 0xFF87, 0xFF88, 0xFF89, 0x0072,
-  0xFF8A, 0xFF8B, 0xFF8C, 0x007E, 0x203E, 0xFF8D, 0xFF8E, 0xFF8F, 0xFF90,
-  0xFF91, 0xFF92, 0xFF93, 0xFF94, 0xFF95, 0x0073, 0xFF96, 0xFF97, 0xFF98,
-  0xFF99, 0x005E, 0x00A2, 0x005C, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078,
-  0x0079, 0x007A, 0xFF9A, 0xFF9B, 0xFF9C, 0xFF9D, 0xFF9E, 0xFF9F, 0x007B,
-  0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049,
-  0x007D, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, 0x0050, 0x0051,
-  0x0052, 0x0024, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059,
-  0x005A, 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
-  0x0038, 0x0039, 0x009F
+  /* 0x00 */ 0x0000, 0x0001, 0x0002, 0x0003, 0x009C, 0x0009, 0x0086, 0x007F,
+  /* 0x08 */ 0x0097, 0x008D, 0x008E, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F,
+  /* 0x10 */ 0x0010, 0x0011, 0x0012, 0x0013, 0x009D, 0x0085, 0x0008, 0x0087,
+  /* 0x18 */ 0x0018, 0x0019, 0x0092, 0x008F, 0x001C, 0x001D, 0x001E, 0x001F,
+  /* 0x20 */ 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x000A, 0x0017, 0x001B,
+  /* 0x28 */ 0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x0005, 0x0006, 0x0007,
+  /* 0x30 */ 0x0090, 0x0091, 0x0016, 0x0093, 0x0094, 0x0095, 0x0096, 0x0004,
+  /* 0x38 */ 0x0098, 0x0099, 0x009A, 0x009B, 0x0014, 0x0015, 0x009E, 0x001A,
+  /* 0x40 */ 0x0020, 0xFF61, 0xFF62, 0xFF63, 0xFF64, 0xFF65, 0xFF66, 0xFF67,
+  /* 0x48 */ 0xFF68, 0xFF69, 0x00A3, 0x002E, 0x003C, 0x0028, 0x002B, 0x007C,
+  /* 0x50 */ 0x0026, 0xFF6A, 0xFF6B, 0xFF6C, 0xFF6D, 0xFF6E, 0xFF6F, 0x0000,
+  /* 0x58 */ 0xFF70, 0x0000, 0x0021, 0x005C, 0x002A, 0x0029, 0x003B, 0x00AC,
+  /* 0x60 */ 0x002D, 0x002F, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066,
+  /* 0x68 */ 0x0067, 0x0068, 0x0000, 0x002C, 0x0025, 0x005F, 0x003E, 0x003F,
+  /* 0x70 */ 0x005B, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F,
+  /* 0x78 */ 0x0070, 0x0060, 0x003A, 0x0023, 0x0040, 0x0027, 0x003D, 0x0022,
+  /* 0x80 */ 0x005D, 0xFF71, 0xFF72, 0xFF73, 0xFF74, 0xFF75, 0xFF76, 0xFF77,
+  /* 0x88 */ 0xFF78, 0xFF79, 0xFF7A, 0x0071, 0xFF7B, 0xFF7C, 0xFF7D, 0xFF7E,
+  /* 0x90 */ 0xFF7F, 0xFF80, 0xFF81, 0xFF82, 0xFF83, 0xFF84, 0xFF85, 0xFF86,
+  /* 0x98 */ 0xFF87, 0xFF88, 0xFF89, 0x0072, 0x0000, 0xFF8A, 0xFF8B, 0xFF8C,
+  /* 0xa0 */ 0x007E, 0x203E, 0xFF8D, 0xFF8E, 0xFF8F, 0xFF90, 0xFF91, 0xFF92,
+  /* 0xa8 */ 0xFF93, 0xFF94, 0xFF95, 0x0073, 0xFF96, 0xFF97, 0xFF98, 0xFF99,
+  /* 0xb0 */ 0x005E, 0x00A2, 0x005C, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078,
+  /* 0xb8 */ 0x0079, 0x007A, 0xFF9A, 0xFF9B, 0xFF9C, 0xFF9D, 0xFF9E, 0xFF9F,
+  /* 0xc0 */ 0x007B, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
+  /* 0xc8 */ 0x0048, 0x0049, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+  /* 0xd0 */ 0x007D, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, 0x0050,
+  /* 0xd8 */ 0x0051, 0x0052, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+  /* 0xe0 */ 0x0024, 0x0000, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058,
+  /* 0xe8 */ 0x0059, 0x005A, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+  /* 0xf0 */ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
+  /* 0xf8 */ 0x0038, 0x0039, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x009F
 };
 
 static const struct gap __ibm930db_to_ucs4_idx[] =
diff --git a/iconvdata/ibm933.c b/iconvdata/ibm933.c
index be7fc0c86b..9a9b053627 100644
--- a/iconvdata/ibm933.c
+++ b/iconvdata/ibm933.c
@@ -1,5 +1,5 @@
 /* Conversion from and to IBM933.
-   Copyright (C) 2000 Free Software Foundation, Inc.
+   Copyright (C) 2000, 2001 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Masahide Washizawa <washi@yamato.ibm.co.jp>, 2000.
 
@@ -32,42 +32,76 @@
 #define CHARSET_NAME	"IBM933//"
 #define FROM_LOOP	from_ibm933
 #define TO_LOOP		to_ibm933
+#define MIN_NEEDED_FROM	1
+#define MAX_NEEDED_FROM	2
+#define MIN_NEEDED_TO	4
+#define MAX_NEEDED_TO	4
+#define PREPARE_LOOP \
+  int save_curcs;							      \
+  int *curcsp = &data->__statep->__count;
+#define EXTRA_LOOP_ARGS		, curcsp
 
 /* Definitions of initialization and destructor function.  */
 #define DEFINE_INIT	1
 #define DEFINE_FINI	1
 
-#define MIN_NEEDED_FROM	1
-#define MIN_NEEDED_TO	4
+
+/* Since this is a stateful encoding we have to provide code which resets
+   the output state to the initial state.  This has to be done during the
+   flushing.  */
+#define EMIT_SHIFT_TO_INIT \
+  if ((data->__statep->__count & ~7) != sb)				      \
+    {									      \
+      if (FROM_DIRECTION)						      \
+	data->__statep->__count &= 7;					      \
+      else								      \
+	{								      \
+	  unsigned char *outbuf = data->__outbuf;			      \
+									      \
+	  /* We are not in the initial state.  To switch back we have	      \
+	     to emit `SI'.  */						      \
+	  if (__builtin_expect (outbuf >= data->__outbufend, 0))	      \
+	    /* We don't have enough room in the output buffer.  */	      \
+	    status = __GCONV_FULL_OUTPUT;				      \
+	  else								      \
+	    {								      \
+	      /* Write out the shift sequence.  */			      \
+	      *outbuf++ = SI;						      \
+	      data->__outbuf = outbuf;					      \
+	      data->__statep->__count &= 7;				      \
+	    }								      \
+	}								      \
+    }
+
+
+/* Since we might have to reset input pointer we must be able to save
+   and retore the state.  */
+#define SAVE_RESET_STATE(Save) \
+  if (Save)								      \
+    save_curcs = *curcsp;						      \
+  else									      \
+    *curcsp = save_curcs
+
 
 /* Current codeset type.  */
 enum
 {
-  init = 0,
-  sb,
-  db
+  sb = 0,
+  db = 64
 };
 
 /* First, define the conversion function from IBM-933 to UCS4.  */
 #define MIN_NEEDED_INPUT  	MIN_NEEDED_FROM
+#define MAX_NEEDED_INPUT  	MAX_NEEDED_FROM
 #define MIN_NEEDED_OUTPUT 	MIN_NEEDED_TO
-#define INIT_PARAMS 		int curcs = init;
 #define LOOPFCT 		FROM_LOOP
 #define BODY \
   {									      \
     uint32_t ch = *inptr;						      \
     uint32_t res;							      \
-    const struct gap *rp1 = __ibm933sb_to_ucs4_idx;			      \
-    const struct gap *rp2 = __ibm933db_to_ucs4_idx;			      \
 									      \
     if (__builtin_expect (ch, 0) == SO)					      \
       {									      \
-	if (__builtin_expect (inptr + 1 >= inend, 0))			      \
-	  {								      \
-	    result = __GCONV_INCOMPLETE_INPUT;				      \
-	    break;							      \
-	  }								      \
-									      \
 	/* Shift OUT, change to DBCS converter.  */			      \
 	if (curcs == db)						      \
 	  {								      \
@@ -76,16 +110,10 @@ enum
 	  }								      \
 	curcs = db;							      \
 	++inptr;							      \
-	ch = *inptr;							      \
+	continue;							      \
       }									      \
     else if (__builtin_expect (ch, 0) == SI)				      \
       {									      \
-	if (__builtin_expect (inptr + 1 >= inend, 0))			      \
-	  {								      \
-	    result = __GCONV_INCOMPLETE_INPUT;				      \
-	    break;							      \
-	  }								      \
-									      \
 	/* Shift IN, change to SBCS converter.  */			      \
 	if (curcs == sb)						      \
 	  {								      \
@@ -94,19 +122,14 @@ enum
 	  }								      \
 	curcs = sb;							      \
 	++inptr;							      \
-	ch = *inptr;							      \
+	continue;							      \
       }									      \
 									      \
-    if (curcs == sb || curcs == init)					      \
+    if (curcs == sb)							      \
       {									      \
 	/* Use the IBM933 table for single byte.  */			      \
-	while (ch > rp1->end)						      \
-	  ++rp1;							      \
-									      \
-	if (__builtin_expect (rp1 == NULL, 0)				      \
-	    || __builtin_expect (ch < rp1->start, 0)			      \
-	    || (res = __ibm933sb_to_ucs4[ch + rp1->idx],		      \
-		__builtin_expect (res, L'\1') == L'\0' && ch != '\0'))	      \
+	res = __ibm933sb_to_ucs4[ch];					      \
+	if (__builtin_expect (res, L'\1') == L'\0' && ch != '\0')	      \
 	  {								      \
 	    /* This is an illegal character.  */			      \
 	    if (! ignore_errors_p ())					      \
@@ -115,18 +138,20 @@ enum
 		break;							      \
 	      }								      \
 	    ++*irreversible;						      \
-	    ++inptr;							      \
-	    continue;							      \
 	  }								      \
 	else								      \
 	  {								      \
 	    put32 (outptr, res);					      \
 	    outptr += 4;						      \
-	    ++inptr;							      \
 	  }								      \
+	++inptr;							      \
       }									      \
-    else if (curcs == db)						      \
+    else								      \
       {									      \
+	const struct gap *rp2 = __ibm933db_to_ucs4_idx;			      \
+									      \
+	assert (curcs == db);						      \
+									      \
 	/* Use the IBM933 table for double byte.  */			      \
 	if (__builtin_expect (inptr + 1 >= inend, 0))			      \
 	  {								      \
@@ -164,12 +189,15 @@ enum
       }									      \
   }
 #define LOOP_NEED_FLAGS
+#define EXTRA_LOOP_DECLS	, int *curcsp
+#define INIT_PARAMS		int curcs = *curcsp & ~7
+#define UPDATE_PARAMS		*curcsp = curcs
 #include <iconv/loop.c>
 
 /* Next, define the other direction.  */
 #define MIN_NEEDED_INPUT	MIN_NEEDED_TO
 #define MIN_NEEDED_OUTPUT	MIN_NEEDED_FROM
-#define INIT_PARAMS 		int curcs = init;
+#define MAX_NEEDED_OUTPUT	MAX_NEEDED_FROM
 #define LOOPFCT			TO_LOOP
 #define BODY \
   {									      \
@@ -180,16 +208,21 @@ enum
 									      \
     if (__builtin_expect (ch, 0) >= 0xffff)				      \
       {									      \
-	rp1 = NULL;							      \
-	rp2 = NULL;							      \
+	if (! ignore_errors_p ())					      \
+	  {								      \
+	    result = __GCONV_ILLEGAL_INPUT;				      \
+	    break;							      \
+	  }								      \
+	++*irreversible;						      \
+	inptr += 4;							      \
+	continue;							      \
       }									      \
-    else								      \
-      while (ch > rp1->end)						      \
-	++rp1;								      \
+									      \
+    while (ch > rp1->end)						      \
+      ++rp1;								      \
 									      \
     /* Use the UCS4 table for single byte.  */				      \
-    if (__builtin_expect (rp1 == NULL, 0)				      \
-	|| __builtin_expect (ch < rp1->start, 0)			      \
+    if (__builtin_expect (ch < rp1->start, 0)			      \
 	|| (cp = __ucs4_to_ibm933sb[ch + rp1->idx],			      \
 	    __builtin_expect (cp[0], L'\1') == L'\0' && ch != '\0'))	      \
       {									      \
@@ -197,8 +230,7 @@ enum
 	while (ch > rp2->end)						      \
 	  ++rp2;							      \
 									      \
-	if (__builtin_expect (rp2 == NULL, 0)				      \
-	    || __builtin_expect (ch < rp2->start, 0)			      \
+	if (__builtin_expect (ch < rp2->start, 0)			      \
 	    || (cp = __ucs4_to_ibm933db[ch + rp2->idx],			      \
 		__builtin_expect (cp[0], L'\1')==L'\0' && ch != '\0'))	      \
 	  {								      \
@@ -212,7 +244,7 @@ enum
 	  }								      \
 	else								      \
 	  {								      \
-	    if (curcs == init || curcs == sb)				      \
+	    if (curcs == sb)						      \
 	      {								      \
 		if (__builtin_expect (outptr+1 > outend, 0))		      \
 		  {							      \
@@ -257,6 +289,9 @@ enum
     inptr += 4;								      \
   }
 #define LOOP_NEED_FLAGS
+#define EXTRA_LOOP_DECLS	, int *curcsp
+#define INIT_PARAMS		int curcs = *curcsp & ~7
+#define UPDATE_PARAMS		*curcsp = curcs
 #include <iconv/loop.c>
 
 /* Now define the toplevel functions.  */
diff --git a/iconvdata/ibm933.h b/iconvdata/ibm933.h
index 09daf88b0f..20f25cc999 100644
--- a/iconvdata/ibm933.h
+++ b/iconvdata/ibm933.h
@@ -1,5 +1,5 @@
 /* Tables for conversion from and to IBM933.
-   Copyright (C) 2000 Free Software Foundation, Inc.
+   Copyright (C) 2000, 2001 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Masahide Washizawa <washi@yamato.ibm.co.jp>, 2000.
 
@@ -32,51 +32,40 @@ struct gap
 };
 
 
-static const struct gap __ibm933sb_to_ucs4_idx[] =
+static const uint16_t __ibm933sb_to_ucs4[256] =
 {
-  { start: 0x0000, end: 0x0040, idx:     0 },
-  { start: 0x0042, end: 0x0050, idx:    -1 },
-  { start: 0x0052, end: 0x0070, idx:    -2 },
-  { start: 0x0072, end: 0x008f, idx:    -3 },
-  { start: 0x0091, end: 0x00b0, idx:    -4 },
-  { start: 0x00b2, end: 0x00b2, idx:    -5 },
-  { start: 0x00ba, end: 0x00bc, idx:   -12 },
-  { start: 0x00c0, end: 0x00c9, idx:   -15 },
-  { start: 0x00d0, end: 0x00d9, idx:   -21 },
-  { start: 0x00e0, end: 0x00e0, idx:   -27 },
-  { start: 0x00e2, end: 0x00e9, idx:   -28 },
-  { start: 0x00f0, end: 0x00f9, idx:   -34 },
-  { start: 0x00ff, end: 0x00ff, idx:   -39 },
-  { start: 0xffff, end: 0xffff, idx:     0 }
-};
-
-static const uint16_t __ibm933sb_to_ucs4[] =
-{
-  0x0000, 0x0001, 0x0002, 0x0003, 0x009C, 0x0009, 0x0086, 0x007F, 0x0097,
-  0x008D, 0x008E, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F, 0x0010, 0x0011,
-  0x0012, 0x0013, 0x009D, 0x0085, 0x0008, 0x0087, 0x0018, 0x0019, 0x0092,
-  0x008F, 0x001C, 0x001D, 0x001E, 0x001F, 0x0080, 0x0081, 0x0082, 0x0083,
-  0x0084, 0x000A, 0x0017, 0x001B, 0x0088, 0x0089, 0x008A, 0x008B, 0x008C,
-  0x0005, 0x0006, 0x0007, 0x0090, 0x0091, 0x0016, 0x0093, 0x0094, 0x0095,
-  0x0096, 0x0004, 0x0098, 0x0099, 0x009A, 0x009B, 0x0014, 0x0015, 0x009E,
-  0x001A, 0x0020, 0xFFA0, 0xFFA1, 0xFFA2, 0xFFA3, 0xFFA4, 0xFFA5, 0xFFA6,
-  0xFFA7, 0x00A2, 0x002E, 0x003C, 0x0028, 0x002B, 0x007C, 0x0026, 0xFFA8,
-  0xFFA9, 0xFFAA, 0xFFAB, 0xFFAC, 0xFFAD, 0xFFAE, 0xFFAF, 0x0021, 0x0024,
-  0x002A, 0x0029, 0x003B, 0x00AC, 0x002D, 0x002F, 0xFFB0, 0xFFB1, 0xFFB2,
-  0xFFB3, 0xFFB4, 0xFFB5, 0xFFB6, 0xFFB7, 0x00A6, 0x002C, 0x0025, 0x005F,
-  0x003E, 0x003F, 0x005B, 0xFFB8, 0xFFB9, 0xFFBA, 0xFFBB, 0xFFBC, 0xFFBD,
-  0xFFBE, 0x0060, 0x003A, 0x0023, 0x0040, 0x0027, 0x003D, 0x0022, 0x005D,
-  0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069,
-  0xFFC2, 0xFFC3, 0xFFC4, 0xFFC5, 0xFFC6, 0xFFC7, 0x006A, 0x006B, 0x006C,
-  0x006D, 0x006E, 0x006F, 0x0070, 0x0071, 0x0072, 0xFFCA, 0xFFCB, 0xFFCC,
-  0xFFCD, 0xFFCE, 0xFFCF, 0x203E, 0x007E, 0x0073, 0x0074, 0x0075, 0x0076,
-  0x0077, 0x0078, 0x0079, 0x007A, 0xFFD2, 0xFFD3, 0xFFD4, 0xFFD5, 0xFFD6,
-  0xFFD7, 0x005E, 0x005C, 0xFFDA, 0xFFDB, 0xFFDC, 0x007B, 0x0041, 0x0042,
-  0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x007D, 0x004A,
-  0x004B, 0x004C, 0x004D, 0x004E, 0x004F, 0x0050, 0x0051, 0x0052, 0x20A9,
-  0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005A, 0x0030,
-  0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039,
-  0x009F
+  /* 0x00 */ 0x0000, 0x0001, 0x0002, 0x0003, 0x009C, 0x0009, 0x0086, 0x007F,
+  /* 0x08 */ 0x0097, 0x008D, 0x008E, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F,
+  /* 0x10 */ 0x0010, 0x0011, 0x0012, 0x0013, 0x009D, 0x0085, 0x0008, 0x0087,
+  /* 0x18 */ 0x0018, 0x0019, 0x0092, 0x008F, 0x001C, 0x001D, 0x001E, 0x001F,
+  /* 0x20 */ 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x000A, 0x0017, 0x001B,
+  /* 0x28 */ 0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x0005, 0x0006, 0x0007,
+  /* 0x30 */ 0x0090, 0x0091, 0x0016, 0x0093, 0x0094, 0x0095, 0x0096, 0x0004,
+  /* 0x38 */ 0x0098, 0x0099, 0x009A, 0x009B, 0x0014, 0x0015, 0x009E, 0x001A,
+  /* 0x40 */ 0x0020, 0x0000, 0xFFA0, 0xFFA1, 0xFFA2, 0xFFA3, 0xFFA4, 0xFFA5,
+  /* 0x48 */ 0xFFA6, 0xFFA7, 0x00A2, 0x002E, 0x003C, 0x0028, 0x002B, 0x007C,
+  /* 0x50 */ 0x0026, 0x0000, 0xFFA8, 0xFFA9, 0xFFAA, 0xFFAB, 0xFFAC, 0xFFAD,
+  /* 0x58 */ 0xFFAE, 0xFFAF, 0x0021, 0x0024, 0x002A, 0x0029, 0x003B, 0x00AC,
+  /* 0x60 */ 0x002D, 0x002F, 0xFFB0, 0xFFB1, 0xFFB2, 0xFFB3, 0xFFB4, 0xFFB5,
+  /* 0x68 */ 0xFFB6, 0xFFB7, 0x00A6, 0x002C, 0x0025, 0x005F, 0x003E, 0x003F,
+  /* 0x70 */ 0x005B, 0x0000, 0xFFB8, 0xFFB9, 0xFFBA, 0xFFBB, 0xFFBC, 0xFFBD,
+  /* 0x78 */ 0xFFBE, 0x0060, 0x003A, 0x0023, 0x0040, 0x0027, 0x003D, 0x0022,
+  /* 0x80 */ 0x005D, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
+  /* 0x88 */ 0x0068, 0x0069, 0xFFC2, 0xFFC3, 0xFFC4, 0xFFC5, 0xFFC6, 0xFFC7,
+  /* 0x90 */ 0x0000, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F, 0x0070,
+  /* 0x98 */ 0x0071, 0x0072, 0xFFCA, 0xFFCB, 0xFFCC, 0xFFCD, 0xFFCE, 0xFFCF,
+  /* 0xa0 */ 0x203E, 0x007E, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078,
+  /* 0xa8 */ 0x0079, 0x007A, 0xFFD2, 0xFFD3, 0xFFD4, 0xFFD5, 0xFFD6, 0xFFD7,
+  /* 0xb0 */ 0x005E, 0x0000, 0x005C, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+  /* 0xb8 */ 0x0000, 0x0000, 0xFFDA, 0xFFDB, 0xFFDC, 0x0000, 0x0000, 0x0000,
+  /* 0xc0 */ 0x007B, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
+  /* 0xc8 */ 0x0048, 0x0049, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+  /* 0xd0 */ 0x007D, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, 0x0050,
+  /* 0xd8 */ 0x0051, 0x0052, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+  /* 0xe0 */ 0x20A9, 0x0000, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058,
+  /* 0xe8 */ 0x0059, 0x005A, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+  /* 0xf0 */ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
+  /* 0xf8 */ 0x0038, 0x0039, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x009F
 };
 
 static const struct gap __ibm933db_to_ucs4_idx[] =
diff --git a/iconvdata/ibm935.c b/iconvdata/ibm935.c
index f63398d9ea..04b8e9dd38 100644
--- a/iconvdata/ibm935.c
+++ b/iconvdata/ibm935.c
@@ -1,5 +1,5 @@
 /* Conversion from and to IBM935
-   Copyright (C) 2000 Free Software Foundation, Inc.
+   Copyright (C) 2000, 2001 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Masahide Washizawa <washi@yamato.ibm.co.jp>, 2000.
 
@@ -32,42 +32,76 @@
 #define CHARSET_NAME	"IBM935//"
 #define FROM_LOOP	from_ibm935
 #define TO_LOOP		to_ibm935
+#define MIN_NEEDED_FROM	1
+#define MAX_NEEDED_FROM	2
+#define MIN_NEEDED_TO	4
+#define MAX_NEEDED_TO	4
+#define PREPARE_LOOP \
+  int save_curcs;							      \
+  int *curcsp = &data->__statep->__count;
+#define EXTRA_LOOP_ARGS		, curcsp
 
 /* Definitions of initialization and destructor function.  */
 #define DEFINE_INIT	1
 #define DEFINE_FINI	1
 
-#define MIN_NEEDED_FROM	1
-#define MIN_NEEDED_TO	4
+
+/* Since this is a stateful encoding we have to provide code which resets
+   the output state to the initial state.  This has to be done during the
+   flushing.  */
+#define EMIT_SHIFT_TO_INIT \
+  if ((data->__statep->__count & ~7) != sb)				      \
+    {									      \
+      if (FROM_DIRECTION)						      \
+	data->__statep->__count &= 7;					      \
+      else								      \
+	{								      \
+	  unsigned char *outbuf = data->__outbuf;			      \
+									      \
+	  /* We are not in the initial state.  To switch back we have	      \
+	     to emit `SI'.  */						      \
+	  if (__builtin_expect (outbuf >= data->__outbufend, 0))	      \
+	    /* We don't have enough room in the output buffer.  */	      \
+	    status = __GCONV_FULL_OUTPUT;				      \
+	  else								      \
+	    {								      \
+	      /* Write out the shift sequence.  */			      \
+	      *outbuf++ = SI;						      \
+	      data->__outbuf = outbuf;					      \
+	      data->__statep->__count &= 7;				      \
+	    }								      \
+	}								      \
+    }
+
+
+/* Since we might have to reset input pointer we must be able to save
+   and retore the state.  */
+#define SAVE_RESET_STATE(Save) \
+  if (Save)								      \
+    save_curcs = *curcsp;						      \
+  else									      \
+    *curcsp = save_curcs
+
 
 /* Current codeset type.  */
 enum
 {
-  init = 0,
-  sb,
-  db
+  sb = 0,
+  db = 64
 };
 
 /* First, define the conversion function from IBM-935 to UCS4.  */
 #define MIN_NEEDED_INPUT  	MIN_NEEDED_FROM
+#define MAX_NEEDED_INPUT  	MAX_NEEDED_FROM
 #define MIN_NEEDED_OUTPUT 	MIN_NEEDED_TO
-#define INIT_PARAMS 		int curcs = init;
 #define LOOPFCT 		FROM_LOOP
 #define BODY \
   {									      \
     uint32_t ch = *inptr;						      \
     uint32_t res;							      \
-    const struct gap *rp1 = __ibm935sb_to_ucs4_idx;			      \
-    const struct gap *rp2 = __ibm935db_to_ucs4_idx;			      \
 									      \
     if (__builtin_expect(ch, 0) == SO)					      \
       {									      \
-	if (__builtin_expect (inptr + 1 >= inend, 0))			      \
-	  {								      \
-	    result = __GCONV_INCOMPLETE_INPUT;				      \
-	    break;							      \
-	  }								      \
-									      \
 	/* Shift OUT, change to DBCS converter.  */			      \
 	if (curcs == db)						      \
 	  {								      \
@@ -76,16 +110,10 @@ enum
 	  }								      \
 	curcs = db;							      \
 	++inptr;							      \
-	ch = *inptr;							      \
+	continue;							      \
       }									      \
     else if (__builtin_expect (ch, 0) == SI)				      \
       {									      \
-	if (__builtin_expect (inptr + 1 >= inend, 0))			      \
-	  {								      \
-	    result = __GCONV_INCOMPLETE_INPUT;				      \
-	    break;							      \
-	  }								      \
-									      \
 	/* Shift IN, change to SBCS converter.  */			      \
 	if (curcs == sb)						      \
 	  {								      \
@@ -94,19 +122,14 @@ enum
 	  }								      \
 	curcs = sb;							      \
 	++inptr;							      \
-	ch = *inptr;							      \
+	continue;							      \
       }									      \
 									      \
-    if (curcs == sb || curcs == init)					      \
+    if (curcs == sb)							      \
       {									      \
 	/* Use the IBM935 table for single byte.  */			      \
-	while (ch > rp1->end)						      \
-	  ++rp1;							      \
-									      \
-	if (__builtin_expect (rp1 == NULL, 0)				      \
-	    || __builtin_expect (ch < rp1->start, 0)			      \
-	    || (res = __ibm935sb_to_ucs4[ch + rp1->idx],		      \
-		__builtin_expect (res, L'\1') == L'\0' && ch != '\0'))	      \
+	res = __ibm935sb_to_ucs4[ch];					      \
+	if (__builtin_expect (res, L'\1') == L'\0' && ch != '\0')	      \
 	  {								      \
 	    /* This is an illegal character.  */			      \
 	    if (! ignore_errors_p ())					      \
@@ -115,18 +138,20 @@ enum
 		break;							      \
 	      }								      \
 	    ++*irreversible;						      \
-	    ++inptr;							      \
-	    continue;							      \
 	  }								      \
 	else								      \
 	  {								      \
 	    put32 (outptr, res);					      \
 	    outptr += 4;						      \
-	    inptr++;							      \
 	  }								      \
+	++inptr;							      \
       }									      \
-    else if (curcs == db)						      \
+    else								      \
       {									      \
+	const struct gap *rp2 = __ibm935db_to_ucs4_idx;			      \
+									      \
+	assert (curcs == db);						      \
+									      \
 	/* Use the IBM935 table for double byte.  */			      \
 	if (__builtin_expect (inptr + 1 >= inend, 0))			      \
 	  {								      \
@@ -152,24 +177,25 @@ enum
 		break;							      \
 	      }								      \
 	    ++*irreversible;						      \
-	    inptr += 2;							      \
-	    continue;							      \
 	  }								      \
 	else								      \
 	  {								      \
 	    put32 (outptr, res);					      \
 	    outptr += 4;						      \
-	    inptr += 2;							      \
 	  }								      \
+	inptr += 2;							      \
       }									      \
   }
 #define LOOP_NEED_FLAGS
+#define EXTRA_LOOP_DECLS	, int *curcsp
+#define INIT_PARAMS		int curcs = *curcsp & ~7
+#define UPDATE_PARAMS		*curcsp = curcs
 #include <iconv/loop.c>
 
 /* Next, define the other direction.  */
 #define MIN_NEEDED_INPUT	MIN_NEEDED_TO
 #define MIN_NEEDED_OUTPUT	MIN_NEEDED_FROM
-#define INIT_PARAMS 		int curcs = init;
+#define MAX_NEEDED_OUTPUT	MAX_NEEDED_FROM
 #define LOOPFCT			TO_LOOP
 #define BODY \
   {									      \
@@ -180,16 +206,21 @@ enum
 									      \
     if (__builtin_expect (ch, 0) >= 0xffff)				      \
       {									      \
-	rp1 = NULL;							      \
-	rp2 = NULL;							      \
+	if (! ignore_errors_p ())					      \
+	  {								      \
+	    result = __GCONV_ILLEGAL_INPUT;				      \
+	    break;							      \
+	  }								      \
+	++*irreversible;						      \
+	inptr += 4;							      \
+	continue;							      \
       }									      \
-    else								      \
-      while (ch > rp1->end)						      \
-	++rp1;								      \
+									      \
+    while (ch > rp1->end)						      \
+      ++rp1;								      \
 									      \
     /* Use the UCS4 table for single byte.  */				      \
-    if (__builtin_expect (rp1 == NULL, 0)				      \
-	|| __builtin_expect (ch < rp1->start, 0)			      \
+    if (__builtin_expect (ch < rp1->start, 0)				      \
 	|| (cp = __ucs4_to_ibm935sb[ch + rp1->idx],			      \
 	    __builtin_expect (cp[0], L'\1') == L'\0' && ch != '\0'))	      \
       {									      \
@@ -197,8 +228,7 @@ enum
 	while (ch > rp2->end)						      \
 	  ++rp2;							      \
 									      \
-	if (__builtin_expect (rp2 == NULL, 0)				      \
-	    || __builtin_expect (ch < rp2->start, 0)			      \
+	if (__builtin_expect (ch < rp2->start, 0)			      \
 	    || (cp = __ucs4_to_ibm935db[ch + rp2->idx],			      \
 		__builtin_expect (cp[0], L'\1')==L'\0' && ch != '\0'))	      \
 	  {								      \
@@ -212,7 +242,7 @@ enum
 	  }								      \
 	else								      \
 	  {								      \
-	    if (curcs == init || curcs == sb)				      \
+	    if (curcs == sb)						      \
 	      {								      \
 		if (__builtin_expect (outptr+1 > outend, 0))		      \
 		  {							      \
@@ -257,6 +287,9 @@ enum
     inptr += 4;								      \
   }
 #define LOOP_NEED_FLAGS
+#define EXTRA_LOOP_DECLS	, int *curcsp
+#define INIT_PARAMS		int curcs = *curcsp & ~7
+#define UPDATE_PARAMS		*curcsp = curcs
 #include <iconv/loop.c>
 
 /* Now define the toplevel functions.  */
diff --git a/iconvdata/ibm935.h b/iconvdata/ibm935.h
index 1e5613b6ef..cfaf96fea5 100644
--- a/iconvdata/ibm935.h
+++ b/iconvdata/ibm935.h
@@ -1,5 +1,5 @@
 /* Tables for conversion from and to IBM935
-   Copyright (C) 2000 Free Software Foundation, Inc.
+   Copyright (C) 2000, 2001 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Masahide Washizawa <washi@yamato.ibm.co.jp>, 2000.
 
@@ -32,49 +32,40 @@ struct gap
 };
 
 
-static const struct gap __ibm935sb_to_ucs4_idx[] =
+static const uint16_t __ibm935sb_to_ucs4[256] =
 {
-  { start: 0x0000, end: 0x0040, idx:     0 },
-  { start: 0x004a, end: 0x0050, idx:    -9 },
-  { start: 0x005a, end: 0x0061, idx:   -18 },
-  { start: 0x006a, end: 0x006f, idx:   -26 },
-  { start: 0x0079, end: 0x007f, idx:   -35 },
-  { start: 0x0081, end: 0x0089, idx:   -36 },
-  { start: 0x0091, end: 0x0099, idx:   -43 },
-  { start: 0x00a0, end: 0x00a9, idx:   -49 },
-  { start: 0x00b0, end: 0x00b0, idx:   -55 },
-  { start: 0x00b2, end: 0x00b2, idx:   -56 },
-  { start: 0x00ba, end: 0x00bb, idx:   -63 },
-  { start: 0x00c0, end: 0x00c9, idx:   -67 },
-  { start: 0x00d0, end: 0x00d9, idx:   -73 },
-  { start: 0x00e0, end: 0x00e0, idx:   -79 },
-  { start: 0x00e2, end: 0x00e9, idx:   -80 },
-  { start: 0x00f0, end: 0x00f9, idx:   -86 },
-  { start: 0x00ff, end: 0x00ff, idx:   -91 },
-  { start: 0xffff, end: 0xffff, idx:     0 }
-};
-
-static const uint16_t __ibm935sb_to_ucs4[] =
-{
-  0x0000, 0x0001, 0x0002, 0x0003, 0x009C, 0x0009, 0x0086, 0x007F, 0x0097,
-  0x008D, 0x008E, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F, 0x0010, 0x0011,
-  0x0012, 0x0013, 0x009D, 0x0085, 0x0008, 0x0087, 0x0018, 0x0019, 0x0092,
-  0x008F, 0x001C, 0x001D, 0x001E, 0x001F, 0x0080, 0x0081, 0x0082, 0x0083,
-  0x0084, 0x000A, 0x0017, 0x001B, 0x0088, 0x0089, 0x008A, 0x008B, 0x008C,
-  0x0005, 0x0006, 0x0007, 0x0090, 0x0091, 0x0016, 0x0093, 0x0094, 0x0095,
-  0x0096, 0x0004, 0x0098, 0x0099, 0x009A, 0x009B, 0x0014, 0x0015, 0x009E,
-  0x001A, 0x0020, 0x00A3, 0x002E, 0x003C, 0x0028, 0x002B, 0x007C, 0x0026,
-  0x0021, 0x00A5, 0x002A, 0x0029, 0x003B, 0x00AC, 0x002D, 0x002F, 0x00A6,
-  0x002C, 0x0025, 0x005F, 0x003E, 0x003F, 0x0060, 0x003A, 0x0023, 0x0040,
-  0x0027, 0x003D, 0x0022, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066,
-  0x0067, 0x0068, 0x0069, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F,
-  0x0070, 0x0071, 0x0072, 0x007E, 0x203E, 0x0073, 0x0074, 0x0075, 0x0076,
-  0x0077, 0x0078, 0x0079, 0x007A, 0x005E, 0x005C, 0x005B, 0x005D, 0x007B,
-  0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049,
-  0x007D, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, 0x0050, 0x0051,
-  0x0052, 0x0024, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059,
-  0x005A, 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
-  0x0038, 0x0039, 0x009F
+  /* 0x00 */ 0x0000, 0x0001, 0x0002, 0x0003, 0x009C, 0x0009, 0x0086, 0x007F,
+  /* 0x08 */ 0x0097, 0x008D, 0x008E, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F,
+  /* 0x10 */ 0x0010, 0x0011, 0x0012, 0x0013, 0x009D, 0x0085, 0x0008, 0x0087,
+  /* 0x18 */ 0x0018, 0x0019, 0x0092, 0x008F, 0x001C, 0x001D, 0x001E, 0x001F,
+  /* 0x20 */ 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x000A, 0x0017, 0x001B,
+  /* 0x28 */ 0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x0005, 0x0006, 0x0007,
+  /* 0x30 */ 0x0090, 0x0091, 0x0016, 0x0093, 0x0094, 0x0095, 0x0096, 0x0004,
+  /* 0x38 */ 0x0098, 0x0099, 0x009A, 0x009B, 0x0014, 0x0015, 0x009E, 0x001A,
+  /* 0x40 */ 0x0020, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+  /* 0x48 */ 0x0000, 0x0000, 0x00A3, 0x002E, 0x003C, 0x0028, 0x002B, 0x007C,
+  /* 0x50 */ 0x0026, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+  /* 0x58 */ 0x0000, 0x0000, 0x0021, 0x00A5, 0x002A, 0x0029, 0x003B, 0x00AC,
+  /* 0x60 */ 0x002D, 0x002F, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+  /* 0x68 */ 0x0000, 0x0000, 0x00A6, 0x002C, 0x0025, 0x005F, 0x003E, 0x003F,
+  /* 0x70 */ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+  /* 0x78 */ 0x0000, 0x0060, 0x003A, 0x0023, 0x0040, 0x0027, 0x003D, 0x0022,
+  /* 0x80 */ 0x0000, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
+  /* 0x88 */ 0x0068, 0x0069, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+  /* 0x90 */ 0x0000, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F, 0x0070,
+  /* 0x98 */ 0x0071, 0x0072, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+  /* 0xa0 */ 0x007E, 0x203E, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078,
+  /* 0xa8 */ 0x0079, 0x007A, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+  /* 0xb0 */ 0x005E, 0x0000, 0x005C, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+  /* 0xb8 */ 0x0000, 0x0000, 0x005B, 0x005D, 0x0000, 0x0000, 0x0000, 0x0000,
+  /* 0xc0 */ 0x007B, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
+  /* 0xc8 */ 0x0048, 0x0049, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+  /* 0xd0 */ 0x007D, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, 0x0050,
+  /* 0xd8 */ 0x0051, 0x0052, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+  /* 0xe0 */ 0x0024, 0x0000, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058,
+  /* 0xe8 */ 0x0059, 0x005A, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+  /* 0xf0 */ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
+  /* 0xf8 */ 0x0038, 0x0039, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x009F
 };
 
 static const struct gap __ibm935db_to_ucs4_idx[] =
diff --git a/iconvdata/ibm937.c b/iconvdata/ibm937.c
index 98e9683253..6da55ae883 100644
--- a/iconvdata/ibm937.c
+++ b/iconvdata/ibm937.c
@@ -1,5 +1,5 @@
 /* Conversion to and from IBM937.
-   Copyright (C) 2000 Free Software Foundation, Inc.
+   Copyright (C) 2000, 2001 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Masahide Washizawa <washi@yamato.ibm.co.jp>, 2000.
 
@@ -32,26 +32,68 @@
 #define CHARSET_NAME	"IBM937//"
 #define FROM_LOOP	from_ibm937
 #define TO_LOOP		to_ibm937
+#define MIN_NEEDED_FROM	1
+#define MAX_NEEDED_FROM	2
+#define MIN_NEEDED_TO	4
+#define MAX_NEEDED_TO	4
+#define PREPARE_LOOP \
+  int save_curcs;							      \
+  int *curcsp = &data->__statep->__count;
+#define EXTRA_LOOP_ARGS		, curcsp
 
 /* Definitions of initialization and destructor function.  */
 #define DEFINE_INIT	1
 #define DEFINE_FINI	1
 
-#define MIN_NEEDED_FROM	1
-#define MIN_NEEDED_TO	4
+
+/* Since this is a stateful encoding we have to provide code which resets
+   the output state to the initial state.  This has to be done during the
+   flushing.  */
+#define EMIT_SHIFT_TO_INIT \
+  if ((data->__statep->__count & ~7) != sb)				      \
+    {									      \
+      if (FROM_DIRECTION)						      \
+	data->__statep->__count &= 7;					      \
+      else								      \
+	{								      \
+	  unsigned char *outbuf = data->__outbuf;			      \
+									      \
+	  /* We are not in the initial state.  To switch back we have	      \
+	     to emit `SI'.  */						      \
+	  if (__builtin_expect (outbuf >= data->__outbufend, 0))	      \
+	    /* We don't have enough room in the output buffer.  */	      \
+	    status = __GCONV_FULL_OUTPUT;				      \
+	  else								      \
+	    {								      \
+	      /* Write out the shift sequence.  */			      \
+	      *outbuf++ = SI;						      \
+	      data->__outbuf = outbuf;					      \
+	      data->__statep->__count &= 7;				      \
+	    }								      \
+	}								      \
+    }
+
+
+/* Since we might have to reset input pointer we must be able to save
+   and retore the state.  */
+#define SAVE_RESET_STATE(Save) \
+  if (Save)								      \
+    save_curcs = *curcsp;						      \
+  else									      \
+    *curcsp = save_curcs
+
 
 /* Current codeset type.  */
 enum
 {
-  init = 0,
-  sb,
-  db
+  sb = 0,
+  db = 64
 };
 
 /* First, define the conversion function from IBM-937 to UCS4.  */
 #define MIN_NEEDED_INPUT  	MIN_NEEDED_FROM
+#define MAX_NEEDED_INPUT  	MAX_NEEDED_FROM
 #define MIN_NEEDED_OUTPUT 	MIN_NEEDED_TO
-#define INIT_PARAMS 		int curcs = init;
 #define LOOPFCT 		FROM_LOOP
 #define BODY \
   {									      \
@@ -59,12 +101,6 @@ enum
 									      \
     if (__builtin_expect (ch, 0) == SO)					      \
       {									      \
-	if (__builtin_expect (inptr + 1 >= inend, 0))			      \
-	  {								      \
-	    result = __GCONV_INCOMPLETE_INPUT;				      \
-	    break;							      \
-	  }								      \
-									      \
 	/* Shift OUT, change to DBCS converter.  */			      \
 	if (curcs == db)						      \
 	  {								      \
@@ -73,16 +109,10 @@ enum
 	  }								      \
 	curcs = db;							      \
 	++inptr;							      \
-	ch = *inptr;							      \
+	continue;							      \
       }									      \
     else if (__builtin_expect (ch, 0) == SI)				      \
       {									      \
-	if (__builtin_expect (inptr + 1 >= inend, 0))			      \
-	  {								      \
-	    result = __GCONV_INCOMPLETE_INPUT;				      \
-	    break;							      \
-	  }								      \
-									      \
 	/* Shift IN, change to SBCS converter.  */			      \
 	if (curcs == sb)						      \
 	  {								      \
@@ -91,10 +121,10 @@ enum
 	  }								      \
 	curcs = sb;							      \
 	++inptr;							      \
-	ch = *inptr;							      \
+	continue;							      \
       }									      \
 									      \
-    if (curcs == sb || curcs == init)					      \
+    if (curcs == sb)							      \
       {									      \
 	/* Use the UCS4 table for single byte.  */			      \
 	ch = __ibm937sb_to_ucs4[ch];					      \
@@ -107,19 +137,20 @@ enum
 		break;							      \
 	      }								      \
 	    ++*irreversible;						      \
-	    ++inptr;							      \
-	    continue;							      \
 	  }								      \
 	else								      \
 	  {								      \
 	    put32 (outptr, ch);						      \
 	    outptr += 4;						      \
-	    inptr++;							      \
 	  }								      \
+	++inptr;							      \
       }									      \
-    else if (curcs == db)						      \
+    else								      \
       {									      \
 	/* Use the IBM937 table for double byte.  */			      \
+									      \
+	assert (curcs == db);						      \
+									      \
 	ch = ibm937db_to_ucs4(inptr[0], inptr[1]);			      \
 	if (__builtin_expect (ch, L'\1') == L'\0' && *inptr != '\0')	      \
 	  {								      \
@@ -130,24 +161,25 @@ enum
 		break;							      \
 	      }								      \
 	    ++*irreversible;						      \
-	    inptr += 2;							      \
-	    continue;							      \
 	  }								      \
 	else								      \
 	  {								      \
 	    put32 (outptr, ch);						      \
 	    outptr += 4;						      \
-	    inptr += 2;							      \
 	  }								      \
+	inptr += 2;							      \
       }									      \
   }
 #define LOOP_NEED_FLAGS
+#define EXTRA_LOOP_DECLS	, int *curcsp
+#define INIT_PARAMS		int curcs = *curcsp & ~7
+#define UPDATE_PARAMS		*curcsp = curcs
 #include <iconv/loop.c>
 
 /* Next, define the other direction.  */
 #define MIN_NEEDED_INPUT	MIN_NEEDED_TO
 #define MIN_NEEDED_OUTPUT	MIN_NEEDED_FROM
-#define INIT_PARAMS 		int curcs = init;
+#define MAX_NEEDED_OUTPUT	MAX_NEEDED_FROM
 #define LOOPFCT			TO_LOOP
 #define BODY \
   {									      \
@@ -174,7 +206,7 @@ enum
 	  }								      \
 	else								      \
 	  {								      \
-	    if (curcs == init || curcs == sb)				      \
+	    if (curcs == sb)						      \
 	      {								      \
 		*outptr++ = SO;						      \
 		if (__builtin_expect (outptr == outend, 0))		      \
@@ -207,6 +239,9 @@ enum
     inptr += 4;								      \
   }
 #define LOOP_NEED_FLAGS
+#define EXTRA_LOOP_DECLS	, int *curcsp
+#define INIT_PARAMS		int curcs = *curcsp & ~7
+#define UPDATE_PARAMS		*curcsp = curcs
 #include <iconv/loop.c>
 
 /* Now define the toplevel functions.  */
diff --git a/iconvdata/ibm939.c b/iconvdata/ibm939.c
index 7dd72840eb..d50d880ab0 100644
--- a/iconvdata/ibm939.c
+++ b/iconvdata/ibm939.c
@@ -1,5 +1,5 @@
 /* Conversion to and from IBM939.
-   Copyright (C) 2000 Free Software Foundation, Inc.
+   Copyright (C) 2000, 2001 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Masahide Washizawa <washi@yamato.ibm.co.jp>, 2000.
 
@@ -32,42 +32,76 @@
 #define CHARSET_NAME	"IBM939//"
 #define FROM_LOOP	from_ibm939
 #define TO_LOOP		to_ibm939
+#define MIN_NEEDED_FROM	1
+#define MAX_NEEDED_FROM	2
+#define MIN_NEEDED_TO	4
+#define MAX_NEEDED_TO	4
+#define PREPARE_LOOP \
+  int save_curcs;							      \
+  int *curcsp = &data->__statep->__count;
+#define EXTRA_LOOP_ARGS		, curcsp
 
 /* Definitions of initialization and destructor function.  */
 #define DEFINE_INIT	1
 #define DEFINE_FINI	1
 
-#define MIN_NEEDED_FROM	1
-#define MIN_NEEDED_TO	4
+
+/* Since this is a stateful encoding we have to provide code which resets
+   the output state to the initial state.  This has to be done during the
+   flushing.  */
+#define EMIT_SHIFT_TO_INIT \
+  if ((data->__statep->__count & ~7) != sb)				      \
+    {									      \
+      if (FROM_DIRECTION)						      \
+	data->__statep->__count &= 7;					      \
+      else								      \
+	{								      \
+	  unsigned char *outbuf = data->__outbuf;			      \
+									      \
+	  /* We are not in the initial state.  To switch back we have	      \
+	     to emit `SI'.  */						      \
+	  if (__builtin_expect (outbuf >= data->__outbufend, 0))	      \
+	    /* We don't have enough room in the output buffer.  */	      \
+	    status = __GCONV_FULL_OUTPUT;				      \
+	  else								      \
+	    {								      \
+	      /* Write out the shift sequence.  */			      \
+	      *outbuf++ = SI;						      \
+	      data->__outbuf = outbuf;					      \
+	      data->__statep->__count &= 7;				      \
+	    }								      \
+	}								      \
+    }
+
+
+/* Since we might have to reset input pointer we must be able to save
+   and retore the state.  */
+#define SAVE_RESET_STATE(Save) \
+  if (Save)								      \
+    save_curcs = *curcsp;						      \
+  else									      \
+    *curcsp = save_curcs
+
 
 /* Current codeset type.  */
 enum
 {
-  init = 0,
-  sb,
-  db
+  sb = 0,
+  db = 64
 };
 
 /* First, define the conversion function from IBM-939 to UCS4.  */
 #define MIN_NEEDED_INPUT  	MIN_NEEDED_FROM
+#define MAX_NEEDED_INPUT  	MAX_NEEDED_FROM
 #define MIN_NEEDED_OUTPUT 	MIN_NEEDED_TO
-#define INIT_PARAMS 		int curcs = init;
 #define LOOPFCT 		FROM_LOOP
 #define BODY \
   {									      \
     uint32_t ch = *inptr;						      \
     uint32_t res;							      \
-    const struct gap *rp1 = __ibm939sb_to_ucs4_idx;			      \
-    const struct gap *rp2 = __ibm939db_to_ucs4_idx;			      \
 									      \
     if (__builtin_expect (ch, 0) == SO)					      \
       {									      \
-	if (__builtin_expect (inptr + 1 >= inend, 0))			      \
-	  {								      \
-	    result = __GCONV_INCOMPLETE_INPUT;				      \
-	    break;							      \
-	  }								      \
-									      \
 	/* Shift OUT, change to DBCS converter.  */			      \
 	if (curcs == db)						      \
 	  {								      \
@@ -76,16 +110,10 @@ enum
 	  }								      \
 	curcs = db;							      \
 	++inptr;							      \
-	ch = *inptr;							      \
+	continue;							      \
       }									      \
     else if (__builtin_expect (ch, 0) == SI)				      \
       {									      \
-	if (__builtin_expect (inptr + 1 >= inend, 0))			      \
-	  {								      \
-	    result = __GCONV_INCOMPLETE_INPUT;				      \
-	    break;							      \
-	  }								      \
-									      \
 	/* Shift IN, change to SBCS converter.  */			      \
 	if (curcs == sb)						      \
 	  {								      \
@@ -94,19 +122,14 @@ enum
 	  }								      \
 	curcs = sb;							      \
 	++inptr;							      \
-	ch = *inptr;							      \
+	continue;							      \
       }									      \
 									      \
-    if (curcs == sb || curcs == init)					      \
+    if (curcs == sb)							      \
       {									      \
 	/* Use the IBM939 table for single byte.  */			      \
-	while (ch > rp1->end)						      \
-	  ++rp1;							      \
-									      \
-	if (__builtin_expect (rp1 == NULL, 0)				      \
-	    || __builtin_expect (ch < rp1->start, 0)			      \
-	    || (res = __ibm939sb_to_ucs4[ch + rp1->idx],		      \
-		__builtin_expect (res, L'\1') == L'\0' && ch != '\0'))	      \
+	res = __ibm939sb_to_ucs4[ch];					      \
+	if (__builtin_expect (res, L'\1') == L'\0' && ch != '\0')	      \
 	  {								      \
 	    /* This is an illegal character.  */			      \
 	    if (! ignore_errors_p ())					      \
@@ -115,21 +138,21 @@ enum
 		break;							      \
 	      }								      \
 	    ++*irreversible;						      \
-	    ++inptr;							      \
-	    continue;							      \
 	  }								      \
 	else								      \
 	  {								      \
-	    if (res == 0xa5)						      \
-	      res = 0x5c;						      \
 	    put32 (outptr, res);					      \
 	    outptr += 4;						      \
-	    ++inptr;							      \
 	  }								      \
+	++inptr;							      \
       }									      \
-    else if (curcs == db)						      \
+    else								      \
       {									      \
 	/* Use the IBM939 table for double byte.  */			      \
+	const struct gap *rp2 = __ibm939db_to_ucs4_idx;			      \
+									      \
+	assert (curcs == db);						      \
+									      \
 	if (__builtin_expect (inptr + 1 >= inend, 0))			      \
 	  {								      \
 	    /* The second character is not available.  Store the	      \
@@ -154,24 +177,25 @@ enum
 		break;							      \
 	      }								      \
 	    ++*irreversible;						      \
-	    inptr += 2;							      \
-	    continue;							      \
 	  }								      \
 	else								      \
 	  {								      \
 	    put32 (outptr, res);					      \
 	    outptr += 4;						      \
-	    inptr += 2;							      \
 	  }								      \
+	inptr += 2;							      \
       }									      \
   }
 #define LOOP_NEED_FLAGS
+#define EXTRA_LOOP_DECLS	, int *curcsp
+#define INIT_PARAMS		int curcs = *curcsp & ~7
+#define UPDATE_PARAMS		*curcsp = curcs
 #include <iconv/loop.c>
 
 /* Next, define the other direction */
 #define MIN_NEEDED_INPUT	MIN_NEEDED_TO
 #define MIN_NEEDED_OUTPUT	MIN_NEEDED_FROM
-#define INIT_PARAMS 		int curcs = init;
+#define MAX_NEEDED_OUTPUT	MAX_NEEDED_FROM
 #define LOOPFCT			TO_LOOP
 #define BODY \
   {									      \
@@ -214,7 +238,7 @@ enum
 	  }								      \
 	else								      \
 	  {								      \
-	    if (curcs == init || curcs == sb)				      \
+	    if (curcs == sb)						      \
 	      {								      \
 		if (__builtin_expect (outptr+1 > outend, 0))		      \
 		  {							      \
@@ -264,6 +288,9 @@ enum
     inptr += 4;								      \
   }
 #define LOOP_NEED_FLAGS
+#define EXTRA_LOOP_DECLS	, int *curcsp
+#define INIT_PARAMS		int curcs = *curcsp & ~7
+#define UPDATE_PARAMS		*curcsp = curcs
 #include <iconv/loop.c>
 
 /* Now define the toplevel functions. */
diff --git a/iconvdata/ibm939.h b/iconvdata/ibm939.h
index 57e0b6f500..d5b0639299 100644
--- a/iconvdata/ibm939.h
+++ b/iconvdata/ibm939.h
@@ -1,5 +1,5 @@
 /* Tables for conversion to and from IBM939.
-   Copyright (C) 2000 Free Software Foundation, Inc.
+   Copyright (C) 2000, 2001 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Masahide Washizawa <washi@yamato.ibm.co.jp>, 2000.
 
@@ -32,49 +32,40 @@ struct gap
 };
 
 
-static const struct gap __ibm939sb_to_ucs4_idx[] =
+static const uint16_t __ibm939sb_to_ucs4[256] =
 {
-  { start: 0x0000, end: 0x0040, idx:     0 },
-  { start: 0x0042, end: 0x0069, idx:    -1 },
-  { start: 0x006b, end: 0x007f, idx:    -2 },
-  { start: 0x0081, end: 0x008f, idx:    -3 },
-  { start: 0x0091, end: 0x00c9, idx:    -4 },
-  { start: 0x00d0, end: 0x00d9, idx:   -10 },
-  { start: 0x00e0, end: 0x00e0, idx:   -16 },
-  { start: 0x00e2, end: 0x00e9, idx:   -17 },
-  { start: 0x00f0, end: 0x00f9, idx:   -23 },
-  { start: 0x00ff, end: 0x00ff, idx:   -28 },
-  { start: 0xffff, end: 0xffff, idx:     0 }
-};
-
-static const uint16_t __ibm939sb_to_ucs4[] =
-{
-  0x0000, 0x0001, 0x0002, 0x0003, 0x009C, 0x0009, 0x0086, 0x007F, 0x0097,
-  0x008D, 0x008E, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F, 0x0010, 0x0011,
-  0x0012, 0x0013, 0x009D, 0x0085, 0x0008, 0x0087, 0x0018, 0x0019, 0x0092,
-  0x008F, 0x001C, 0x001D, 0x001E, 0x001F, 0x0080, 0x0081, 0x0082, 0x0083,
-  0x0084, 0x000A, 0x0017, 0x001B, 0x0088, 0x0089, 0x008A, 0x008B, 0x008C,
-  0x0005, 0x0006, 0x0007, 0x0090, 0x0091, 0x0016, 0x0093, 0x0094, 0x0095,
-  0x0096, 0x0004, 0x0098, 0x0099, 0x009A, 0x009B, 0x0014, 0x0015, 0x009E,
-  0x001A, 0x0020, 0xFF61, 0xFF62, 0xFF63, 0xFF64, 0xFF65, 0xFF66, 0xFF67,
-  0xFF68, 0x00A2, 0x002E, 0x003C, 0x0028, 0x002B, 0x007C, 0x0026, 0xFF69,
-  0xFF6A, 0xFF6B, 0xFF6C, 0xFF6D, 0xFF6E, 0xFF6F, 0xFF70, 0xFF71, 0x0021,
-  0x0024, 0x002A, 0x0029, 0x003B, 0x00AC, 0x002D, 0x002F, 0xFF72, 0xFF73,
-  0xFF74, 0xFF75, 0xFF76, 0xFF77, 0xFF78, 0xFF79, 0x002C, 0x0025, 0x005F,
-  0x003E, 0x003F, 0xFF7A, 0xFF7B, 0xFF7C, 0xFF7D, 0xFF7E, 0xFF7F, 0xFF80,
-  0xFF81, 0xFF82, 0x0060, 0x003A, 0x0023, 0x0040, 0x0027, 0x003D, 0x0022,
-  0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069,
-  0xFF83, 0xFF84, 0xFF85, 0xFF86, 0xFF87, 0xFF88, 0x006A, 0x006B, 0x006C,
-  0x006D, 0x006E, 0x006F, 0x0070, 0x0071, 0x0072, 0xFF89, 0xFF8A, 0xFF8B,
-  0xFF8C, 0xFF8D, 0xFF8E, 0x203E, 0x007E, 0x0073, 0x0074, 0x0075, 0x0076,
-  0x0077, 0x0078, 0x0079, 0x007A, 0xFF8F, 0xFF90, 0xFF91, 0x005B, 0xFF92,
-  0xFF93, 0x005E, 0x00A3, 0x00A5, 0xFF94, 0xFF95, 0xFF96, 0xFF97, 0xFF98,
-  0xFF99, 0xFF9A, 0xFF9B, 0xFF9C, 0xFF9D, 0x005D, 0xFF9E, 0xFF9F, 0x007B,
-  0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049,
-  0x007D, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, 0x0050, 0x0051,
-  0x0052, 0x005C, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059,
-  0x005A, 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
-  0x0038, 0x0039, 0x009F
+  /* 0x00 */ 0x0000, 0x0001, 0x0002, 0x0003, 0x009C, 0x0009, 0x0086, 0x007F,
+  /* 0x08 */ 0x0097, 0x008D, 0x008E, 0x000B, 0x000C, 0x000D, 0x000E, 0x000F,
+  /* 0x10 */ 0x0010, 0x0011, 0x0012, 0x0013, 0x009D, 0x0085, 0x0008, 0x0087,
+  /* 0x18 */ 0x0018, 0x0019, 0x0092, 0x008F, 0x001C, 0x001D, 0x001E, 0x001F,
+  /* 0x20 */ 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x000A, 0x0017, 0x001B,
+  /* 0x28 */ 0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x0005, 0x0006, 0x0007,
+  /* 0x30 */ 0x0090, 0x0091, 0x0016, 0x0093, 0x0094, 0x0095, 0x0096, 0x0004,
+  /* 0x38 */ 0x0098, 0x0099, 0x009A, 0x009B, 0x0014, 0x0015, 0x009E, 0x001A,
+  /* 0x40 */ 0x0020, 0x0000, 0xFF61, 0xFF62, 0xFF63, 0xFF64, 0xFF65, 0xFF66,
+  /* 0x48 */ 0xFF67, 0xFF68, 0x00A2, 0x002E, 0x003C, 0x0028, 0x002B, 0x007C,
+  /* 0x50 */ 0x0026, 0xFF69, 0xFF6A, 0xFF6B, 0xFF6C, 0xFF6D, 0xFF6E, 0xFF6F,
+  /* 0x58 */ 0xFF70, 0xFF71, 0x0021, 0x0024, 0x002A, 0x0029, 0x003B, 0x00AC,
+  /* 0x60 */ 0x002D, 0x002F, 0xFF72, 0xFF73, 0xFF74, 0xFF75, 0xFF76, 0xFF77,
+  /* 0x68 */ 0xFF78, 0xFF79, 0x0000, 0x002C, 0x0025, 0x005F, 0x003E, 0x003F,
+  /* 0x70 */ 0xFF7A, 0xFF7B, 0xFF7C, 0xFF7D, 0xFF7E, 0xFF7F, 0xFF80, 0xFF81,
+  /* 0x78 */ 0xFF82, 0x0060, 0x003A, 0x0023, 0x0040, 0x0027, 0x003D, 0x0022,
+  /* 0x80 */ 0x0000, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
+  /* 0x88 */ 0x0068, 0x0069, 0xFF83, 0xFF84, 0xFF85, 0xFF86, 0xFF87, 0xFF88,
+  /* 0x90 */ 0x0000, 0x006A, 0x006B, 0x006C, 0x006D, 0x006E, 0x006F, 0x0070,
+  /* 0x98 */ 0x0071, 0x0072, 0xFF89, 0xFF8A, 0xFF8B, 0xFF8C, 0xFF8D, 0xFF8E,
+  /* 0xa0 */ 0x203E, 0x007E, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078,
+  /* 0xa8 */ 0x0079, 0x007A, 0xFF8F, 0xFF90, 0xFF91, 0x005B, 0xFF92, 0xFF93,
+  /* 0xb0 */ 0x005E, 0x00A3, 0x005C, 0xFF94, 0xFF95, 0xFF96, 0xFF97, 0xFF98,
+  /* 0xb8 */ 0xFF99, 0xFF9A, 0xFF9B, 0xFF9C, 0xFF9D, 0x005D, 0xFF9E, 0xFF9F,
+  /* 0xc0 */ 0x007B, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
+  /* 0xc8 */ 0x0048, 0x0049, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+  /* 0xd0 */ 0x007D, 0x004A, 0x004B, 0x004C, 0x004D, 0x004E, 0x004F, 0x0050,
+  /* 0xd8 */ 0x0051, 0x0052, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+  /* 0xe0 */ 0x005C, 0x0000, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058,
+  /* 0xe8 */ 0x0059, 0x005A, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+  /* 0xf0 */ 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
+  /* 0xf8 */ 0x0038, 0x0039, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x009F
 };
 
 static const struct gap __ibm939db_to_ucs4_idx[] =
diff --git a/iconvdata/testdata/IBM930 b/iconvdata/testdata/IBM930
index 551cb60797..ab2632ef54 100644
--- a/iconvdata/testdata/IBM930
+++ b/iconvdata/testdata/IBM930
Binary files differdiff --git a/iconvdata/testdata/IBM933 b/iconvdata/testdata/IBM933
index 4da0d685bf..449ed02c3e 100644
--- a/iconvdata/testdata/IBM933
+++ b/iconvdata/testdata/IBM933
Binary files differdiff --git a/iconvdata/testdata/IBM935 b/iconvdata/testdata/IBM935
index 4a905ee27e..a35941b841 100644
--- a/iconvdata/testdata/IBM935
+++ b/iconvdata/testdata/IBM935
Binary files differdiff --git a/iconvdata/testdata/IBM937 b/iconvdata/testdata/IBM937
index 58bd2632c4..b448487982 100644
--- a/iconvdata/testdata/IBM937
+++ b/iconvdata/testdata/IBM937
Binary files differdiff --git a/iconvdata/testdata/IBM939 b/iconvdata/testdata/IBM939
index 9c10f9e416..6970f02977 100644
--- a/iconvdata/testdata/IBM939
+++ b/iconvdata/testdata/IBM939
Binary files differ