This is the mail archive of the java-patches@gcc.gnu.org mailing list for the Java project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Partial fix for libgcj/9802


Hi,

On Sun, 2003-03-02 at 00:15, Tom Tromey wrote:
> >>>>> "Mark" == Mark Wielaard <mark at klomp dot org> writes:
> 
> Mark> +	* gnu/gcj/convert/UnicodeToBytes.java (havePendingByes): New method.
> 
> Should be "Bytes", not "Byes".  There are several of these in the
> ChangeLog entry.

Fixed ChangeLog entry:

2002-03-14  James Clark  <jjc at jclark dot com>

       Fix for PR libgcj/8738:
       * gnu/gcj/convert/UnicodeToBytes.java (havePendingBytes): New method.
       * gnu/gcj/convert/Output_SJIS.java (havePendingBytes): Likewise.
       * gnu/gcj/convert/Output_EUCJIS.java (havePendingBytes): Likewise.
       * gnu/gcj/convert/Output_UTF8.java (havePendingBytes): Likewise.
       (write): Always decrease avail when count is increased.
       * java/lang/natString.cc (getBytes): Check converter havePendingBytes()
       and whether output buffer is full before increasing size.

> I'm inclined to put this in, but first a couple questions.
> 
> What should we do about the iconv converter?
> Perhaps for 3.3 we can hack around the problem, and just ditch old
> glibc compatibility for 3.4.  Or maybe now is the time 

Since the iconv converter does not keep internal state it does not need
a havePendingBytes() method. But I think your patch is necessary since
we need to break out of the iconv loop when we hit errno == E2BIG, but
keep on converting/throwing away bytes when we see invalid sequences.
(But again, I didn't actually test it. The only test case that I
actually made is the surrogate Mauve test that James Clark pointed out.
We need some users which use different encodings to help us get all this
right/debugged.)

> Do we also need to update PrintStream and friends?

Yes. PrintStream and OutputStreamWriter should get the following
updates. PrintStream always clears a working buffer of 100 bytes so
doesn't need to flush or enlarge it, but OutputStreamWriter might be
using a very small BufferedOutputStream or when count is small might not
trigger an automatic flush() so it does need extra flushing. Although in
practice this will probably never actually happen.

2002-03-14  Mark Wielaard  <mark at klomp dot org>

       * java/io/PrintStream.java (writeChars(char[],int, int)):
       Check converter.havePendingBytes().
       (writeChars(String,int,int)): Likewise.
       * java/io/OutputStreamWriter.java (writeChars(char[], int, int)):
       Check converter.havePendingBytes() and flush buffer when stalled.

No new tests created, but also no regression with the libgcj and Mauve
test suites. Should I check this in into branch and mainline?

Cheers,

Mark
Index: java/lang/natString.cc
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/lang/natString.cc,v
retrieving revision 1.27
diff -u -r1.27 natString.cc
--- java/lang/natString.cc	13 Jun 2002 18:16:26 -0000	1.27
+++ java/lang/natString.cc	14 Mar 2003 16:17:36 -0000
@@ -1,6 +1,6 @@
 // natString.cc - Implementation of java.lang.String native methods.
 
-/* Copyright (C) 1998, 1999, 2000, 2001, 2002  Free Software Foundation
+/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003  Free Software Foundation
 
    This file is part of libgcj.
 
@@ -586,12 +586,11 @@
   jint offset = 0;
   gnu::gcj::convert::UnicodeToBytes *converter
     = gnu::gcj::convert::UnicodeToBytes::getEncoder(enc);
-  while (todo > 0)
+  while (todo > 0 || converter->havePendingBytes())
     {
       converter->setOutput(buffer, bufpos);
       int converted = converter->write(this, offset, todo, NULL);
-      bufpos = converter->count;
-      if (converted == 0)
+      if (converted == 0 && bufpos == converter->count)
 	{
 	  buflen *= 2;
 	  jbyteArray newbuffer = JvNewByteArray(buflen);
@@ -599,10 +598,10 @@
 	  buffer = newbuffer;
 	}
       else
-	{
-	  offset += converted;
-	  todo -= converted;
-	}
+	bufpos = converter->count;
+
+      offset += converted;
+      todo -= converted;
     }
   converter->done ();
   if (bufpos == buflen)
Index: java/io/PrintStream.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/io/PrintStream.java,v
retrieving revision 1.10
diff -u -r1.10 PrintStream.java
--- java/io/PrintStream.java	2 Apr 2001 21:16:38 -0000	1.10
+++ java/io/PrintStream.java	14 Mar 2003 16:17:36 -0000
@@ -1,6 +1,6 @@
 // PrintStream.java - Print string representations
 
-/* Copyright (C) 1998, 1999, 2001  Free Software Foundation
+/* Copyright (C) 1998, 1999, 2001, 2003  Free Software Foundation
 
    This file is part of libgcj.
 
@@ -110,7 +110,7 @@
   private void writeChars(char[] buf, int offset, int count)
     throws IOException
   {
-    while (count > 0)
+    while (count > 0 || converter.havePendingBytes())
       {
 	converter.setOutput(work_bytes, 0);
 	int converted = converter.write(buf, offset, count);
@@ -123,7 +123,7 @@
   private void writeChars(String str, int offset, int count)
     throws IOException
   {
-    while (count > 0)
+    while (count > 0 || converter.havePendingBytes())
       {
 	converter.setOutput(work_bytes, 0);
 	int converted = converter.write(str, offset, count, work);
Index: java/io/OutputStreamWriter.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/java/io/OutputStreamWriter.java,v
retrieving revision 1.11
diff -u -r1.11 OutputStreamWriter.java
--- java/io/OutputStreamWriter.java	13 Feb 2003 23:28:57 -0000	1.11
+++ java/io/OutputStreamWriter.java	14 Mar 2003 16:17:36 -0000
@@ -106,7 +106,7 @@
   private void writeChars(char[] buf, int offset, int count)
     throws IOException
   {
-    while (count > 0)
+    while (count > 0 || converter.havePendingBytes())
       {
 	// We must flush if out.count == out.buf.length.
 	// It is probably a good idea to flush if out.buf is almost full.
@@ -119,6 +119,13 @@
 	  }
 	converter.setOutput(out.buf, out.count);
 	int converted = converter.write(buf, offset, count);
+	// Flush if we cannot make progress.
+	if (converted == 0 && out.count == converter.count)
+	  {
+	    out.flush();
+	    if (out.count != 0)
+	      throw new IOException("unable to flush output byte buffer");
+	  }
 	offset += converted;
 	count -= converted;
 	out.count = converter.count;
Index: gnu/gcj/convert/Output_EUCJIS.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/gnu/gcj/convert/Output_EUCJIS.java,v
retrieving revision 1.3
diff -u -r1.3 Output_EUCJIS.java
--- gnu/gcj/convert/Output_EUCJIS.java	7 Mar 2000 19:55:24 -0000	1.3
+++ gnu/gcj/convert/Output_EUCJIS.java	14 Mar 2003 16:17:36 -0000
@@ -1,4 +1,4 @@
-/* Copyright (C) 1999  Free Software Foundation
+/* Copyright (C) 1999, 2003  Free Software Foundation
 
    This file is part of libgcj.
 
@@ -21,6 +21,11 @@
   public native int write (char[] inbuffer, int inpos, int inlength);
 
   public native int write (String str, int inpos, int inlength, char[] work);
+
+  public boolean havePendingBytes()
+  {
+    return pending1 >= 0;
+  }
 
   int pending1 = -1;
   int pending2;
Index: gnu/gcj/convert/Output_SJIS.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/gnu/gcj/convert/Output_SJIS.java,v
retrieving revision 1.3
diff -u -r1.3 Output_SJIS.java
--- gnu/gcj/convert/Output_SJIS.java	7 Mar 2000 19:55:24 -0000	1.3
+++ gnu/gcj/convert/Output_SJIS.java	14 Mar 2003 16:17:36 -0000
@@ -1,4 +1,4 @@
-/* Copyright (C) 1999  Free Software Foundation
+/* Copyright (C) 1999, 2003  Free Software Foundation
 
    This file is part of libgcj.
 
@@ -21,6 +21,11 @@
   public native int write (char[] inbuffer, int inpos, int inlength);
 
   public native int write (String str, int inpos, int inlength, char[] work);
+
+  public boolean havePendingBytes()
+  {
+    return pending >= 0;
+  }
 
   int pending = -1;
 }
Index: gnu/gcj/convert/Output_UTF8.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/gnu/gcj/convert/Output_UTF8.java,v
retrieving revision 1.6
diff -u -r1.6 Output_UTF8.java
--- gnu/gcj/convert/Output_UTF8.java	8 Aug 2000 17:35:32 -0000	1.6
+++ gnu/gcj/convert/Output_UTF8.java	14 Mar 2003 16:17:36 -0000
@@ -1,4 +1,4 @@
-/* Copyright (C) 1999, 2000  Free Software Foundation
+/* Copyright (C) 1999, 2000, 2003  Free Software Foundation
 
    This file is part of libgcj.
 
@@ -104,6 +104,7 @@
 	      {
 		value = (hi_part - 0xD800) * 0x400 + (ch - 0xDC00) + 0x10000;
 		buf[count++] = (byte) (0xF0 | (value >> 18));
+		avail--;
 		bytes_todo = 3;
 		hi_part = 0;
 	      }
@@ -118,4 +119,10 @@
       }
     return inpos - start_pos;
   }
+
+  public boolean havePendingBytes()
+  {
+    return bytes_todo > 0;
+  }
+
 }
Index: gnu/gcj/convert/UnicodeToBytes.java
===================================================================
RCS file: /cvs/gcc/gcc/libjava/gnu/gcj/convert/UnicodeToBytes.java,v
retrieving revision 1.9
diff -u -r1.9 UnicodeToBytes.java
--- gnu/gcj/convert/UnicodeToBytes.java	18 Aug 2001 03:56:01 -0000	1.9
+++ gnu/gcj/convert/UnicodeToBytes.java	14 Mar 2003 16:17:36 -0000
@@ -1,4 +1,4 @@
-/* Copyright (C) 1999, 2000, 2001  Free Software Foundation
+/* Copyright (C) 1999, 2000, 2001, 2003  Free Software Foundation
 
    This file is part of libgcj.
 
@@ -144,6 +144,17 @@
     int srcEnd = inpos + (inlength > work.length ? work.length : inlength);
     str.getChars(inpos, srcEnd, work, 0);
     return write(work, 0, srcEnd - inpos);
+  }
+
+  /**
+   * Returns true when the converter has consumed some bytes that are
+   * not yet converted to characters because further continuation
+   * bytes are needed.  Defaults to false, should be overridden by
+   * decoders that internally store some bytes.
+   */
+  public boolean havePendingBytes()
+  {
+    return false;
   }
 
   /** Indicate that the converter is resuable.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]