This is the mail archive of the
java-patches@gcc.gnu.org
mailing list for the Java project.
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.