⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tclio.c

📁 linux系统下的音频通信
💻 C
📖 第 1 页 / 共 5 页
字号:
 *	output on closed channels. Removes any channeEvent handlers that were *	registered in this interpreter. * *---------------------------------------------------------------------- */static voidDeleteChannelTable(clientData, interp)    ClientData clientData;	/* The per-interpreter data structure. */    Tcl_Interp *interp;		/* The interpreter being deleted. */{    Tcl_HashTable *hTblPtr;	/* The hash table. */    Tcl_HashSearch hSearch;	/* Search variable. */    Tcl_HashEntry *hPtr;	/* Search variable. */    Channel *chanPtr;	/* Channel being deleted. */    EventScriptRecord *sPtr, *prevPtr, *nextPtr;    				/* Variables to loop over all channel events                                 * registered, to delete the ones that refer                                 * to the interpreter being deleted. */        /*     * Delete all the registered channels - this will close channels whose     * refcount reaches zero.     */        hTblPtr = (Tcl_HashTable *) clientData;    for (hPtr = Tcl_FirstHashEntry(hTblPtr, &hSearch);             hPtr != (Tcl_HashEntry *) NULL;             hPtr = Tcl_FirstHashEntry(hTblPtr, &hSearch)) {        chanPtr = (Channel *) Tcl_GetHashValue(hPtr);        /*         * Remove any fileevents registered in this interpreter.         */                for (sPtr = chanPtr->scriptRecordPtr,                 prevPtr = (EventScriptRecord *) NULL;                 sPtr != (EventScriptRecord *) NULL;                 sPtr = nextPtr) {            nextPtr = sPtr->nextPtr;            if (sPtr->interp == interp) {                if (prevPtr == (EventScriptRecord *) NULL) {                    chanPtr->scriptRecordPtr = nextPtr;                } else {                    prevPtr->nextPtr = nextPtr;                }                Tcl_DeleteChannelHandler((Tcl_Channel) chanPtr,                        ChannelEventScriptInvoker, (ClientData) sPtr);		ckfree(sPtr->script);                ckfree((char *) sPtr);            } else {                prevPtr = sPtr;            }        }        /*         * Cannot call Tcl_UnregisterChannel because that procedure calls         * Tcl_GetAssocData to get the channel table, which might already         * be inaccessible from the interpreter structure. Instead, we         * emulate the behavior of Tcl_UnregisterChannel directly here.         */        Tcl_DeleteHashEntry(hPtr);        chanPtr->refCount--;        if (chanPtr->refCount <= 0) {            if (!(chanPtr->flags & BG_FLUSH_SCHEDULED)) {                (void) Tcl_Close(interp, (Tcl_Channel) chanPtr);            }        }    }    Tcl_DeleteHashTable(hTblPtr);    ckfree((char *) hTblPtr);}/* *---------------------------------------------------------------------- * * CheckForStdChannelsBeingClosed -- * *	Perform special handling for standard channels being closed. When *	given a standard channel, if the refcount is now 1, it means that *	the last reference to the standard channel is being explicitly *	closed. Now bump the refcount artificially down to 0, to ensure the *	normal handling of channels being closed will occur. Also reset the *	static pointer to the channel to NULL, to avoid dangling references. * * Results: *	None. * * Side effects: *	Manipulates the refcount on standard channels. May smash the global *	static pointer to a standard channel. * *---------------------------------------------------------------------- */static voidCheckForStdChannelsBeingClosed(chan)    Tcl_Channel chan;{    Channel *chanPtr = (Channel *) chan;        if ((chan == stdinChannel) && (stdinInitialized)) {        if (chanPtr->refCount < 2) {            chanPtr->refCount = 0;            stdinChannel = NULL;            return;        }    } else if ((chan == stdoutChannel) && (stdoutInitialized)) {        if (chanPtr->refCount < 2) {            chanPtr->refCount = 0;            stdoutChannel = NULL;            return;        }    } else if ((chan == stderrChannel) && (stderrInitialized)) {        if (chanPtr->refCount < 2) {            chanPtr->refCount = 0;            stderrChannel = NULL;            return;        }    }}/* *---------------------------------------------------------------------- * * Tcl_UnregisterChannel -- * *	Deletes the hash entry for a channel associated with an interpreter. *	If the interpreter given as argument is NULL, it only decrements the *	reference count. * * Results: *	A standard Tcl result. * * Side effects: *	Deletes the hash entry for a channel associated with an interpreter. * *---------------------------------------------------------------------- */intTcl_UnregisterChannel(interp, chan)    Tcl_Interp *interp;		/* Interpreter in which channel is defined. */    Tcl_Channel chan;		/* Channel to delete. */{    Tcl_HashTable *hTblPtr;	/* Hash table of channels. */    Tcl_HashEntry *hPtr;	/* Search variable. */    Channel *chanPtr;		/* The real IO channel. */    chanPtr = (Channel *) chan;        if (interp != (Tcl_Interp *) NULL) {        hTblPtr = (Tcl_HashTable *) Tcl_GetAssocData(interp, "tclIO", NULL);        if (hTblPtr == (Tcl_HashTable *) NULL) {            return TCL_OK;        }        hPtr = Tcl_FindHashEntry(hTblPtr, chanPtr->channelName);        if (hPtr == (Tcl_HashEntry *) NULL) {            return TCL_OK;        }        if ((Channel *) Tcl_GetHashValue(hPtr) != chanPtr) {            return TCL_OK;        }        Tcl_DeleteHashEntry(hPtr);        /*         * Remove channel handlers that refer to this interpreter, so that they         * will not be present if the actual close is delayed and more events         * happen on the channel. This may occur if the channel is shared         * between several interpreters, or if the channel has async         * flushing active.         */            CleanupChannelHandlers(interp, chanPtr);    }    chanPtr->refCount--;        /*     * Perform special handling for standard channels being closed. If the     * refCount is now 1 it means that the last reference to the standard     * channel is being explicitly closed, so bump the refCount down     * artificially to 0. This will ensure that the channel is actually     * closed, below. Also set the static pointer to NULL for the channel.     */    CheckForStdChannelsBeingClosed(chan);    /*     * If the refCount reached zero, close the actual channel.     */    if (chanPtr->refCount <= 0) {        /*         * Ensure that if there is another buffer, it gets flushed         * whether or not we are doing a background flush.         */        if ((chanPtr->curOutPtr != NULL) &&                (chanPtr->curOutPtr->nextAdded >                        chanPtr->curOutPtr->nextRemoved)) {            chanPtr->flags |= BUFFER_READY;        }        chanPtr->flags |= CHANNEL_CLOSED;        if (!(chanPtr->flags & BG_FLUSH_SCHEDULED)) {            if (Tcl_Close(interp, chan) != TCL_OK) {                return TCL_ERROR;            }        }    }    return TCL_OK;}/* *---------------------------------------------------------------------- * * Tcl_RegisterChannel -- * *	Adds an already-open channel to the channel table of an interpreter. *	If the interpreter passed as argument is NULL, it only increments *	the channel refCount. * * Results: *	None. * * Side effects: *	May increment the reference count of a channel. * *---------------------------------------------------------------------- */voidTcl_RegisterChannel(interp, chan)    Tcl_Interp *interp;		/* Interpreter in which to add the channel. */    Tcl_Channel chan;		/* The channel to add to this interpreter                                 * channel table. */{    Tcl_HashTable *hTblPtr;	/* Hash table of channels. */    Tcl_HashEntry *hPtr;	/* Search variable. */    int new;			/* Is the hash entry new or does it exist? */    Channel *chanPtr;		/* The actual channel. */    chanPtr = (Channel *) chan;    if (chanPtr->channelName == (char *) NULL) {        panic("Tcl_RegisterChannel: channel without name");    }    if (interp != (Tcl_Interp *) NULL) {        hTblPtr = GetChannelTable(interp);        hPtr = Tcl_CreateHashEntry(hTblPtr, chanPtr->channelName, &new);        if (new == 0) {            if (chan == (Tcl_Channel) Tcl_GetHashValue(hPtr)) {                return;            }            panic("Tcl_RegisterChannel: duplicate channel names");        }        Tcl_SetHashValue(hPtr, (ClientData) chanPtr);    }    chanPtr->refCount++;}/* *---------------------------------------------------------------------- * * Tcl_GetChannel -- * *	Finds an existing Tcl_Channel structure by name in a given *	interpreter. This function is public because it is used by *	channel-type-specific functions. * * Results: *	A Tcl_Channel or NULL on failure. If failed, interp->result *	contains an error message. It also returns, in modePtr, the *	modes in which the channel is opened. * * Side effects: *	None. * *---------------------------------------------------------------------- */Tcl_ChannelTcl_GetChannel(interp, chanName, modePtr)    Tcl_Interp *interp;		/* Interpreter in which to find or create                                 * the channel. */    char *chanName;		/* The name of the channel. */    int *modePtr;		/* Where to store the mode in which the                                 * channel was opened? Will contain an ORed                                 * combination of TCL_READABLE and                                 * TCL_WRITABLE, if non-NULL. */{    Channel *chanPtr;		/* The actual channel. */    Tcl_HashTable *hTblPtr;	/* Hash table of channels. */    Tcl_HashEntry *hPtr;	/* Search variable. */    char *name;			/* Translated name. */    /*     * Substitute "stdin", etc.  Note that even though we immediately     * find the channel using Tcl_GetStdChannel, we still need to look     * it up in the specified interpreter to ensure that it is present     * in the channel table.  Otherwise, safe interpreters would always     * have access to the standard channels.     */    name = chanName;    if ((chanName[0] == 's') && (chanName[1] == 't')) {	chanPtr = NULL;	if (strcmp(chanName, "stdin") == 0) {	    chanPtr = (Channel *)Tcl_GetStdChannel(TCL_STDIN);	} else if (strcmp(chanName, "stdout") == 0) {	    chanPtr = (Channel *)Tcl_GetStdChannel(TCL_STDOUT);	} else if (strcmp(chanName, "stderr") == 0) {	    chanPtr = (Channel *)Tcl_GetStdChannel(TCL_STDERR);	}	if (chanPtr != NULL) {	    name = chanPtr->channelName;	}    }        hTblPtr = GetChannelTable(interp);    hPtr = Tcl_FindHashEntry(hTblPtr, name);    if (hPtr == (Tcl_HashEntry *) NULL) {        Tcl_AppendResult(interp, "can not find channel named \"",                chanName, "\"", (char *) NULL);        return NULL;    }    chanPtr = (Channel *) Tcl_GetHashValue(hPtr);    if (modePtr != NULL) {        *modePtr = (chanPtr->flags & (TCL_READABLE|TCL_WRITABLE));    }        return (Tcl_Channel) chanPtr;}/* *---------------------------------------------------------------------- * * Tcl_CreateChannel -- * *	Creates a new entry in the hash table for a Tcl_Channel *	record. * * Results: *	Returns the new Tcl_Channel. * * Side effects: *	Creates a new Tcl_Channel instance and inserts it into the *	hash table. * *---------------------------------------------------------------------- */Tcl_ChannelTcl_CreateChannel(typePtr, chanName, instanceData, mask)    Tcl_ChannelType *typePtr;	/* The channel type record. */    char *chanName;		/* Name of channel to record. */    ClientData instanceData;	/* Instance specific data. */    int mask;			/* TCL_READABLE & TCL_WRITABLE to indicate                                 * if the channel is readable, writable. */{    Channel *chanPtr;		/* The channel structure newly created. */    chanPtr = (Channel *) ckalloc((unsigned) sizeof(Channel));        if (chanName != (char *) NULL) {        chanPtr->channelName = ckalloc((unsigned) (strlen(chanName) + 1));        strcpy(chanPtr->channelName, chanName);    } else {        panic("Tcl_CreateChannel: NULL channel name");    }    chanPtr->flags = mask;    /*     * Set the channel up initially in AUTO input translation mode to     * accept "\n", "\r" and "\r\n". Output translation mode is set to     * a platform specific default value. The eofChar is set to 0 for both     * input and output, so that Tcl does not look for an in-file EOF     * indicator (e.g. ^Z) and does not append an EOF indicator to files.     */    chanPtr->inputTranslation = TCL_TRANSLATE_AUTO;    chanPtr->outputTranslation = TCL_PLATFORM_TRANSLATION;    chanPtr->inEofChar = 0;    chanPtr->outEofChar = 0;    chanPtr->unreportedError = 0;    chanPtr->instanceData = instanceData;    chanPtr->typePtr = typePtr;    chanPtr->refCount = 0;    chanPtr->closeCbPtr = (CloseCallback *) NULL;    chanPtr->curOutPtr = (ChannelBuffer *) NULL;    chanPtr->outQueueHead = (ChannelBuffer *) NULL;    chanPtr->outQueueTail = (ChannelBuffer *) NULL;    chanPtr->saveInBufPtr = (ChannelBuffer *) NULL;    chanPtr->inQueueHead = (ChannelBuffer *) NULL;    chanPtr->inQueueTail = (ChannelBuffer *) NULL;    chanPtr->chPtr = (ChannelHandler *) NULL;    chanPtr->interestMask = 0;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -