tcliogt.c
来自「tcl是工具命令语言」· C语言 代码 · 共 1,454 行 · 第 1/3 页
C
1,454 行
return (*parentWideSeekProc) (parentData, offset, mode, errorCodePtr); } /* * We're transferring to narrow seeks at this point; this is a bit * complex because we have to check whether the seek is possible * first (i.e. whether we are losing information in truncating the * bits of the offset.) Luckily, there's a defined error for what * happens when trying to go out of the representable range. */ if (offset<Tcl_LongAsWide(LONG_MIN) || offset>Tcl_LongAsWide(LONG_MAX)) { *errorCodePtr = EOVERFLOW; return Tcl_LongAsWide(-1); } return Tcl_LongAsWide((*parentSeekProc) (parentData, Tcl_WideAsLong(offset), mode, errorCodePtr));}/* *------------------------------------------------------* * * TransformSetOptionProc -- * * Called by generic layer to handle the reconfi- * guration of channel specific options. As this * channel type does not have such, it simply passes * all requests downstream. * * Sideeffects: * As defined by the channel downstream. * * Result: * A standard TCL error code. * *------------------------------------------------------* */static intTransformSetOptionProc (instanceData, interp, optionName, value) ClientData instanceData; Tcl_Interp *interp; CONST char *optionName; CONST char *value;{ TransformChannelData* dataPtr = (TransformChannelData*) instanceData; Tcl_Channel downChan = Tcl_GetStackedChannel(dataPtr->self); Tcl_DriverSetOptionProc *setOptionProc; setOptionProc = Tcl_ChannelSetOptionProc(Tcl_GetChannelType(downChan)); if (setOptionProc != NULL) { return (*setOptionProc)(Tcl_GetChannelInstanceData(downChan), interp, optionName, value); } return TCL_ERROR;}/* *------------------------------------------------------* * * TransformGetOptionProc -- * * Called by generic layer to handle requests for * the values of channel specific options. As this * channel type does not have such, it simply passes * all requests downstream. * * Sideeffects: * As defined by the channel downstream. * * Result: * A standard TCL error code. * *------------------------------------------------------* */static intTransformGetOptionProc (instanceData, interp, optionName, dsPtr) ClientData instanceData; Tcl_Interp* interp; CONST char* optionName; Tcl_DString* dsPtr;{ TransformChannelData* dataPtr = (TransformChannelData*) instanceData; Tcl_Channel downChan = Tcl_GetStackedChannel(dataPtr->self); Tcl_DriverGetOptionProc *getOptionProc; getOptionProc = Tcl_ChannelGetOptionProc(Tcl_GetChannelType(downChan)); if (getOptionProc != NULL) { return (*getOptionProc)(Tcl_GetChannelInstanceData(downChan), interp, optionName, dsPtr); } else if (optionName == (CONST char*) NULL) { /* * Request is query for all options, this is ok. */ return TCL_OK; } /* * Request for a specific option has to fail, we don't have any. */ return TCL_ERROR;}/* *------------------------------------------------------* * * TransformWatchProc -- * * Initialize the notifier to watch for events from * this channel. * * Sideeffects: * Sets up the notifier so that a future * event on the channel will be seen by Tcl. * * Result: * None. * *------------------------------------------------------* */ /* ARGSUSED */static voidTransformWatchProc (instanceData, mask) ClientData instanceData; /* Channel to watch */ int mask; /* Events of interest */{ /* The caller expressed interest in events occuring for this * channel. We are forwarding the call to the underlying * channel now. */ TransformChannelData* dataPtr = (TransformChannelData*) instanceData; Tcl_Channel downChan; dataPtr->watchMask = mask; /* No channel handlers any more. We will be notified automatically * about events on the channel below via a call to our * 'TransformNotifyProc'. But we have to pass the interest down now. * We are allowed to add additional 'interest' to the mask if we want * to. But this transformation has no such interest. It just passes * the request down, unchanged. */ downChan = Tcl_GetStackedChannel(dataPtr->self); (Tcl_GetChannelType(downChan)) ->watchProc(Tcl_GetChannelInstanceData(downChan), mask); /* * Management of the internal timer. */ if ((dataPtr->timer != (Tcl_TimerToken) NULL) && (!(mask & TCL_READABLE) || (ResultLength(&dataPtr->result) == 0))) { /* A pending timer exists, but either is there no (more) * interest in the events it generates or nothing is availablee * for reading, so remove it. */ Tcl_DeleteTimerHandler (dataPtr->timer); dataPtr->timer = (Tcl_TimerToken) NULL; } if ((dataPtr->timer == (Tcl_TimerToken) NULL) && (mask & TCL_READABLE) && (ResultLength (&dataPtr->result) > 0)) { /* There is no pending timer, but there is interest in readable * events and we actually have data waiting, so generate a timer * to flush that. */ dataPtr->timer = Tcl_CreateTimerHandler (FLUSH_DELAY, TransformChannelHandlerTimer, (ClientData) dataPtr); }}/* *------------------------------------------------------* * * TransformGetFileHandleProc -- * * Called from Tcl_GetChannelHandle to retrieve * OS specific file handle from inside this channel. * * Sideeffects: * None. * * Result: * The appropriate Tcl_File or NULL if not * present. * *------------------------------------------------------* */static intTransformGetFileHandleProc (instanceData, direction, handlePtr) ClientData instanceData; /* Channel to query */ int direction; /* Direction of interest */ ClientData* handlePtr; /* Place to store the handle into */{ /* * Return the handle belonging to parent channel. * IOW, pass the request down and the result up. */ TransformChannelData* dataPtr = (TransformChannelData*) instanceData; return Tcl_GetChannelHandle(Tcl_GetStackedChannel(dataPtr->self), direction, handlePtr);}/* *------------------------------------------------------* * * TransformNotifyProc -- * * ------------------------------------------------* * Handler called by Tcl to inform us of activity * on the underlying channel. * ------------------------------------------------* * * Sideeffects: * May process the incoming event by itself. * * Result: * None. * *------------------------------------------------------* */static intTransformNotifyProc (clientData, mask) ClientData clientData; /* The state of the notified transformation */ int mask; /* The mask of occuring events */{ TransformChannelData* dataPtr = (TransformChannelData*) clientData; /* * An event occured in the underlying channel. This * transformation doesn't process such events thus returns the * incoming mask unchanged. */ if (dataPtr->timer != (Tcl_TimerToken) NULL) { /* * Delete an existing timer. It was not fired, yet we are * here, so the channel below generated such an event and we * don't have to. The renewal of the interest after the * execution of channel handlers will eventually cause us to * recreate the timer (in TransformWatchProc). */ Tcl_DeleteTimerHandler (dataPtr->timer); dataPtr->timer = (Tcl_TimerToken) NULL; } return mask;}/* *------------------------------------------------------* * * TransformChannelHandlerTimer -- * * Called by the notifier (-> timer) to flush out * information waiting in the input buffer. * * Sideeffects: * As of 'Tcl_NotifyChannel'. * * Result: * None. * *------------------------------------------------------* */static voidTransformChannelHandlerTimer (clientData) ClientData clientData; /* Transformation to query */{ TransformChannelData* dataPtr = (TransformChannelData*) clientData; dataPtr->timer = (Tcl_TimerToken) NULL; if (!(dataPtr->watchMask & TCL_READABLE) || (ResultLength (&dataPtr->result) == 0)) { /* The timer fired, but either is there no (more) * interest in the events it generates or nothing is available * for reading, so ignore it and don't recreate it. */ return; } Tcl_NotifyChannel(dataPtr->self, TCL_READABLE);}/* *------------------------------------------------------* * * ResultClear -- * * Deallocates any memory allocated by 'ResultAdd'. * * Sideeffects: * See above. * * Result: * None. * *------------------------------------------------------* */static voidResultClear (r) ResultBuffer* r; /* Reference to the buffer to clear out */{ r->used = 0; if (r->allocated) { ckfree((char*) r->buf); r->buf = UCHARP (NULL); r->allocated = 0; }}/* *------------------------------------------------------* * * ResultInit -- * * Initializes the specified buffer structure. The * structure will contain valid information for an * emtpy buffer. * * Sideeffects: * See above. * * Result: * None. * *------------------------------------------------------* */static voidResultInit (r) ResultBuffer* r; /* Reference to the structure to initialize */{ r->used = 0; r->allocated = 0; r->buf = UCHARP (NULL);}/* *------------------------------------------------------* * * ResultLength -- * * Returns the number of bytes stored in the buffer. * * Sideeffects: * None. * * Result: * An integer, see above too. * *------------------------------------------------------* */static intResultLength (r) ResultBuffer* r; /* The structure to query */{ return r->used;}/* *------------------------------------------------------* * * ResultCopy -- * * Copies the requested number of bytes from the * buffer into the specified array and removes them * from the buffer afterward. Copies less if there * is not enough data in the buffer. * * Sideeffects: * See above. * * Result: * The number of actually copied bytes, * possibly less than 'toRead'. * *------------------------------------------------------* */static intResultCopy (r, buf, toRead) ResultBuffer* r; /* The buffer to read from */ unsigned char* buf; /* The buffer to copy into */ int toRead; /* Number of requested bytes */{ if (r->used == 0) { /* Nothing to copy in the case of an empty buffer. */ return 0; } if (r->used == toRead) { /* We have just enough. Copy everything to the caller. */ memcpy ((VOID*) buf, (VOID*) r->buf, (size_t) toRead); r->used = 0; return toRead; } if (r->used > toRead) { /* The internal buffer contains more than requested. * Copy the requested subset to the caller, and shift * the remaining bytes down. */ memcpy ((VOID*) buf, (VOID*) r->buf, (size_t) toRead); memmove ((VOID*) r->buf, (VOID*) (r->buf + toRead), (size_t) r->used - toRead); r->used -= toRead; return toRead; } /* There is not enough in the buffer to satisfy the caller, so * take everything. */ memcpy((VOID*) buf, (VOID*) r->buf, (size_t) r->used); toRead = r->used; r->used = 0; return toRead;}/* *------------------------------------------------------* * * ResultAdd -- * * Adds the bytes in the specified array to the * buffer, by appending it. * * Sideeffects: * See above. * * Result: * None. * *------------------------------------------------------* */static voidResultAdd (r, buf, toWrite) ResultBuffer* r; /* The buffer to extend */ unsigned char* buf; /* The buffer to read from */ int toWrite; /* The number of bytes in 'buf' */{ if ((r->used + toWrite) > r->allocated) { /* Extension of the internal buffer is required. */ if (r->allocated == 0) { r->allocated = toWrite + INCREMENT; r->buf = UCHARP (ckalloc((unsigned) r->allocated)); } else { r->allocated += toWrite + INCREMENT; r->buf = UCHARP (ckrealloc((char*) r->buf, (unsigned) r->allocated)); } } /* now copy data */ memcpy(r->buf + r->used, buf, (size_t) toWrite); r->used += toWrite;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?