Attachment "yamako-endenc.patch" to
ticket [526524ffff]
added by
hobbs
2002-04-18 08:52:18.
Index: generic/tclEncoding.c
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclEncoding.c,v
retrieving revision 1.12
diff -b -u -r1.12 tclEncoding.c
--- generic/tclEncoding.c 11 Mar 2002 20:43:07 -0000 1.12
+++ generic/tclEncoding.c 18 Apr 2002 01:48:58 -0000
@@ -2562,14 +2562,28 @@
tablePrefixBytes = tableDataPtr->prefixBytes;
tableFromUnicode = tableDataPtr->fromUnicode;
+ /*
+ * The state variable has the value of oldState when word is 0.
+ * In this case, the escape sequense should not be copied to dst
+ * because the current character set is not changed.
+ */
+ if (state != oldState) {
subTablePtr = &dataPtr->subTables[state];
- if (dst + subTablePtr->sequenceLen > dstEnd) {
+ if ((dst + subTablePtr->sequenceLen) > dstEnd) {
+ /*
+ * If there is no space to write the escape sequence, the
+ * state variable must be changed to the value of oldState
+ * variable because this escape sequence must be written
+ * in the next conversion.
+ */
+ state = oldState;
result = TCL_CONVERT_NOSPACE;
break;
}
memcpy((VOID *) dst, (VOID *) subTablePtr->sequence,
(size_t) subTablePtr->sequenceLen);
dst += subTablePtr->sequenceLen;
+ }
}
if (tablePrefixBytes[(word >> 8)] != 0) {
Index: generic/tclIO.c
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclIO.c,v
retrieving revision 1.54
diff -b -u -r1.54 tclIO.c
--- generic/tclIO.c 11 Mar 2002 20:43:10 -0000 1.54
+++ generic/tclIO.c 18 Apr 2002 01:48:58 -0000
@@ -2522,6 +2522,16 @@
panic("called Tcl_Close on channel with refCount > 0");
}
+ /*
+ * When the channel has an escape sequence driven encoding such as
+ * iso2022, the terminated escape sequence must write to the buffer.
+ */
+ if ((statePtr->encoding != NULL) && (statePtr->curOutPtr != NULL)
+ && (CheckChannelErrors(statePtr, TCL_WRITABLE) == 0)) {
+ statePtr->outputEncodingFlags |= TCL_ENCODING_END;
+ WriteChars(chanPtr, "", 0);
+ }
+
Tcl_ClearChannelHandlers(chan);
/*
@@ -3041,8 +3051,8 @@
ChannelState *statePtr = chanPtr->state; /* state info for channel */
ChannelBuffer *bufPtr;
char *dst, *stage;
- int saved, savedLF, sawLF, total, flags, dstLen, stageMax, dstWrote;
- int stageLen, toWrite, stageRead;
+ int saved, savedLF, sawLF, total, dstLen, stageMax, dstWrote;
+ int stageLen, toWrite, stageRead, endEncoding, result;
Tcl_Encoding encoding;
char safe[BUFFER_PADDING];
@@ -3053,11 +3063,17 @@
encoding = statePtr->encoding;
/*
+ * Write the terminated escape sequence even if srcLen is 0.
+ */
+
+ endEncoding = ((statePtr->outputEncodingFlags & TCL_ENCODING_END) != 0);
+
+ /*
* Loop over all UTF-8 characters in src, storing them in staging buffer
* with proper EOL translation.
*/
- while (srcLen + savedLF > 0) {
+ while (srcLen + savedLF + endEncoding > 0) {
stage = statePtr->outputStage;
stageMax = statePtr->bufSize;
stageLen = stageMax;
@@ -3092,17 +3108,12 @@
src += toWrite;
srcLen -= toWrite;
- flags = statePtr->outputEncodingFlags;
- if (srcLen == 0) {
- flags |= TCL_ENCODING_END;
- }
-
/*
* Loop over all UTF-8 characters in staging buffer, converting them
* to external encoding, storing them in output buffer.
*/
- while (stageLen + saved > 0) {
+ while (stageLen + saved + endEncoding > 0) {
bufPtr = statePtr->curOutPtr;
if (bufPtr == NULL) {
bufPtr = AllocChannelBuffer(statePtr->bufSize);
@@ -3125,28 +3136,31 @@
saved = 0;
}
- Tcl_UtfToExternal(NULL, encoding, stage, stageLen, flags,
+ result = Tcl_UtfToExternal(NULL, encoding, stage, stageLen,
+ statePtr->outputEncodingFlags,
&statePtr->outputEncodingState, dst,
dstLen + BUFFER_PADDING, &stageRead, &dstWrote, NULL);
- /* Fix for SF #506297, reported by Martin Forssen <[email protected]>.
+ /* Fix for SF #506297, reported by Martin Forssen
+ * <[email protected]>.
*
- * The encoding chosen in the script exposing the bug
- * writes out three intro characters when
- * TCL_ENCODING_START is set, but does not consume any
- * input as TCL_ENCODING_END is cleared. As some output
- * was generated the enclosing loop calls UtfToExternal
- * again, again with START set. Three more characters in
- * the out and still no use of input ... To break this
- * infinite loop we remove TCL_ENCODING_START from the set
- * of flags after the first call (no condition is
- * required, the later calls remove an unset flag, which
- * is a no-op). This causes the subsequent calls to
+ * The encoding chosen in the script exposing the bug writes out
+ * three intro characters when TCL_ENCODING_START is set, but does
+ * not consume any input as TCL_ENCODING_END is cleared. As some
+ * output was generated the enclosing loop calls UtfToExternal
+ * again, again with START set. Three more characters in the out
+ * and still no use of input ... To break this infinite loop we
+ * remove TCL_ENCODING_START from the set of flags after the first
+ * call (no condition is required, the later calls remove an unset
+ * flag, which is a no-op). This causes the subsequent calls to
* UtfToExternal to consume and convert the actual input.
*/
- flags &= ~TCL_ENCODING_START;
- if (stageRead + dstWrote == 0) {
+ statePtr->outputEncodingFlags &= ~TCL_ENCODING_START;
+ /*
+ * The following code must be executed only when result is not 0.
+ */
+ if (result && ((stageRead + dstWrote) == 0)) {
/*
* We have an incomplete UTF-8 character at the end of the
* staging buffer. It will get moved to the beginning of the
@@ -3182,6 +3196,16 @@
stage += stageRead;
stageLen -= stageRead;
sawLF = 0;
+
+ /*
+ * If all translated characters are written to the buffer,
+ * endEncoding is set to 0 because the escape sequence may be
+ * output.
+ */
+
+ if ((stageLen + saved == 0) && (result == 0)) {
+ endEncoding = 0;
+ }
}
}
return total;
@@ -6334,6 +6358,15 @@
if (encoding == NULL) {
return TCL_ERROR;
}
+ }
+ /*
+ * When the channel has an escape sequence driven encoding such as
+ * iso2022, the terminated escape sequence must write to the buffer.
+ */
+ if ((statePtr->encoding != NULL) && (statePtr->curOutPtr != NULL)
+ && (CheckChannelErrors(statePtr, TCL_WRITABLE) == 0)) {
+ statePtr->outputEncodingFlags |= TCL_ENCODING_END;
+ WriteChars(chanPtr, "", 0);
}
Tcl_FreeEncoding(statePtr->encoding);
statePtr->encoding = encoding;