diff options
author | andreas_kupries <akupries@shaw.ca> | 2009-12-09 23:03:04 (GMT) |
---|---|---|
committer | andreas_kupries <akupries@shaw.ca> | 2009-12-09 23:03:04 (GMT) |
commit | b17b07981f00b8dfdb3894baeb9a5f6e67cf2010 (patch) | |
tree | 977b95fa2857e73daf39ea2b0cda6dec6662a4dc /generic | |
parent | 04598fc6cbdc102630fee4976e6afc6c2edd08bc (diff) | |
download | tcl-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')
-rw-r--r-- | generic/tclIO.c | 53 |
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; } /* |