summaryrefslogtreecommitdiffstats
path: root/generic/tclIO.c
diff options
context:
space:
mode:
authorandreas_kupries <akupries@shaw.ca>2009-12-09 23:03:04 (GMT)
committerandreas_kupries <akupries@shaw.ca>2009-12-09 23:03:04 (GMT)
commitb17b07981f00b8dfdb3894baeb9a5f6e67cf2010 (patch)
tree977b95fa2857e73daf39ea2b0cda6dec6662a4dc /generic/tclIO.c
parent04598fc6cbdc102630fee4976e6afc6c2edd08bc (diff)
downloadtcl-b17b07981f00b8dfdb3894baeb9a5f6e67cf2010.zip
tcl-b17b07981f00b8dfdb3894baeb9a5f6e67cf2010.tar.gz
tcl-b17b07981f00b8dfdb3894baeb9a5f6e67cf2010.tar.bz2
* generic/tclIO.c: [Bug 2901998]: Applied Alexandre Ferrieux's
patch fixing the inconsistent buffered I/O. Tcl's I/O now flushes buffered output before reading, discards buffered input before writing, etc.
Diffstat (limited to 'generic/tclIO.c')
-rw-r--r--generic/tclIO.c53
1 files changed, 48 insertions, 5 deletions
diff --git a/generic/tclIO.c b/generic/tclIO.c
index 7044381..4e3bd4b 100644
--- a/generic/tclIO.c
+++ b/generic/tclIO.c
@@ -10,7 +10,7 @@
* See the file "license.terms" for information on usage and redistribution of
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tclIO.c,v 1.168 2009/11/18 22:41:41 nijtmans Exp $
+ * RCS: @(#) $Id: tclIO.c,v 1.169 2009/12/09 23:03:04 andreas_kupries Exp $
*/
#include "tclInt.h"
@@ -120,6 +120,7 @@ static int WriteChars(Channel *chanPtr, const char *src,
static Tcl_Obj * FixLevelCode(Tcl_Obj *msg);
static void SpliceChannel(Tcl_Channel chan);
static void CutChannel(Tcl_Channel chan);
+static int WillRead(Channel *chanPtr);
/*
* Simplifying helper macros. All may use their argument(s) multiple times.
@@ -276,6 +277,10 @@ ChanRead(
int dstSize,
int *errnoPtr)
{
+ if (WillRead(chanPtr) < 0) {
+ return -1;
+ }
+
return chanPtr->typePtr->inputProc(chanPtr->instanceData, dst, dstSize,
errnoPtr);
}
@@ -3831,6 +3836,33 @@ Tcl_WriteObj(
}
}
+static void WillWrite(Channel *chanPtr)
+{
+ int inputBuffered;
+
+ if ((chanPtr->typePtr->seekProc != NULL)
+ && ((inputBuffered = Tcl_InputBuffered((Tcl_Channel) chanPtr)) > 0)) {
+ int ignore;
+ DiscardInputQueued(chanPtr->state, 0);
+ ChanSeek(chanPtr, - inputBuffered, SEEK_CUR, &ignore);
+ }
+}
+
+static int WillRead(Channel *chanPtr)
+{
+ if ((chanPtr->typePtr->seekProc != NULL)
+ && (Tcl_OutputBuffered((Tcl_Channel) chanPtr) > 0)) {
+ if ((chanPtr->state->curOutPtr != NULL)
+ && IsBufferReady(chanPtr->state->curOutPtr)) {
+ SetFlag(chanPtr->state, BUFFER_READY);
+ }
+ if (FlushChannel(NULL, chanPtr, 0) != 0) {
+ return -1;
+ }
+ }
+ return 0;
+}
+
/*
*----------------------------------------------------------------------
*
@@ -3864,6 +3896,10 @@ WriteBytes(
char *dst;
int dstMax, sawLF, savedLF, total, dstLen, toWrite, translate;
+ if (srcLen) {
+ WillWrite(chanPtr);
+ }
+
total = 0;
sawLF = 0;
savedLF = 0;
@@ -3965,6 +4001,10 @@ WriteChars(
Tcl_Encoding encoding;
char safe[BUFFER_PADDING];
+ if (srcLen) {
+ WillWrite(chanPtr);
+ }
+
total = 0;
sawLF = 0;
savedLF = 0;
@@ -6920,8 +6960,8 @@ Tcl_Tell(
outputBuffered = Tcl_OutputBuffered(chan);
if ((inputBuffered != 0) && (outputBuffered != 0)) {
- Tcl_SetErrno(EFAULT);
- return Tcl_LongAsWide(-1);
+ //Tcl_SetErrno(EFAULT);
+ //return Tcl_LongAsWide(-1);
}
/*
@@ -6935,6 +6975,7 @@ Tcl_Tell(
Tcl_SetErrno(result);
return Tcl_LongAsWide(-1);
}
+
if (inputBuffered != 0) {
return curPos - inputBuffered;
}
@@ -7035,8 +7076,10 @@ Tcl_TruncateChannel(
* pre-read input data.
*/
- if (Tcl_Seek(chan, (Tcl_WideInt) 0, SEEK_CUR) == Tcl_LongAsWide(-1)) {
- return TCL_ERROR;
+ WillWrite(chanPtr);
+
+ if (WillRead(chanPtr) < 0) {
+ return TCL_ERROR;
}
/*