libcpp/charset: close out shift states

DJ Delorie dj@redhat.com
Mon Dec 10 21:18:00 GMT 2007


How about this?  I pulled some common code out into a macro, because I
didn't know how portable it would be to call iconv with inbytesleft==0

The other option is to put an "if (inbytesleft)" before the other call
to iconv, so that we call one iconv or the other, but use the common
loop/grow code.  I don't know if it's possible to loop infinitely on a
close-shift call, either.

Index: charset.c
===================================================================
--- charset.c	(revision 129957)
+++ charset.c	(working copy)
@@ -548,6 +548,13 @@
 /* And this one uses the system iconv primitive.  It's a little
    different, since iconv's interface is a little different.  */
 #if HAVE_ICONV
+
+#define CONVERT_ICONV_GROW_BUFFER \
+      outbytesleft += OUTBUF_BLOCK_SIZE; \
+      to->asize += OUTBUF_BLOCK_SIZE; \
+      to->text = XRESIZEVEC (uchar, to->text, to->asize); \
+      outbuf = (char *)to->text + to->asize - outbytesleft;
+
 static bool
 convert_using_iconv (iconv_t cd, const uchar *from, size_t flen,
 		     struct _cpp_strbuf *to)
@@ -570,16 +577,24 @@
       iconv (cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft);
       if (__builtin_expect (inbytesleft == 0, 1))
 	{
+	  /* Close out any shift states, returning to the initial state.  */
+	  if (iconv (cd, 0, 0, &outbuf, &outbytesleft) == (size_t)-1)
+	    {
+	      if (errno != E2BIG)
+		return false;
+
+	      CONVERT_ICONV_GROW_BUFFER;
+	      if (iconv (cd, 0, 0, &outbuf, &outbytesleft) == (size_t)-1)
+		return false;
+	    }
+
 	  to->len = to->asize - outbytesleft;
 	  return true;
 	}
       if (errno != E2BIG)
 	return false;
 
-      outbytesleft += OUTBUF_BLOCK_SIZE;
-      to->asize += OUTBUF_BLOCK_SIZE;
-      to->text = XRESIZEVEC (uchar, to->text, to->asize);
-      outbuf = (char *)to->text + to->asize - outbytesleft;
+      CONVERT_ICONV_GROW_BUFFER;
     }
 }
 #else



More information about the Gcc-patches mailing list