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

📄 tclio.c

📁 linux系统下的音频通信
💻 C
📖 第 1 页 / 共 5 页
字号:
/*  * tclIO.c -- * *	This file provides the generic portions (those that are the same on *	all platforms and for all channel types) of Tcl's IO facilities. * * Copyright (c) 1998 Scriptics Corporation * Copyright (c) 1995-1997 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * * SCCS: @(#) tclIO.c 1.3 98/06/27 18:10:15 */#include	"tclInt.h"#include	"tclPort.h"/* * Make sure that both EAGAIN and EWOULDBLOCK are defined. This does not * compile on systems where neither is defined. We want both defined so * that we can test safely for both. In the code we still have to test for * both because there may be systems on which both are defined and have * different values. */#if ((!defined(EWOULDBLOCK)) && (defined(EAGAIN)))#   define EWOULDBLOCK EAGAIN#endif#if ((!defined(EAGAIN)) && (defined(EWOULDBLOCK)))#   define EAGAIN EWOULDBLOCK#endif#if ((!defined(EAGAIN)) && (!defined(EWOULDBLOCK)))    error one of EWOULDBLOCK or EAGAIN must be defined#endif/* * The following structure encapsulates the state for a background channel * copy.  Note that the data buffer for the copy will be appended to this * structure. */typedef struct CopyState {    struct Channel *readPtr;	/* Pointer to input channel. */    struct Channel *writePtr;	/* Pointer to output channel. */    int readFlags;		/* Original read channel flags. */    int writeFlags;		/* Original write channel flags. */    int toRead;			/* Number of bytes to copy, or -1. */    int total;			/* Total bytes transferred (written). */    Tcl_Interp *interp;		/* Interp that started the copy. */    Tcl_Obj *cmdPtr;		/* Command to be invoked at completion. */    int bufSize;		/* Size of appended buffer. */    char buffer[1];		/* Copy buffer, this must be the last				 * field. */} CopyState;/* * struct ChannelBuffer: * * Buffers data being sent to or from a channel. */typedef struct ChannelBuffer {    int nextAdded;		/* The next position into which a character                                 * will be put in the buffer. */    int nextRemoved;		/* Position of next byte to be removed                                 * from the buffer. */    int bufSize;		/* How big is the buffer? */    struct ChannelBuffer *nextPtr;    				/* Next buffer in chain. */    char buf[4];		/* Placeholder for real buffer. The real                                 * buffer occuppies this space + bufSize-4                                 * bytes. This must be the last field in                                 * the structure. */} ChannelBuffer;#define CHANNELBUFFER_HEADER_SIZE	(sizeof(ChannelBuffer) - 4)/* * The following defines the *default* buffer size for channels. */#define CHANNELBUFFER_DEFAULT_SIZE	(1024 * 4)/* * Structure to record a close callback. One such record exists for * each close callback registered for a channel. */typedef struct CloseCallback {    Tcl_CloseProc *proc;		/* The procedure to call. */    ClientData clientData;		/* Arbitrary one-word data to pass                                         * to the callback. */    struct CloseCallback *nextPtr;	/* For chaining close callbacks. */} CloseCallback;/* * The following structure describes the information saved from a call to * "fileevent". This is used later when the event being waited for to * invoke the saved script in the interpreter designed in this record. */typedef struct EventScriptRecord {    struct Channel *chanPtr;	/* The channel for which this script is                                 * registered. This is used only when an                                 * error occurs during evaluation of the                                 * script, to delete the handler. */    char *script;		/* Script to invoke. */    Tcl_Interp *interp;		/* In what interpreter to invoke script? */    int mask;			/* Events must overlap current mask for the                                 * stored script to be invoked. */    struct EventScriptRecord *nextPtr;    				/* Next in chain of records. */} EventScriptRecord;/* * struct Channel: * * One of these structures is allocated for each open channel. It contains data * specific to the channel but which belongs to the generic part of the Tcl * channel mechanism, and it points at an instance specific (and type * specific) * instance data, and at a channel type structure. */typedef struct Channel {    char *channelName;		/* The name of the channel instance in Tcl                                 * commands. Storage is owned by the generic IO                                 * code,  is dynamically allocated. */    int	flags;			/* ORed combination of the flags defined                                 * below. */    Tcl_EolTranslation inputTranslation;				/* What translation to apply for end of line                                 * sequences on input? */        Tcl_EolTranslation outputTranslation;    				/* What translation to use for generating                                 * end of line sequences in output? */    int inEofChar;		/* If nonzero, use this as a signal of EOF                                 * on input. */    int outEofChar;             /* If nonzero, append this to the channel                                 * when it is closed if it is open for                                 * writing. */    int unreportedError;	/* Non-zero if an error report was deferred                                 * because it happened in the background. The                                 * value is the POSIX error code. */    ClientData instanceData;	/* Instance specific data. */    Tcl_ChannelType *typePtr;	/* Pointer to channel type structure. */    int refCount;		/* How many interpreters hold references to                                 * this IO channel? */    CloseCallback *closeCbPtr;	/* Callbacks registered to be called when the                                 * channel is closed. */    ChannelBuffer *curOutPtr;	/* Current output buffer being filled. */    ChannelBuffer *outQueueHead;/* Points at first buffer in output queue. */    ChannelBuffer *outQueueTail;/* Points at last buffer in output queue. */    ChannelBuffer *saveInBufPtr;/* Buffer saved for input queue - eliminates                                 * need to allocate a new buffer for "gets"                                 * that crosses buffer boundaries. */    ChannelBuffer *inQueueHead;	/* Points at first buffer in input queue. */    ChannelBuffer *inQueueTail;	/* Points at last buffer in input queue. */    struct ChannelHandler *chPtr;/* List of channel handlers registered                                  * for this channel. */    int interestMask;		/* Mask of all events this channel has                                 * handlers for. */    struct Channel *nextChanPtr;/* Next in list of channels currently open. */    EventScriptRecord *scriptRecordPtr;    				/* Chain of all scripts registered for                                 * event handlers ("fileevent") on this                                 * channel. */    int bufSize;		/* What size buffers to allocate? */    Tcl_TimerToken timer;	/* Handle to wakeup timer for this channel. */    CopyState *csPtr;		/* State of background copy, or NULL. */} Channel;    /* * Values for the flags field in Channel. Any ORed combination of the * following flags can be stored in the field. These flags record various * options and state bits about the channel. In addition to the flags below, * the channel can also have TCL_READABLE (1<<1) and TCL_WRITABLE (1<<2) set. */#define CHANNEL_NONBLOCKING	(1<<3)	/* Channel is currently in					 * nonblocking mode. */#define CHANNEL_LINEBUFFERED	(1<<4)	/* Output to the channel must be					 * flushed after every newline. */#define CHANNEL_UNBUFFERED	(1<<5)	/* Output to the channel must always					 * be flushed immediately. */#define BUFFER_READY		(1<<6)	/* Current output buffer (the					 * curOutPtr field in the                                         * channel structure) should be                                         * output as soon as possible even                                         * though it may not be full. */#define BG_FLUSH_SCHEDULED	(1<<7)	/* A background flush of the					 * queued output buffers has been                                         * scheduled. */#define CHANNEL_CLOSED		(1<<8)	/* Channel has been closed. No					 * further Tcl-level IO on the                                         * channel is allowed. */#define CHANNEL_EOF		(1<<9)	/* EOF occurred on this channel.					 * This bit is cleared before every                                         * input operation. */#define CHANNEL_STICKY_EOF	(1<<10)	/* EOF occurred on this channel because					 * we saw the input eofChar. This bit                                         * prevents clearing of the EOF bit                                         * before every input operation. */#define CHANNEL_BLOCKED	(1<<11)	/* EWOULDBLOCK or EAGAIN occurred					 * on this channel. This bit is                                         * cleared before every input or                                         * output operation. */#define INPUT_SAW_CR		(1<<12)	/* Channel is in CRLF eol input					 * translation mode and the last                                         * byte seen was a "\r". */#define CHANNEL_DEAD		(1<<13)	/* The channel has been closed by					 * the exit handler (on exit) but                                         * not deallocated. When any IO                                         * operation sees this flag on a                                         * channel, it does not call driver                                         * level functions to avoid referring                                         * to deallocated data. */#define CHANNEL_GETS_BLOCKED	(1<<14)	/* The last input operation was a gets					 * that failed to get a comlete line.					 * When set, file events will not be					 * delivered for buffered data unless					 * an EOL is present. *//* * For each channel handler registered in a call to Tcl_CreateChannelHandler, * there is one record of the following type. All of records for a specific * channel are chained together in a singly linked list which is stored in * the channel structure. */typedef struct ChannelHandler {    Channel *chanPtr;		/* The channel structure for this channel. */    int mask;			/* Mask of desired events. */    Tcl_ChannelProc *proc;	/* Procedure to call in the type of                                 * Tcl_CreateChannelHandler. */    ClientData clientData;	/* Argument to pass to procedure. */    struct ChannelHandler *nextPtr;    				/* Next one in list of registered handlers. */} ChannelHandler;/* * This structure keeps track of the current ChannelHandler being invoked in * the current invocation of ChannelHandlerEventProc. There is a potential * problem if a ChannelHandler is deleted while it is the current one, since * ChannelHandlerEventProc needs to look at the nextPtr field. To handle this * problem, structures of the type below indicate the next handler to be * processed for any (recursively nested) dispatches in progress. The * nextHandlerPtr field is updated if the handler being pointed to is deleted. * The nextPtr field is used to chain together all recursive invocations, so * that Tcl_DeleteChannelHandler can find all the recursively nested * invocations of ChannelHandlerEventProc and compare the handler being * deleted against the NEXT handler to be invoked in that invocation; when it * finds such a situation, Tcl_DeleteChannelHandler updates the nextHandlerPtr * field of the structure to the next handler. */typedef struct NextChannelHandler {    ChannelHandler *nextHandlerPtr;	/* The next handler to be invoked in                                         * this invocation. */    struct NextChannelHandler *nestedHandlerPtr;					/* Next nested invocation of                                         * ChannelHandlerEventProc. */} NextChannelHandler;/* * This variable holds the list of nested ChannelHandlerEventProc invocations. */static NextChannelHandler *nestedHandlerPtr = (NextChannelHandler *) NULL;/* * List of all channels currently open. */static Channel *firstChanPtr = (Channel *) NULL;/* * Has a channel exit handler been created yet? */static int channelExitHandlerCreated = 0;/* * The following structure describes the event that is added to the Tcl * event queue by the channel handler check procedure. */typedef struct ChannelHandlerEvent {    Tcl_Event header;		/* Standard header for all events. */    Channel *chanPtr;		/* The channel that is ready. */    int readyMask;		/* Events that have occurred. */} ChannelHandlerEvent;/* * Static variables to hold channels for stdin, stdout and stderr. */static Tcl_Channel stdinChannel = NULL;static int stdinInitialized = 0;static Tcl_Channel stdoutChannel = NULL;static int stdoutInitialized = 0;static Tcl_Channel stderrChannel = NULL;static int stderrInitialized = 0;/* * Static functions in this file: */static void		ChannelEventScriptInvoker _ANSI_ARGS_((			    ClientData clientData, int flags));static void		ChannelTimerProc _ANSI_ARGS_((			    ClientData clientData));static void		CheckForStdChannelsBeingClosed _ANSI_ARGS_((			    Tcl_Channel chan));static void		CleanupChannelHandlers _ANSI_ARGS_((			    Tcl_Interp *interp, Channel *chanPtr));static int		CloseChannel _ANSI_ARGS_((Tcl_Interp *interp,                            Channel *chanPtr, int errorCode));static void		CloseChannelsOnExit _ANSI_ARGS_((ClientData data));static int		CopyAndTranslateBuffer _ANSI_ARGS_((			    Channel *chanPtr, char *result, int space));static int		CopyData _ANSI_ARGS_((CopyState *csPtr, int mask));static void		CopyEventProc _ANSI_ARGS_((ClientData clientData,			    int mask));static void		CreateScriptRecord _ANSI_ARGS_((			    Tcl_Interp *interp, Channel *chanPtr,                            int mask, char *script));static void		DeleteChannelTable _ANSI_ARGS_((			    ClientData clientData, Tcl_Interp *interp));static void		DeleteScriptRecord _ANSI_ARGS_((Tcl_Interp *interp,        		    Channel *chanPtr, int mask));static void		DiscardInputQueued _ANSI_ARGS_((			    Channel *chanPtr, int discardSavedBuffers));static void		DiscardOutputQueued _ANSI_ARGS_((    			    Channel *chanPtr));static int		DoRead _ANSI_ARGS_((Channel *chanPtr, char *srcPtr,			    int slen));static int		DoWrite _ANSI_ARGS_((Channel *chanPtr, char *srcPtr,			    int slen));static int		FlushChannel _ANSI_ARGS_((Tcl_Interp *interp,                            Channel *chanPtr, int calledFromAsyncFlush));static Tcl_HashTable	*GetChannelTable _ANSI_ARGS_((Tcl_Interp *interp));static int		GetEOL _ANSI_ARGS_((Channel *chanPtr));static int		GetInput _ANSI_ARGS_((Channel *chanPtr));static void		RecycleBuffer _ANSI_ARGS_((Channel *chanPtr,		            ChannelBuffer *bufPtr, int mustDiscard));static int		ScanBufferForEOL _ANSI_ARGS_((Channel *chanPtr,                            ChannelBuffer *bufPtr,                            Tcl_EolTranslation translation, int eofChar,		            int *bytesToEOLPtr, int *crSeenPtr));static int		ScanInputForEOL _ANSI_ARGS_((Channel *chanPtr,		            int *bytesQueuedPtr));static int		SetBlockMode _ANSI_ARGS_((Tcl_Interp *interp,		            Channel *chanPtr, int mode));static void		StopCopy _ANSI_ARGS_((CopyState *csPtr));static void		UpdateInterest _ANSI_ARGS_((Channel *chanPtr));static int		CheckForDeadChannel _ANSI_ARGS_((Tcl_Interp *interp,							Channel *chan));/* *---------------------------------------------------------------------- * * SetBlockMode -- * *	This function sets the blocking mode for a channel and updates *	the state flags. * * Results: *	A standard Tcl result. * * Side effects: *	Modifies the blocking mode of the channel and possibly generates *	an error. * *---------------------------------------------------------------------- */static intSetBlockMode(interp, chanPtr, mode)    Tcl_Interp *interp;		/* Interp for error reporting. */    Channel *chanPtr;		/* Channel to modify. */    int mode;			/* One of TCL_MODE_BLOCKING or				 * TCL_MODE_NONBLOCKING. */{    int result = 0;    if (chanPtr->typePtr->blockModeProc != NULL) {	result = (chanPtr->typePtr->blockModeProc) (chanPtr->instanceData,		mode);    }    if (result != 0) {	Tcl_SetErrno(result);	if (interp != (Tcl_Interp *) NULL) {	    Tcl_AppendResult(interp, "error setting blocking mode: ",		    Tcl_PosixError(interp), (char *) NULL);	}	return TCL_ERROR;    }    if (mode == TCL_MODE_BLOCKING) {	chanPtr->flags &= (~(CHANNEL_NONBLOCKING | BG_FLUSH_SCHEDULED));    } else {	chanPtr->flags |= CHANNEL_NONBLOCKING;    }    return TCL_OK;

⌨️ 快捷键说明

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