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 + -
显示快捷键?