diff options
Diffstat (limited to 'generic')
-rw-r--r-- | generic/tclIO.c | 572 |
1 files changed, 294 insertions, 278 deletions
diff --git a/generic/tclIO.c b/generic/tclIO.c index e6e11d0..1a2bbfb 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.151 2008/12/02 18:23:25 andreas_kupries Exp $ + * RCS: @(#) $Id: tclIO.c,v 1.152 2008/12/09 14:09:14 dkf Exp $ */ #include "tclInt.h" @@ -162,21 +162,21 @@ static void CutChannel(Tcl_Channel chan); * -------------------------------------------------------------------------- */ -#define BytesLeft(bufPtr) ((bufPtr)->nextAdded - (bufPtr)->nextRemoved) +#define BytesLeft(bufPtr) ((bufPtr)->nextAdded - (bufPtr)->nextRemoved) -#define SpaceLeft(bufPtr) ((bufPtr)->bufLength - (bufPtr)->nextAdded) +#define SpaceLeft(bufPtr) ((bufPtr)->bufLength - (bufPtr)->nextAdded) -#define IsBufferReady(bufPtr) ((bufPtr)->nextAdded > (bufPtr)->nextRemoved) +#define IsBufferReady(bufPtr) ((bufPtr)->nextAdded > (bufPtr)->nextRemoved) -#define IsBufferEmpty(bufPtr) ((bufPtr)->nextAdded == (bufPtr)->nextRemoved) +#define IsBufferEmpty(bufPtr) ((bufPtr)->nextAdded == (bufPtr)->nextRemoved) -#define IsBufferFull(bufPtr) ((bufPtr)->nextAdded >= (bufPtr)->bufLength) +#define IsBufferFull(bufPtr) ((bufPtr)->nextAdded >= (bufPtr)->bufLength) -#define IsBufferOverflowing(bufPtr) ((bufPtr)->nextAdded > (bufPtr)->bufLength) +#define IsBufferOverflowing(bufPtr) ((bufPtr)->nextAdded>(bufPtr)->bufLength) -#define InsertPoint(bufPtr) ((bufPtr)->buf + (bufPtr)->nextAdded) +#define InsertPoint(bufPtr) ((bufPtr)->buf + (bufPtr)->nextAdded) -#define RemovePoint(bufPtr) ((bufPtr)->buf + (bufPtr)->nextRemoved) +#define RemovePoint(bufPtr) ((bufPtr)->buf + (bufPtr)->nextRemoved) /* * For working with channel state flag bits. @@ -184,6 +184,7 @@ static void CutChannel(Tcl_Channel chan); #define SetFlag(statePtr, flag) ((statePtr)->flags |= (flag)) #define ResetFlag(statePtr, flag) ((statePtr)->flags &= ~(flag)) +#define GotFlag(statePtr, flag) ((statePtr)->flags & (flag)) /* * Macro for testing whether a string (in optionName, length len) matches a @@ -204,7 +205,8 @@ static void CutChannel(Tcl_Channel chan); */ static void DupChannelIntRep(Tcl_Obj *objPtr, Tcl_Obj *copyPtr); -static int SetChannelFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr); +static int SetChannelFromAny(Tcl_Interp *interp, + Tcl_Obj *objPtr); static void UpdateStringOfChannel(Tcl_Obj *objPtr); static void FreeChannelIntRep(Tcl_Obj *objPtr); @@ -230,6 +232,100 @@ static const Tcl_ObjType tclChannelType = { /* *--------------------------------------------------------------------------- * + * ChanClose, ChanRead, ChanSeek, ChanThreadAction, ChanWatch, ChanWrite -- + * + * Simplify the access to selected channel driver "methods" that are used + * in multiple places in a stereotypical fashion. These are just thin + * wrappers around the driver functions. + * + *--------------------------------------------------------------------------- + */ + +static inline int +ChanClose( + Channel *chanPtr, + Tcl_Interp *interp) +{ + if (chanPtr->typePtr->closeProc != TCL_CLOSE2PROC) { + return chanPtr->typePtr->closeProc(chanPtr->instanceData, interp); + } else { + return chanPtr->typePtr->close2Proc(chanPtr->instanceData, interp, 0); + } +} + +static inline int +ChanRead( + Channel *chanPtr, + char *dst, + int dstSize, + int *errnoPtr) +{ + return chanPtr->typePtr->inputProc(chanPtr->instanceData, dst, dstSize, + errnoPtr); +} + +static inline Tcl_WideInt +ChanSeek( + Channel *chanPtr, + Tcl_WideInt offset, + int mode, + int *errnoPtr) +{ + /* + * Note that we prefer the wideSeekProc if that field is available in the + * type and non-NULL. + */ + + if (HaveVersion(chanPtr->typePtr, TCL_CHANNEL_VERSION_3) && + chanPtr->typePtr->wideSeekProc != NULL) { + return chanPtr->typePtr->wideSeekProc(chanPtr->instanceData, + offset, mode, errnoPtr); + } + + if (offset<Tcl_LongAsWide(LONG_MIN) || offset>Tcl_LongAsWide(LONG_MAX)) { + *errnoPtr = EOVERFLOW; + return Tcl_LongAsWide(-1); + } + + return Tcl_LongAsWide(chanPtr->typePtr->seekProc(chanPtr->instanceData, + Tcl_WideAsLong(offset), mode, errnoPtr)); +} + +static inline void +ChanThreadAction( + Channel *chanPtr, + int action) +{ + Tcl_DriverThreadActionProc *threadActionProc = + Tcl_ChannelThreadActionProc(chanPtr->typePtr); + + if (threadActionProc != NULL) { + threadActionProc(chanPtr->instanceData, action); + } +} + +static inline void +ChanWatch( + Channel *chanPtr, + int mask) +{ + chanPtr->typePtr->watchProc(chanPtr->instanceData, mask); +} + +static inline int +ChanWrite( + Channel *chanPtr, + const char *src, + int srcLen, + int *errnoPtr) +{ + return chanPtr->typePtr->outputProc(chanPtr->instanceData, src, srcLen, + errnoPtr); +} + +/* + *--------------------------------------------------------------------------- + * * TclInitIOSubsystem -- * * Initialize all resources used by this subsystem on a per-process @@ -299,7 +395,8 @@ TclFinalizeIOSubsystem(void) statePtr != NULL; statePtr = statePtr->nextCSPtr) { chanPtr = statePtr->topChanPtr; - if (!(statePtr->flags & (CHANNEL_INCLOSE|CHANNEL_CLOSED|CHANNEL_DEAD))) { + if (!GotFlag(statePtr, CHANNEL_INCLOSE | CHANNEL_CLOSED | + CHANNEL_DEAD)) { active = 1; break; } @@ -349,12 +446,7 @@ TclFinalizeIOSubsystem(void) * device for this channel. */ - if (chanPtr->typePtr->closeProc != TCL_CLOSE2PROC) { - chanPtr->typePtr->closeProc(chanPtr->instanceData, NULL); - } else { - chanPtr->typePtr->close2Proc(chanPtr->instanceData, NULL, - 0); - } + (void) ChanClose(chanPtr, NULL); /* * Finally, we clean up the fields in the channel data @@ -396,6 +488,7 @@ Tcl_SetStdChannel( int type) /* One of TCL_STDIN, TCL_STDOUT, TCL_STDERR. */ { ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + switch (type) { case TCL_STDIN: tsdPtr->stdinInitialized = 1; @@ -687,7 +780,7 @@ DeleteChannelTable( } Tcl_DeleteChannelHandler((Tcl_Channel) chanPtr, - TclChannelEventScriptInvoker, (ClientData) sPtr); + TclChannelEventScriptInvoker, sPtr); TclDecrRefCount(sPtr->scriptPtr); ckfree((char *) sPtr); @@ -707,7 +800,7 @@ DeleteChannelTable( SetFlag(statePtr, CHANNEL_TAINTED); statePtr->refCount--; if (statePtr->refCount <= 0) { - if (!(statePtr->flags & BG_FLUSH_SCHEDULED)) { + if (!GotFlag(statePtr, BG_FLUSH_SCHEDULED)) { (void) Tcl_Close(interp, (Tcl_Channel) chanPtr); } } @@ -746,21 +839,19 @@ CheckForStdChannelsBeingClosed( ChannelState *statePtr = ((Channel *) chan)->state; ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); - if ((chan == tsdPtr->stdinChannel) && (tsdPtr->stdinInitialized)) { + if ((chan == tsdPtr->stdinChannel) && tsdPtr->stdinInitialized) { if (statePtr->refCount < 2) { statePtr->refCount = 0; tsdPtr->stdinChannel = NULL; return; } - } else if ((chan == tsdPtr->stdoutChannel) - && (tsdPtr->stdoutInitialized)) { + } else if ((chan == tsdPtr->stdoutChannel) && tsdPtr->stdoutInitialized) { if (statePtr->refCount < 2) { statePtr->refCount = 0; tsdPtr->stdoutChannel = NULL; return; } - } else if ((chan == tsdPtr->stderrChannel) - && (tsdPtr->stderrInitialized)) { + } else if ((chan == tsdPtr->stderrChannel) && tsdPtr->stderrInitialized) { if (statePtr->refCount < 2) { statePtr->refCount = 0; tsdPtr->stderrChannel = NULL; @@ -894,7 +985,7 @@ Tcl_UnregisterChannel( statePtr = ((Channel *) chan)->state->bottomChanPtr->state; - if (statePtr->flags & CHANNEL_INCLOSE) { + if (GotFlag(statePtr, CHANNEL_INCLOSE)) { if (interp != NULL) { Tcl_AppendResult(interp, "Illegal recursive call to close " "through close-handler of channel", NULL); @@ -933,12 +1024,12 @@ Tcl_UnregisterChannel( SetFlag(statePtr, BUFFER_READY); } Tcl_Preserve(statePtr); - if (!(statePtr->flags & BG_FLUSH_SCHEDULED)) { + if (!GotFlag(statePtr, BG_FLUSH_SCHEDULED)) { /* * We don't want to re-enter Tcl_Close(). */ - if (!(statePtr->flags & CHANNEL_CLOSED)) { + if (!GotFlag(statePtr, CHANNEL_CLOSED)) { if (Tcl_Close(interp, chan) != TCL_OK) { SetFlag(statePtr, CHANNEL_CLOSED); Tcl_Release(statePtr); @@ -1147,7 +1238,7 @@ Tcl_GetChannel( chanPtr = Tcl_GetHashValue(hPtr); chanPtr = chanPtr->state->bottomChanPtr; if (modePtr != NULL) { - *modePtr = (chanPtr->state->flags & (TCL_READABLE|TCL_WRITABLE)); + *modePtr = chanPtr->state->flags & (TCL_READABLE|TCL_WRITABLE); } return (Tcl_Channel) chanPtr; @@ -1192,10 +1283,10 @@ TclGetChannelFromObj( } statePtr = GET_CHANNELSTATE(objPtr); - *channelPtr = (Tcl_Channel) (statePtr->bottomChanPtr); + *channelPtr = (Tcl_Channel) statePtr->bottomChanPtr; if (modePtr != NULL) { - *modePtr = (statePtr->flags & (TCL_READABLE|TCL_WRITABLE)); + *modePtr = statePtr->flags & (TCL_READABLE|TCL_WRITABLE); } return TCL_OK; @@ -1241,7 +1332,7 @@ Tcl_CreateChannel( * as well. */ - assert(sizeof(Tcl_ChannelTypeVersion) == sizeof(Tcl_DriverBlockModeProc*)); + assert(sizeof(Tcl_ChannelTypeVersion)==sizeof(Tcl_DriverBlockModeProc *)); /* * JH: We could subsequently memset these to 0 to avoid the numerous @@ -1322,9 +1413,8 @@ Tcl_CreateChannel( statePtr->csPtrW = NULL; statePtr->outputStage = NULL; - if ((statePtr->encoding != NULL) && (statePtr->flags & TCL_WRITABLE)) { - statePtr->outputStage = (char *) - ckalloc((unsigned) (statePtr->bufSize + 2)); + if ((statePtr->encoding != NULL) && GotFlag(statePtr, TCL_WRITABLE)) { + statePtr->outputStage = ckalloc((unsigned) statePtr->bufSize + 2); } /* @@ -1415,7 +1505,8 @@ Tcl_CreateChannel( Tcl_Channel Tcl_StackChannel( Tcl_Interp *interp, /* The interpreter we are working in */ - const Tcl_ChannelType *typePtr, /* The channel type record for the new + const Tcl_ChannelType *typePtr, + /* The channel type record for the new * channel. */ ClientData instanceData, /* Instance specific data for the new * channel. */ @@ -1426,7 +1517,6 @@ Tcl_StackChannel( ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); Channel *chanPtr, *prevChanPtr; ChannelState *statePtr; - Tcl_DriverThreadActionProc *threadActionProc; /* * Find the given channel (prevChan) in the list of all channels. If we do @@ -1480,13 +1570,10 @@ Tcl_StackChannel( */ if ((mask & TCL_WRITABLE) != 0) { - CopyState *csPtrR; - CopyState *csPtrW; + CopyState *csPtrR = statePtr->csPtrR; + CopyState *csPtrW = statePtr->csPtrW; - csPtrR = statePtr->csPtrR; statePtr->csPtrR = NULL; - - csPtrW = statePtr->csPtrW; statePtr->csPtrW = NULL; if (Tcl_Flush((Tcl_Channel) prevChanPtr) != TCL_OK) { @@ -1571,10 +1658,7 @@ Tcl_StackChannel( * time, mangling it. */ - threadActionProc = Tcl_ChannelThreadActionProc(chanPtr->typePtr); - if (threadActionProc != NULL) { - threadActionProc(chanPtr->instanceData, TCL_CHANNEL_THREAD_INSERT); - } + ChanThreadAction(chanPtr, TCL_CHANNEL_THREAD_INSERT); return (Tcl_Channel) chanPtr; } @@ -1605,7 +1689,6 @@ Tcl_UnstackChannel( Channel *chanPtr = (Channel *) chan; ChannelState *statePtr = chanPtr->state; int result = 0; - Tcl_DriverThreadActionProc *threadActionProc; /* * This operation should occur at the top of a channel stack. @@ -1631,14 +1714,11 @@ Tcl_UnstackChannel( * CheckForChannelErrors inside. */ - if (statePtr->flags & TCL_WRITABLE) { - CopyState *csPtrR; - CopyState *csPtrW; + if (GotFlag(statePtr, TCL_WRITABLE)) { + CopyState *csPtrR = statePtr->csPtrR; + CopyState *csPtrW = statePtr->csPtrW; - csPtrR = statePtr->csPtrR; statePtr->csPtrR = NULL; - - csPtrW = statePtr->csPtrW; statePtr->csPtrW = NULL; if (Tcl_Flush((Tcl_Channel) chanPtr) != TCL_OK) { @@ -1675,16 +1755,14 @@ Tcl_UnstackChannel( * 'DiscardInputQueued' on that. */ - if ((((statePtr->flags & TCL_READABLE) != 0)) && + if (GotFlag(statePtr, TCL_READABLE) && ((statePtr->inQueueHead != NULL) || (chanPtr->inQueueHead != NULL))) { - if ((statePtr->inQueueHead != NULL) && (chanPtr->inQueueHead != NULL)) { statePtr->inQueueTail->nextPtr = chanPtr->inQueueHead; statePtr->inQueueTail = chanPtr->inQueueTail; statePtr->inQueueHead = statePtr->inQueueTail; - } else if (chanPtr->inQueueHead != NULL) { statePtr->inQueueHead = chanPtr->inQueueHead; statePtr->inQueueTail = chanPtr->inQueueTail; @@ -1708,10 +1786,7 @@ Tcl_UnstackChannel( * the state which are still active. */ - threadActionProc = Tcl_ChannelThreadActionProc(chanPtr->typePtr); - if (threadActionProc != NULL) { - threadActionProc(chanPtr->instanceData,TCL_CHANNEL_THREAD_REMOVE); - } + ChanThreadAction(chanPtr, TCL_CHANNEL_THREAD_REMOVE); statePtr->topChanPtr = downChanPtr; downChanPtr->upChanPtr = NULL; @@ -1725,14 +1800,7 @@ Tcl_UnstackChannel( * Close and free the channel driver state. */ - if (chanPtr->typePtr->closeProc != TCL_CLOSE2PROC) { - result = chanPtr->typePtr->closeProc(chanPtr->instanceData, - interp); - } else { - result = chanPtr->typePtr->close2Proc(chanPtr->instanceData, - interp, 0); - } - + result = ChanClose(chanPtr, interp); chanPtr->typePtr = NULL; /* @@ -1967,9 +2035,9 @@ const char * Tcl_GetChannelName( Tcl_Channel chan) /* The channel for which to return the name. */ { - ChannelState *statePtr; /* State of actual channel. */ + ChannelState *statePtr = ((Channel *) chan)->state; + /* State of actual channel. */ - statePtr = ((Channel *) chan)->state; return statePtr->channelName; } @@ -2099,7 +2167,7 @@ RecycleBuffer( * Only save buffers for the input queue if the channel is readable. */ - if (statePtr->flags & TCL_READABLE) { + if (GotFlag(statePtr, TCL_READABLE)) { if (statePtr->inQueueHead == NULL) { statePtr->inQueueHead = bufPtr; statePtr->inQueueTail = bufPtr; @@ -2115,7 +2183,7 @@ RecycleBuffer( * Only save buffers for the output queue if the channel is writable. */ - if (statePtr->flags & TCL_WRITABLE) { + if (GotFlag(statePtr, TCL_WRITABLE)) { if (statePtr->curOutPtr == NULL) { statePtr->curOutPtr = bufPtr; goto keepBuffer; @@ -2188,15 +2256,16 @@ CheckForDeadChannel( Tcl_Interp *interp, /* For error reporting (can be NULL) */ ChannelState *statePtr) /* The channel state to check. */ { - if (statePtr->flags & CHANNEL_DEAD) { - Tcl_SetErrno(EINVAL); - if (interp) { - Tcl_AppendResult(interp, - "unable to access channel: invalid channel", NULL); - } - return 1; + if (!GotFlag(statePtr, CHANNEL_DEAD)) { + return 0; } - return 0; + + Tcl_SetErrno(EINVAL); + if (interp) { + Tcl_AppendResult(interp, "unable to access channel: invalid channel", + NULL); + } + return 1; } /* @@ -2264,7 +2333,7 @@ FlushChannel( if (((statePtr->curOutPtr != NULL) && IsBufferFull(statePtr->curOutPtr)) - || ((statePtr->flags & BUFFER_READY) && + || (GotFlag(statePtr, BUFFER_READY) && (statePtr->outQueueHead == NULL))) { ResetFlag(statePtr, BUFFER_READY); statePtr->curOutPtr->nextPtr = NULL; @@ -2283,8 +2352,7 @@ FlushChannel( * is active, we just return without producing any output. */ - if ((!calledFromAsyncFlush) && - (statePtr->flags & BG_FLUSH_SCHEDULED)) { + if (!calledFromAsyncFlush && GotFlag(statePtr, BG_FLUSH_SCHEDULED)) { return 0; } @@ -2293,7 +2361,7 @@ FlushChannel( */ if (bufPtr == NULL) { - break; /* Out of the "while (1)". */ + break; /* Out of the "while (1)". */ } /* @@ -2301,8 +2369,7 @@ FlushChannel( */ toWrite = BytesLeft(bufPtr); - written = chanPtr->typePtr->outputProc(chanPtr->instanceData, - RemovePoint(bufPtr), toWrite, &errorCode); + written = ChanWrite(chanPtr, RemovePoint(bufPtr),toWrite, &errorCode); /* * If the write failed completely attempt to start the asynchronous @@ -2333,7 +2400,7 @@ FlushChannel( * it's a tty channel (dup'ed underneath) */ - if (!(statePtr->flags & BG_FLUSH_SCHEDULED)) { + if (!GotFlag(statePtr, BG_FLUSH_SCHEDULED)) { SetFlag(statePtr, BG_FLUSH_SCHEDULED); UpdateInterest(chanPtr); } @@ -2383,7 +2450,8 @@ FlushChannel( Tcl_SetErrno(errorCode); if (interp != NULL && !TclChanCaughtErrorBypass(interp, (Tcl_Channel) chanPtr)) { - Tcl_SetObjResult(interp, Tcl_NewStringObj(Tcl_PosixError(interp), -1)); + Tcl_SetObjResult(interp, + Tcl_NewStringObj(Tcl_PosixError(interp), -1)); } /* @@ -2425,13 +2493,12 @@ FlushChannel( * data has been flushed at the system level. */ - if (statePtr->flags & BG_FLUSH_SCHEDULED) { + if (GotFlag(statePtr, BG_FLUSH_SCHEDULED)) { if (wroteSome) { return errorCode; } else if (statePtr->outQueueHead == NULL) { ResetFlag(statePtr, BG_FLUSH_SCHEDULED); - chanPtr->typePtr->watchProc(chanPtr->instanceData, - statePtr->interestMask); + ChanWatch(chanPtr, statePtr->interestMask); } } @@ -2441,7 +2508,7 @@ FlushChannel( * current output buffer. */ - if ((statePtr->flags & CHANNEL_CLOSED) && (statePtr->refCount <= 0) && + if (GotFlag(statePtr, CHANNEL_CLOSED) && (statePtr->refCount <= 0) && (statePtr->outQueueHead == NULL) && ((statePtr->curOutPtr == NULL) || IsBufferEmpty(statePtr->curOutPtr))) { @@ -2517,11 +2584,11 @@ CloseChannel( * device. */ - if ((statePtr->outEofChar != 0) && (statePtr->flags & TCL_WRITABLE)) { + if ((statePtr->outEofChar != 0) && GotFlag(statePtr, TCL_WRITABLE)) { int dummy; char c = (char) statePtr->outEofChar; - chanPtr->typePtr->outputProc(chanPtr->instanceData, &c, 1, &dummy); + (void) ChanWrite(chanPtr, &c, 1, &dummy); } /* @@ -2549,12 +2616,7 @@ CloseChannel( * This may leave a TIP #219 error message in the interp. */ - if (chanPtr->typePtr->closeProc != TCL_CLOSE2PROC) { - result = chanPtr->typePtr->closeProc(chanPtr->instanceData, interp); - } else { - result = chanPtr->typePtr->close2Proc(chanPtr->instanceData, interp, - 0); - } + result = ChanClose(chanPtr, interp); /* * Some resources can be cleared only if the bottom channel in a stack is @@ -2678,7 +2740,6 @@ CutChannel( * the list on close. */ ChannelState *statePtr = ((Channel *) chan)->state; /* State of the channel stack. */ - Tcl_DriverThreadActionProc *threadActionProc; /* * Remove this channel from of the list of all channels (in the current @@ -2705,11 +2766,7 @@ CutChannel( * TIP #218, Channel Thread Actions */ - threadActionProc = Tcl_ChannelThreadActionProc(Tcl_GetChannelType(chan)); - if (threadActionProc != NULL) { - threadActionProc(Tcl_GetChannelInstanceData(chan), - TCL_CHANNEL_THREAD_REMOVE); - } + ChanThreadAction((Channel *) chan, TCL_CHANNEL_THREAD_REMOVE); } void @@ -2724,7 +2781,6 @@ Tcl_CutChannel( * the list on close. */ ChannelState *statePtr = chanPtr->state; /* State of the channel stack. */ - Tcl_DriverThreadActionProc *threadActionProc; /* * Remove this channel from of the list of all channels (in the current @@ -2752,12 +2808,8 @@ Tcl_CutChannel( * For all transformations and the base channel. */ - while (chanPtr) { - threadActionProc = Tcl_ChannelThreadActionProc(chanPtr->typePtr); - if (threadActionProc != NULL) { - threadActionProc(chanPtr->instanceData,TCL_CHANNEL_THREAD_REMOVE); - } - chanPtr= chanPtr->upChanPtr; + for (; chanPtr != NULL ; chanPtr = chanPtr->upChanPtr) { + ChanThreadAction(chanPtr, TCL_CHANNEL_THREAD_REMOVE); } } @@ -2794,7 +2846,6 @@ SpliceChannel( { ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); ChannelState *statePtr = ((Channel *) chan)->state; - Tcl_DriverThreadActionProc *threadActionProc; if (statePtr->nextCSPtr != NULL) { Tcl_Panic("SpliceChannel: trying to add channel used in different list"); @@ -2815,11 +2866,7 @@ SpliceChannel( * TIP #218, Channel Thread Actions */ - threadActionProc = Tcl_ChannelThreadActionProc(Tcl_GetChannelType(chan)); - if (threadActionProc != NULL) { - threadActionProc(Tcl_GetChannelInstanceData(chan), - TCL_CHANNEL_THREAD_INSERT); - } + ChanThreadAction((Channel *) chan, TCL_CHANNEL_THREAD_INSERT); } void @@ -2830,7 +2877,6 @@ Tcl_SpliceChannel( Channel *chanPtr = ((Channel *) chan)->state->bottomChanPtr; ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); ChannelState *statePtr = chanPtr->state; - Tcl_DriverThreadActionProc *threadActionProc; if (statePtr->nextCSPtr != NULL) { Tcl_Panic("SpliceChannel: trying to add channel used in different list"); @@ -2852,12 +2898,8 @@ Tcl_SpliceChannel( * For all transformations and the base channel. */ - while (chanPtr) { - threadActionProc = Tcl_ChannelThreadActionProc(chanPtr->typePtr); - if (threadActionProc != NULL) { - threadActionProc(chanPtr->instanceData,TCL_CHANNEL_THREAD_INSERT); - } - chanPtr= chanPtr->upChanPtr; + for (; chanPtr != NULL ; chanPtr = chanPtr->upChanPtr) { + ChanThreadAction(chanPtr, TCL_CHANNEL_THREAD_INSERT); } } @@ -2923,7 +2965,7 @@ Tcl_Close( Tcl_Panic("called Tcl_Close on channel with refCount > 0"); } - if (statePtr->flags & CHANNEL_INCLOSE) { + if (GotFlag(statePtr, CHANNEL_INCLOSE)) { if (interp) { Tcl_AppendResult(interp, "Illegal recursive call to close " "through close-handler of channel", NULL); @@ -3219,9 +3261,7 @@ Tcl_WriteRaw( * The code was stolen from 'FlushChannel'. */ - written = chanPtr->typePtr->outputProc(chanPtr->instanceData, src, - srcLen, &errorCode); - + written = ChanWrite(chanPtr, src, srcLen, &errorCode); if (written < 0) { Tcl_SetErrno(errorCode); } @@ -3322,12 +3362,13 @@ DoWriteChars( * be extended to more efficient translation of the src string. */ - int result; + int result; if ((len == 1) && (UCHAR(*src) < 0xC0)) { result = WriteBytes(chanPtr, src, len); } else { Tcl_Obj *objPtr = Tcl_NewStringObj(src, len); + src = (char *) Tcl_GetByteArrayFromObj(objPtr, &len); result = WriteBytes(chanPtr, src, len); TclDecrRefCount(objPtr); @@ -3427,8 +3468,8 @@ WriteBytes( total = 0; sawLF = 0; savedLF = 0; - translate = (statePtr->flags & CHANNEL_LINEBUFFERED) - || (statePtr->outputTranslation != TCL_TRANSLATE_LF); + translate = GotFlag(statePtr, CHANNEL_LINEBUFFERED) + || (statePtr->outputTranslation != TCL_TRANSLATE_LF); /* * Loop over all bytes in src, storing them in output buffer with proper @@ -3537,8 +3578,8 @@ WriteChars( endEncoding = ((statePtr->outputEncodingFlags & TCL_ENCODING_END) != 0); - translate = (statePtr->flags & CHANNEL_LINEBUFFERED) - || (statePtr->outputTranslation != TCL_TRANSLATE_LF); + translate = GotFlag(statePtr, CHANNEL_LINEBUFFERED) + || (statePtr->outputTranslation != TCL_TRANSLATE_LF); /* * Loop over all UTF-8 characters in src, storing them in staging buffer @@ -3561,16 +3602,17 @@ WriteChars( if (savedLF) { /* * A '\n' was left over from last call to TranslateOutputEOL() - * and we need to store it in the staging buffer. If the channel - * is line-based, we will need to flush the output buffer (after - * translating the staging buffer). + * and we need to store it in the staging buffer. If the + * channel is line-based, we will need to flush the output + * buffer (after translating the staging buffer). */ *stage++ = '\n'; stageLen--; sawLF++; } - if (TranslateOutputEOL(statePtr, stage, src, &stageLen, &toWrite)) { + if (TranslateOutputEOL(statePtr, stage, src, &stageLen, + &toWrite)) { sawLF++; } @@ -3863,18 +3905,18 @@ CheckFlush( * 3. if it contains any output and this channel is unbuffered. */ - if ((statePtr->flags & BUFFER_READY) == 0) { + if (!GotFlag(statePtr, BUFFER_READY)) { if (IsBufferFull(bufPtr)) { SetFlag(statePtr, BUFFER_READY); - } else if (statePtr->flags & CHANNEL_LINEBUFFERED) { + } else if (GotFlag(statePtr, CHANNEL_LINEBUFFERED)) { if (newlineFlag != 0) { SetFlag(statePtr, BUFFER_READY); } - } else if (statePtr->flags & CHANNEL_UNBUFFERED) { + } else if (GotFlag(statePtr, CHANNEL_UNBUFFERED)) { SetFlag(statePtr, BUFFER_READY); } } - if (statePtr->flags & BUFFER_READY) { + if (GotFlag(statePtr, BUFFER_READY)) { if (FlushChannel(NULL, chanPtr, 0) != 0) { return -1; } @@ -4125,7 +4167,7 @@ Tcl_GetsObj( case TCL_TRANSLATE_AUTO: eol = dst; skip = 1; - if (statePtr->flags & INPUT_SAW_CR) { + if (GotFlag(statePtr, INPUT_SAW_CR)) { ResetFlag(statePtr, INPUT_SAW_CR); if ((eol < dstEnd) && (*eol == '\n')) { /* @@ -4193,7 +4235,7 @@ Tcl_GetsObj( SetFlag(statePtr, CHANNEL_EOF | CHANNEL_STICKY_EOF); statePtr->inputEncodingFlags |= TCL_ENCODING_END; } - if (statePtr->flags & CHANNEL_EOF) { + if (GotFlag(statePtr, CHANNEL_EOF)) { skip = 0; eol = dstEnd; if (eol == objPtr->bytes + oldLength) { @@ -4350,7 +4392,11 @@ TclGetsObjBinary( skip = 0; eof = NULL; inEofChar = statePtr->inEofChar; - /* Only handle TCL_TRANSLATE_LF and TCL_TRANSLATE_CR */ + + /* + * Only handle TCL_TRANSLATE_LF and TCL_TRANSLATE_CR. + */ + eolChar = (statePtr->inputTranslation == TCL_TRANSLATE_LF) ? '\n' : '\r'; while (1) { @@ -4373,8 +4419,8 @@ TclGetsObjBinary( * device. Side effect is to allocate another channel buffer. */ - if (statePtr->flags & CHANNEL_BLOCKED) { - if (statePtr->flags & CHANNEL_NONBLOCKING) { + if (GotFlag(statePtr, CHANNEL_BLOCKED)) { + if (GotFlag(statePtr, CHANNEL_NONBLOCKING)) { goto restore; } ResetFlag(statePtr, CHANNEL_BLOCKED); @@ -4425,7 +4471,7 @@ TclGetsObjBinary( SetFlag(statePtr, CHANNEL_EOF | CHANNEL_STICKY_EOF); statePtr->inputEncodingFlags |= TCL_ENCODING_END; } - if (statePtr->flags & CHANNEL_EOF) { + if (GotFlag(statePtr, CHANNEL_EOF)) { skip = 0; eol = dstEnd; if ((dst == dstEnd) && (byteLen == oldLength)) { @@ -4624,8 +4670,8 @@ FilterInputBytes( */ read: - if (statePtr->flags & CHANNEL_BLOCKED) { - if (statePtr->flags & CHANNEL_NONBLOCKING) { + if (GotFlag(statePtr, CHANNEL_BLOCKED)) { + if (GotFlag(statePtr, CHANNEL_NONBLOCKING)) { gsPtr->charsWrote = 0; gsPtr->rawRead = 0; return -1; @@ -4701,7 +4747,7 @@ FilterInputBytes( * returning those UTF-8 characters because a EOL might be * present in them. */ - } else if (statePtr->flags & CHANNEL_EOF) { + } else if (GotFlag(statePtr, CHANNEL_EOF)) { /* * There was a partial character followed by EOF on the * device. Fall through, returning that nothing was found. @@ -4790,7 +4836,7 @@ PeekAhead( goto cleanup; } - if ((statePtr->flags & CHANNEL_NONBLOCKING) == 0) { + if (!GotFlag(statePtr, CHANNEL_NONBLOCKING)) { blockModeProc = Tcl_ChannelBlockModeProc(chanPtr->typePtr); if (blockModeProc == NULL) { /* @@ -4986,11 +5032,11 @@ Tcl_ReadRaw( copiedNow = CopyBuffer(chanPtr, bufPtr + copied, bytesToRead - copied); if (copiedNow == 0) { - if (statePtr->flags & CHANNEL_EOF) { + if (GotFlag(statePtr, CHANNEL_EOF)) { goto done; } - if (statePtr->flags & CHANNEL_BLOCKED) { - if (statePtr->flags & CHANNEL_NONBLOCKING) { + if (GotFlag(statePtr, CHANNEL_BLOCKED)) { + if (GotFlag(statePtr, CHANNEL_NONBLOCKING)) { goto done; } ResetFlag(statePtr, CHANNEL_BLOCKED); @@ -5004,9 +5050,9 @@ Tcl_ReadRaw( * and only if we are sure to have data. */ - if ((statePtr->flags & CHANNEL_NONBLOCKING) && + if (GotFlag(statePtr, CHANNEL_NONBLOCKING) && (Tcl_ChannelBlockModeProc(chanPtr->typePtr) == NULL) && - !(statePtr->flags & CHANNEL_HAS_MORE_DATA)) { + !GotFlag(statePtr, CHANNEL_HAS_MORE_DATA)) { /* * We bypass the driver; it would block as no data is * available. @@ -5014,9 +5060,9 @@ Tcl_ReadRaw( nread = -1; result = EWOULDBLOCK; - } else { + } else #endif /* TCL_IO_TRACK_OS_FOR_DRIVER_WITH_BAD_BLOCKING */ - + { /* * Now go to the driver to get as much as is possible to fill * the remaining request. Do all the error handling by @@ -5026,12 +5072,9 @@ Tcl_ReadRaw( * The case of 'bytesToRead == 0' at this point cannot happen. */ - nread = chanPtr->typePtr->inputProc(chanPtr->instanceData, - bufPtr + copied, bytesToRead - copied, &result); - -#ifdef TCL_IO_TRACK_OS_FOR_DRIVER_WITH_BAD_BLOCKING + nread = ChanRead(chanPtr, bufPtr + copied, + bytesToRead - copied, &result); } -#endif /* TCL_IO_TRACK_OS_FOR_DRIVER_WITH_BAD_BLOCKING */ if (nread > 0) { /* @@ -5055,7 +5098,6 @@ Tcl_ReadRaw( ResetFlag(statePtr, CHANNEL_HAS_MORE_DATA); } #endif /* TCL_IO_TRACK_OS_FOR_DRIVER_WITH_BAD_BLOCKING */ - } else if (nread == 0) { SetFlag(statePtr, CHANNEL_EOF); statePtr->inputEncodingFlags |= TCL_ENCODING_END; @@ -5231,9 +5273,8 @@ DoReadChars( bufPtr = statePtr->inQueueHead; if (IsBufferEmpty(bufPtr)) { - ChannelBuffer *nextPtr; + ChannelBuffer *nextPtr = bufPtr->nextPtr; - nextPtr = bufPtr->nextPtr; RecycleBuffer(statePtr, bufPtr, 0); statePtr->inQueueHead = nextPtr; if (nextPtr == NULL) { @@ -5243,11 +5284,11 @@ DoReadChars( } if (copiedNow < 0) { - if (statePtr->flags & CHANNEL_EOF) { + if (GotFlag(statePtr, CHANNEL_EOF)) { break; } - if (statePtr->flags & CHANNEL_BLOCKED) { - if (statePtr->flags & CHANNEL_NONBLOCKING) { + if (GotFlag(statePtr, CHANNEL_BLOCKED)) { + if (GotFlag(statePtr, CHANNEL_NONBLOCKING)) { break; } ResetFlag(statePtr, CHANNEL_BLOCKED); @@ -5359,7 +5400,7 @@ ReadBytes( } dst += offset; - if (statePtr->flags & INPUT_NEED_NL) { + if (GotFlag(statePtr, INPUT_NEED_NL)) { ResetFlag(statePtr, INPUT_NEED_NL); if ((srcLen == 0) || (*src != '\n')) { *dst = '\r'; @@ -5449,7 +5490,7 @@ ReadChars( srcLen = BytesLeft(bufPtr); toRead = charsToRead; - if ((unsigned)toRead > (unsigned)srcLen) { + if ((unsigned) toRead > (unsigned) srcLen) { toRead = srcLen; } @@ -5534,7 +5575,7 @@ ReadChars( } oldState = statePtr->inputEncodingState; - if (statePtr->flags & INPUT_NEED_NL) { + if (GotFlag(statePtr, INPUT_NEED_NL)) { /* * We want a '\n' because the last character we saw was '\r'. */ @@ -5650,16 +5691,15 @@ ReadChars( * '\n' in dst. */ - numChars -= (dstRead - dstWrote); + numChars -= dstRead - dstWrote; if ((unsigned) numChars > (unsigned) toRead) { /* * Got too many chars. */ - const char *eof; + const char *eof = Tcl_UtfAtIndex(dst, toRead); - eof = Tcl_UtfAtIndex(dst, toRead); statePtr->inputEncodingState = oldState; Tcl_ExternalToUtf(NULL, statePtr->encoding, src, srcLen, statePtr->inputEncodingFlags, &statePtr->inputEncodingState, @@ -5727,9 +5767,8 @@ TranslateInputEOL( * buffer. */ - const char *src, *srcMax; + const char *src, *srcMax = srcStart + *srcLenPtr; - srcMax = srcStart + *srcLenPtr; for (src = srcStart; src < srcMax; src++) { if (*src == inEofChar) { eof = src; @@ -5800,7 +5839,7 @@ TranslateInputEOL( srcEnd = srcStart + dstLen; srcMax = srcStart + *srcLenPtr; - if ((statePtr->flags & INPUT_SAW_CR) && (src < srcMax)) { + if (GotFlag(statePtr, INPUT_SAW_CR) && (src < srcMax)) { if (*src == '\n') { src++; } @@ -5905,7 +5944,7 @@ Tcl_Ungets( * bit. We want to discover these conditions anew in each operation. */ - if (statePtr->flags & CHANNEL_STICKY_EOF) { + if (GotFlag(statePtr, CHANNEL_STICKY_EOF)) { goto done; } ResetFlag(statePtr, CHANNEL_BLOCKED | CHANNEL_EOF); @@ -6162,7 +6201,7 @@ GetInput( * platforms it is impossible to read from a device after EOF. */ - if (statePtr->flags & CHANNEL_EOF) { + if (GotFlag(statePtr, CHANNEL_EOF)) { return 0; } @@ -6174,24 +6213,20 @@ GetInput( * sure to have data. */ - if ((statePtr->flags & CHANNEL_NONBLOCKING) && + if (GotFlag(statePtr, CHANNEL_NONBLOCKING) && (Tcl_ChannelBlockModeProc(chanPtr->typePtr) == NULL) && - !(statePtr->flags & CHANNEL_HAS_MORE_DATA)) { + !GotFlag(statePtr, CHANNEL_HAS_MORE_DATA)) { /* * Bypass the driver, it would block, as no data is available */ nread = -1; result = EWOULDBLOCK; - } else { + } else #endif /* TCL_IO_TRACK_OS_FOR_DRIVER_WITH_BAD_BLOCKING */ - - nread = chanPtr->typePtr->inputProc(chanPtr->instanceData, - InsertPoint(bufPtr), toRead, &result); - -#ifdef TCL_IO_TRACK_OS_FOR_DRIVER_WITH_BAD_BLOCKING + { + nread = ChanRead(chanPtr, InsertPoint(bufPtr), toRead, &result); } -#endif /* TCL_IO_TRACK_OS_FOR_DRIVER_WITH_BAD_BLOCKING */ if (nread > 0) { bufPtr->nextAdded += nread; @@ -6217,7 +6252,6 @@ GetInput( ResetFlag(statePtr, CHANNEL_HAS_MORE_DATA); } #endif /* TCL_IO_TRACK_OS_FOR_DRIVER_WITH_BAD_BLOCKING */ - } else if (nread == 0) { SetFlag(statePtr, CHANNEL_EOF); statePtr->inputEncodingFlags |= TCL_ENCODING_END; @@ -6333,8 +6367,8 @@ Tcl_Seek( * point. Also clear CR related flags. */ - statePtr->flags &= - ~(CHANNEL_EOF | CHANNEL_STICKY_EOF | CHANNEL_BLOCKED | INPUT_SAW_CR); + ResetFlag(statePtr, CHANNEL_EOF | CHANNEL_STICKY_EOF | CHANNEL_BLOCKED | + INPUT_SAW_CR); /* * If the channel is in asynchronous output mode, switch it back to @@ -6344,14 +6378,14 @@ Tcl_Seek( */ wasAsync = 0; - if (statePtr->flags & CHANNEL_NONBLOCKING) { + if (GotFlag(statePtr, CHANNEL_NONBLOCKING)) { wasAsync = 1; result = StackSetBlockMode(chanPtr, TCL_MODE_BLOCKING); if (result != 0) { return Tcl_LongAsWide(-1); } ResetFlag(statePtr, CHANNEL_NONBLOCKING); - if (statePtr->flags & BG_FLUSH_SCHEDULED) { + if (GotFlag(statePtr, BG_FLUSH_SCHEDULED)) { ResetFlag(statePtr, BG_FLUSH_SCHEDULED); } } @@ -6378,23 +6412,10 @@ Tcl_Seek( } else { /* * Now seek to the new position in the channel as requested by the - * caller. Note that we prefer the wideSeekProc if that is available - * and non-NULL... + * caller. */ - if (HaveVersion(chanPtr->typePtr, TCL_CHANNEL_VERSION_3) && - chanPtr->typePtr->wideSeekProc != NULL) { - curPos = chanPtr->typePtr->wideSeekProc(chanPtr->instanceData, - offset, mode, &result); - } else if (offset < Tcl_LongAsWide(LONG_MIN) || - offset > Tcl_LongAsWide(LONG_MAX)) { - result = EOVERFLOW; - curPos = Tcl_LongAsWide(-1); - } else { - curPos = Tcl_LongAsWide(chanPtr->typePtr->seekProc( - chanPtr->instanceData, Tcl_WideAsLong(offset), mode, - &result)); - } + curPos = ChanSeek(chanPtr, offset, mode, &result); if (curPos == Tcl_LongAsWide(-1)) { Tcl_SetErrno(result); } @@ -6500,14 +6521,7 @@ Tcl_Tell( * wideSeekProc if that is available and non-NULL... */ - if (HaveVersion(chanPtr->typePtr, TCL_CHANNEL_VERSION_3) && - chanPtr->typePtr->wideSeekProc != NULL) { - curPos = chanPtr->typePtr->wideSeekProc(chanPtr->instanceData, - Tcl_LongAsWide(0), SEEK_CUR, &result); - } else { - curPos = Tcl_LongAsWide(chanPtr->typePtr->seekProc( - chanPtr->instanceData, 0, SEEK_CUR, &result)); - } + curPos = ChanSeek(chanPtr, Tcl_LongAsWide(0), SEEK_CUR, &result); if (curPos == Tcl_LongAsWide(-1)) { Tcl_SetErrno(result); return Tcl_LongAsWide(-1); @@ -6545,19 +6559,18 @@ Tcl_SeekOld( { Tcl_WideInt wOffset, wResult; - wOffset = Tcl_LongAsWide((long)offset); + wOffset = Tcl_LongAsWide((long) offset); wResult = Tcl_Seek(chan, wOffset, mode); - return (int)Tcl_WideAsLong(wResult); + return (int) Tcl_WideAsLong(wResult); } int Tcl_TellOld( Tcl_Channel chan) /* The channel to return pos for. */ { - Tcl_WideInt wResult; + Tcl_WideInt wResult = Tcl_Tell(chan); - wResult = Tcl_Tell(chan); - return (int)Tcl_WideAsLong(wResult); + return (int) Tcl_WideAsLong(wResult); } /* @@ -6598,7 +6611,7 @@ Tcl_TruncateChannel( return TCL_ERROR; } - if (!(chanPtr->state->flags & TCL_WRITABLE)) { + if (!GotFlag(chanPtr->state, TCL_WRITABLE)) { /* * We require that the file was opened of writing. Do that check now * so that we only flush if we think we're going to succeed. @@ -6613,7 +6626,7 @@ Tcl_TruncateChannel( * pre-read input data. */ - if (Tcl_Seek(chan, (Tcl_WideInt)0, SEEK_CUR) == Tcl_LongAsWide(-1)) { + if (Tcl_Seek(chan, (Tcl_WideInt) 0, SEEK_CUR) == Tcl_LongAsWide(-1)) { return TCL_ERROR; } @@ -6684,8 +6697,7 @@ CheckChannelErrors( * order to drain data from stacked channels. */ - if ((statePtr->flags & CHANNEL_CLOSED) && - ((flags & CHANNEL_RAW_MODE) == 0)) { + if (GotFlag(statePtr, CHANNEL_CLOSED) && !(flags & CHANNEL_RAW_MODE)) { Tcl_SetErrno(EACCES); return -1; } @@ -6720,7 +6732,7 @@ CheckChannelErrors( * discover these conditions anew in each operation. */ - if ((statePtr->flags & CHANNEL_STICKY_EOF) == 0) { + if (!GotFlag(statePtr, CHANNEL_STICKY_EOF)) { ResetFlag(statePtr, CHANNEL_EOF); } ResetFlag(statePtr, CHANNEL_BLOCKED | CHANNEL_NEED_MORE_DATA); @@ -6752,8 +6764,8 @@ Tcl_Eof( ChannelState *statePtr = ((Channel *) chan)->state; /* State of real channel structure. */ - return ((statePtr->flags & CHANNEL_STICKY_EOF) || - ((statePtr->flags & CHANNEL_EOF) && + return (GotFlag(statePtr, CHANNEL_STICKY_EOF) || + (GotFlag(statePtr, CHANNEL_EOF) && (Tcl_InputBuffered(chan) == 0))) ? 1 : 0; } @@ -6780,7 +6792,7 @@ Tcl_InputBlocked( ChannelState *statePtr = ((Channel *) chan)->state; /* State of real channel structure. */ - return (statePtr->flags & CHANNEL_BLOCKED) ? 1 : 0; + return GotFlag(statePtr, CHANNEL_BLOCKED) ? 1 : 0; } /* @@ -6933,9 +6945,9 @@ Tcl_SetChannelBufferSize( */ if (sz < 1) { - sz = 1; + sz = 1; } else if (sz > MAX_CHANNEL_BUFFER_SIZE) { - sz = MAX_CHANNEL_BUFFER_SIZE; + sz = MAX_CHANNEL_BUFFER_SIZE; } statePtr = ((Channel *) chan)->state; @@ -6945,9 +6957,8 @@ Tcl_SetChannelBufferSize( ckfree((char *) statePtr->outputStage); statePtr->outputStage = NULL; } - if ((statePtr->encoding != NULL) && (statePtr->flags & TCL_WRITABLE)) { - statePtr->outputStage = (char *) - ckalloc((unsigned) (statePtr->bufSize + 2)); + if ((statePtr->encoding != NULL) && GotFlag(statePtr, TCL_WRITABLE)) { + statePtr->outputStage = ckalloc((unsigned) statePtr->bufSize + 2); } } @@ -7103,9 +7114,9 @@ Tcl_GetChannelOption( */ if (statePtr->csPtrR) { - flags = statePtr->csPtrR->readFlags; + flags = statePtr->csPtrR->readFlags; } else if (statePtr->csPtrW) { - flags = statePtr->csPtrW->writeFlags; + flags = statePtr->csPtrW->writeFlags; } else { flags = statePtr->flags; } @@ -7357,8 +7368,7 @@ Tcl_SetChannelOption( } else if (HaveOpt(7, "-buffering")) { len = strlen(newValue); if ((newValue[0] == 'f') && (strncmp(newValue, "full", len) == 0)) { - statePtr->flags &= - ~(CHANNEL_UNBUFFERED|CHANNEL_LINEBUFFERED); + ResetFlag(statePtr, CHANNEL_UNBUFFERED | CHANNEL_LINEBUFFERED); } else if ((newValue[0] == 'l') && (strncmp(newValue, "line", len) == 0)) { ResetFlag(statePtr, CHANNEL_UNBUFFERED); @@ -7423,6 +7433,7 @@ Tcl_SetChannelOption( int outIndex = (argc - 1); int inValue = (int) argv[0][0]; int outValue = (int) argv[outIndex][0]; + if (inValue & 0x80 || outValue & 0x80) { if (interp) { Tcl_AppendResult(interp, "bad value for -eofchar: ", @@ -7431,10 +7442,10 @@ Tcl_SetChannelOption( ckfree((char *) argv); return TCL_ERROR; } - if (statePtr->flags & TCL_READABLE) { + if (GotFlag(statePtr, TCL_READABLE)) { statePtr->inEofChar = inValue; } - if (statePtr->flags & TCL_WRITABLE) { + if (GotFlag(statePtr, TCL_WRITABLE)) { statePtr->outEofChar = outValue; } } else { @@ -7456,9 +7467,7 @@ Tcl_SetChannelOption( * ahead'. Ditto for blocked. */ - statePtr->flags &= - ~(CHANNEL_EOF | CHANNEL_STICKY_EOF | CHANNEL_BLOCKED); - + ResetFlag(statePtr, CHANNEL_EOF|CHANNEL_STICKY_EOF|CHANNEL_BLOCKED); return TCL_OK; } else if (HaveOpt(1, "-translation")) { const char *readMode, *writeMode; @@ -7468,11 +7477,11 @@ Tcl_SetChannelOption( } if (argc == 1) { - readMode = (statePtr->flags & TCL_READABLE) ? argv[0] : NULL; - writeMode = (statePtr->flags & TCL_WRITABLE) ? argv[0] : NULL; + readMode = GotFlag(statePtr, TCL_READABLE) ? argv[0] : NULL; + writeMode = GotFlag(statePtr, TCL_WRITABLE) ? argv[0] : NULL; } else if (argc == 2) { - readMode = (statePtr->flags & TCL_READABLE) ? argv[0] : NULL; - writeMode = (statePtr->flags & TCL_WRITABLE) ? argv[1] : NULL; + readMode = GotFlag(statePtr, TCL_READABLE) ? argv[0] : NULL; + writeMode = GotFlag(statePtr, TCL_WRITABLE) ? argv[1] : NULL; } else { if (interp) { Tcl_AppendResult(interp, @@ -7485,6 +7494,7 @@ Tcl_SetChannelOption( if (readMode) { TclEolTranslation translation; + if (*readMode == '\0') { translation = statePtr->inputTranslation; } else if (strcmp(readMode, "auto") == 0) { @@ -7597,7 +7607,7 @@ Tcl_SetChannelOption( ckfree(statePtr->outputStage); statePtr->outputStage = NULL; } - if ((statePtr->encoding != NULL) && (statePtr->flags & TCL_WRITABLE)) { + if ((statePtr->encoding != NULL) && GotFlag(statePtr, TCL_WRITABLE)) { statePtr->outputStage = ckalloc((unsigned) (statePtr->bufSize + 2)); } return TCL_OK; @@ -7699,9 +7709,9 @@ Tcl_NotifyChannel( */ if ((mask & TCL_READABLE) && - (statePtr->flags & CHANNEL_NONBLOCKING) && + GotFlag(statePtr, CHANNEL_NONBLOCKING) && (Tcl_ChannelBlockModeProc(chanPtr->typePtr) == NULL) && - !(statePtr->flags & CHANNEL_TIMER_FEV)) { + !GotFlag(statePtr, CHANNEL_TIMER_FEV)) { SetFlag(statePtr, CHANNEL_HAS_MORE_DATA); } #endif /* TCL_IO_TRACK_OS_FOR_DRIVER_WITH_BAD_BLOCKING */ @@ -7718,7 +7728,7 @@ Tcl_NotifyChannel( * their own events and pass them upward. */ - while (mask && (chanPtr->upChanPtr != (NULL))) { + while (mask && (chanPtr->upChanPtr != NULL)) { Tcl_DriverHandlerProc *upHandlerProc; upChanPtr = chanPtr->upChanPtr; @@ -7764,7 +7774,7 @@ Tcl_NotifyChannel( * don't call any write handlers before the flush is complete. */ - if ((statePtr->flags & BG_FLUSH_SCHEDULED) && (mask & TCL_WRITABLE)) { + if (GotFlag(statePtr, BG_FLUSH_SCHEDULED) && (mask & TCL_WRITABLE)) { FlushChannel(NULL, chanPtr, 1); mask &= ~TCL_WRITABLE; } @@ -7839,7 +7849,7 @@ UpdateInterest( * watch for the channel to become writable. */ - if (statePtr->flags & BG_FLUSH_SCHEDULED) { + if (GotFlag(statePtr, BG_FLUSH_SCHEDULED)) { mask |= TCL_WRITABLE; } @@ -7851,7 +7861,7 @@ UpdateInterest( */ if (mask & TCL_READABLE) { - if (!(statePtr->flags & CHANNEL_NEED_MORE_DATA) + if (!GotFlag(statePtr, CHANNEL_NEED_MORE_DATA) && (statePtr->inQueueHead != NULL) && IsBufferReady(statePtr->inQueueHead)) { mask &= ~TCL_READABLE; @@ -7902,7 +7912,7 @@ UpdateInterest( } } } - chanPtr->typePtr->watchProc(chanPtr->instanceData, mask); + ChanWatch(chanPtr, mask); } /* @@ -7930,7 +7940,7 @@ ChannelTimerProc( ChannelState *statePtr = chanPtr->state; /* State info for channel */ - if (!(statePtr->flags & CHANNEL_NEED_MORE_DATA) + if (!GotFlag(statePtr, CHANNEL_NEED_MORE_DATA) && (statePtr->interestMask & TCL_READABLE) && (statePtr->inQueueHead != NULL) && IsBufferReady(statePtr->inQueueHead)) { @@ -7950,8 +7960,8 @@ ChannelTimerProc( * similar test is done in "PeekAhead". */ - if ((statePtr->flags & CHANNEL_NONBLOCKING) && - (Tcl_ChannelBlockModeProc(chanPtr->typePtr) == NULL)) { + if (GotFlag(statePtr, CHANNEL_NONBLOCKING) && + (Tcl_ChannelBlockModeProc(chanPtr->typePtr) == NULL)) { SetFlag(statePtr, CHANNEL_TIMER_FEV); } #endif /* TCL_IO_TRACK_OS_FOR_DRIVER_WITH_BAD_BLOCKING */ @@ -8368,6 +8378,7 @@ Tcl_FileEventObjCmd( if (objc == 3) { EventScriptRecord *esPtr; + for (esPtr = statePtr->scriptRecordPtr; esPtr != NULL; esPtr = esPtr->nextPtr) { if ((esPtr->interp == interp) && (esPtr->mask == mask)) { @@ -8480,8 +8491,8 @@ TclCopyChannel( * Make sure the output side is unbuffered. */ - outStatePtr->flags = (outStatePtr->flags & ~(CHANNEL_LINEBUFFERED)) - | CHANNEL_UNBUFFERED; + outStatePtr->flags = (outStatePtr->flags & ~CHANNEL_LINEBUFFERED) + | CHANNEL_UNBUFFERED; /* * Allocate a new CopyState to maintain info about the current copy in @@ -8593,7 +8604,7 @@ CopyData( * underflow instead to prime the readable fileevent. */ - size = 0; + size = 0; underflow = 1; } else { /* @@ -8732,7 +8743,7 @@ CopyData( * therefore we don't need a writable handler. */ - if (!underflow && (outStatePtr->flags & BG_FLUSH_SCHEDULED)) { + if (!underflow && GotFlag(outStatePtr, BG_FLUSH_SCHEDULED)) { if (!(mask & TCL_WRITABLE)) { if (mask & TCL_READABLE) { Tcl_DeleteChannelHandler(inChan, CopyEventProc, csPtr); @@ -8783,6 +8794,7 @@ CopyData( total = csPtr->total; if (cmdPtr && interp) { int code; + /* * Get a private copy of the command so we can mutate it by adding * arguments. Note that StopCopy frees our saved reference to the @@ -8859,7 +8871,7 @@ DoRead( * operation. */ - if (!(statePtr->flags & CHANNEL_STICKY_EOF)) { + if (!GotFlag(statePtr, CHANNEL_STICKY_EOF)) { ResetFlag(statePtr, CHANNEL_EOF); } ResetFlag(statePtr, CHANNEL_BLOCKED | CHANNEL_NEED_MORE_DATA); @@ -8868,11 +8880,11 @@ DoRead( copiedNow = CopyAndTranslateBuffer(statePtr, bufPtr + copied, toRead - copied); if (copiedNow == 0) { - if (statePtr->flags & CHANNEL_EOF) { + if (GotFlag(statePtr, CHANNEL_EOF)) { goto done; } - if (statePtr->flags & CHANNEL_BLOCKED) { - if (statePtr->flags & CHANNEL_NONBLOCKING) { + if (GotFlag(statePtr, CHANNEL_BLOCKED)) { + if (GotFlag(statePtr, CHANNEL_NONBLOCKING)) { goto done; } ResetFlag(statePtr, CHANNEL_BLOCKED); @@ -9026,7 +9038,7 @@ CopyAndTranslateBuffer( curByte = *src; if (curByte == '\n') { ResetFlag(statePtr, INPUT_SAW_CR); - } else if (statePtr->flags & INPUT_SAW_CR) { + } else if (GotFlag(statePtr, INPUT_SAW_CR)) { ResetFlag(statePtr, INPUT_SAW_CR); *dst = '\r'; dst++; @@ -9069,7 +9081,7 @@ CopyAndTranslateBuffer( *dst = '\n'; dst++; } else { - if ((curByte != '\n') || !(statePtr->flags & INPUT_SAW_CR)) { + if ((curByte != '\n') || !GotFlag(statePtr, INPUT_SAW_CR)) { *dst = (char) curByte; dst++; } @@ -9338,10 +9350,10 @@ DoWrite( */ outBufPtr->nextAdded += destCopied; - if (!(statePtr->flags & BUFFER_READY)) { + if (!GotFlag(statePtr, BUFFER_READY)) { if (IsBufferFull(outBufPtr)) { SetFlag(statePtr, BUFFER_READY); - } else if (statePtr->flags & CHANNEL_LINEBUFFERED) { + } else if (GotFlag(statePtr, CHANNEL_LINEBUFFERED)) { for (sPtr = src, i = 0, foundNewline = 0; (i < srcCopied) && (!foundNewline); i++, sPtr++) { @@ -9353,7 +9365,7 @@ DoWrite( if (foundNewline) { SetFlag(statePtr, BUFFER_READY); } - } else if (statePtr->flags & CHANNEL_UNBUFFERED) { + } else if (GotFlag(statePtr, CHANNEL_UNBUFFERED)) { SetFlag(statePtr, BUFFER_READY); } } @@ -9362,7 +9374,7 @@ DoWrite( src += srcCopied; srcLen -= srcCopied; - if (statePtr->flags & BUFFER_READY) { + if (GotFlag(statePtr, BUFFER_READY)) { if (FlushChannel(NULL, chanPtr, 0) != 0) { return -1; } @@ -9433,19 +9445,19 @@ StopCopy( * Restore the old blocking mode and output buffering mode. */ - nonBlocking = (csPtr->readFlags & CHANNEL_NONBLOCKING); + nonBlocking = csPtr->readFlags & CHANNEL_NONBLOCKING; if (nonBlocking != (inStatePtr->flags & CHANNEL_NONBLOCKING)) { SetBlockMode(NULL, csPtr->readPtr, nonBlocking ? TCL_MODE_NONBLOCKING : TCL_MODE_BLOCKING); } if (csPtr->readPtr != csPtr->writePtr) { - nonBlocking = (csPtr->writeFlags & CHANNEL_NONBLOCKING); + nonBlocking = csPtr->writeFlags & CHANNEL_NONBLOCKING; if (nonBlocking != (outStatePtr->flags & CHANNEL_NONBLOCKING)) { SetBlockMode(NULL, csPtr->writePtr, nonBlocking ? TCL_MODE_NONBLOCKING : TCL_MODE_BLOCKING); } } - outStatePtr->flags &= ~(CHANNEL_LINEBUFFERED | CHANNEL_UNBUFFERED); + ResetFlag(outStatePtr, CHANNEL_LINEBUFFERED | CHANNEL_UNBUFFERED); outStatePtr->flags |= csPtr->writeFlags & (CHANNEL_LINEBUFFERED | CHANNEL_UNBUFFERED); @@ -10635,8 +10647,9 @@ SetChannelFromAny( * The channel is valid until any call to DetachChannel occurs. * Ensure consistency checks are done. */ + statePtr = GET_CHANNELSTATE(objPtr); - if (statePtr->flags & (CHANNEL_TAINTED|CHANNEL_CLOSED)) { + if (GotFlag(statePtr, CHANNEL_TAINTED|CHANNEL_CLOSED)) { ResetFlag(statePtr, CHANNEL_TAINTED); Tcl_Release(statePtr); UpdateStringOfChannel(objPtr); @@ -10650,6 +10663,7 @@ SetChannelFromAny( * We need a valid string with which to check for a valid channel, but * make sure not to free internal rep until validated. [Bug 1847044] */ + if ((objPtr->typePtr != NULL) && (objPtr->bytes == NULL)) { objPtr->typePtr->updateStringProc(objPtr); } @@ -10693,8 +10707,10 @@ UpdateStringOfChannel( if (objPtr->bytes == NULL) { ChannelState *statePtr = GET_CHANNELSTATE(objPtr); const char *name = statePtr->channelName; + if (name) { size_t len = strlen(name); + objPtr->bytes = (char *) ckalloc(len + 1); objPtr->length = len; memcpy(objPtr->bytes, name, len); |