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

📄 tclwinconsole.c

📁 这是leon3处理器的交叉编译链
💻 C
📖 第 1 页 / 共 3 页
字号:
/*  * tclWinConsole.c -- * *	This file implements the Windows-specific console functions, *	and the "console" channel driver. * * Copyright (c) 1999 by Scriptics Corp. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * * RCS: @(#) $Id: tclWinConsole.c,v 1.8 2002/09/02 19:27:02 hobbs Exp $ */#include "tclWinInt.h"#include <fcntl.h>#include <io.h>#include <sys/stat.h>/* * The following variable is used to tell whether this module has been * initialized. */static int initialized = 0;/* * The consoleMutex locks around access to the initialized variable, and it is * used to protect background threads from being terminated while they are * using APIs that hold locks. */TCL_DECLARE_MUTEX(consoleMutex)/* * Bit masks used in the flags field of the ConsoleInfo structure below. */#define CONSOLE_PENDING	(1<<0)	/* Message is pending in the queue. */#define CONSOLE_ASYNC	(1<<1)	/* Channel is non-blocking. *//* * Bit masks used in the sharedFlags field of the ConsoleInfo structure below. */#define CONSOLE_EOF	  (1<<2)  /* Console has reached EOF. */#define CONSOLE_BUFFERED  (1<<3)  /* data was read into a buffer by the reader				     thread */#define CONSOLE_BUFFER_SIZE (8*1024)/* * This structure describes per-instance data for a console based channel. */typedef struct ConsoleInfo {    HANDLE handle;    int type;    struct ConsoleInfo *nextPtr;/* Pointer to next registered console. */    Tcl_Channel channel;	/* Pointer to channel structure. */    int validMask;		/* OR'ed combination of TCL_READABLE,				 * TCL_WRITABLE, or TCL_EXCEPTION: indicates				 * which operations are valid on the file. */    int watchMask;		/* OR'ed combination of TCL_READABLE,				 * TCL_WRITABLE, or TCL_EXCEPTION: indicates				 * which events should be reported. */    int flags;			/* State flags, see above for a list. */    Tcl_ThreadId threadId;	/* Thread to which events should be reported.				 * This value is used by the reader/writer				 * threads. */    HANDLE writeThread;		/* Handle to writer thread. */    HANDLE readThread;		/* Handle to reader thread. */    HANDLE writable;		/* Manual-reset event to signal when the				 * writer thread has finished waiting for				 * the current buffer to be written. */    HANDLE readable;		/* Manual-reset event to signal when the				 * reader thread has finished waiting for				 * input. */    HANDLE startWriter;		/* Auto-reset event used by the main thread to				 * signal when the writer thread should attempt				 * to write to the console. */    HANDLE startReader;		/* Auto-reset event used by the main thread to				 * signal when the reader thread should attempt				 * to read from the console. */    DWORD writeError;		/* An error caused by the last background				 * write.  Set to 0 if no error has been				 * detected.  This word is shared with the				 * writer thread so access must be				 * synchronized with the writable object.				 */    char *writeBuf;		/* Current background output buffer.				 * Access is synchronized with the writable				 * object. */    int writeBufLen;		/* Size of write buffer.  Access is				 * synchronized with the writable				 * object. */    int toWrite;		/* Current amount to be written.  Access is				 * synchronized with the writable object. */    int readFlags;		/* Flags that are shared with the reader				 * thread.  Access is synchronized with the				 * readable object.  */    int bytesRead;              /* number of bytes in the buffer */    int offset;                 /* number of bytes read out of the buffer */    char buffer[CONSOLE_BUFFER_SIZE];                                /* Data consumed by reader thread. */} ConsoleInfo;typedef struct ThreadSpecificData {    /*     * The following pointer refers to the head of the list of consoles     * that are being watched for file events.     */        ConsoleInfo *firstConsolePtr;} ThreadSpecificData;static Tcl_ThreadDataKey dataKey;/* * The following structure is what is added to the Tcl event queue when * console events are generated. */typedef struct ConsoleEvent {    Tcl_Event header;		/* Information that is standard for				 * all events. */    ConsoleInfo *infoPtr;	/* Pointer to console info structure.  Note				 * that we still have to verify that the				 * console exists before dereferencing this				 * pointer. */} ConsoleEvent;/* * Declarations for functions used only in this file. */static int		ConsoleBlockModeProc(ClientData instanceData, int mode);static void		ConsoleCheckProc(ClientData clientData, int flags);static int		ConsoleCloseProc(ClientData instanceData,			    Tcl_Interp *interp);static int		ConsoleEventProc(Tcl_Event *evPtr, int flags);static void		ConsoleExitHandler(ClientData clientData);static int		ConsoleGetHandleProc(ClientData instanceData,			    int direction, ClientData *handlePtr);static ThreadSpecificData *ConsoleInit(void);static int		ConsoleInputProc(ClientData instanceData, char *buf,			    int toRead, int *errorCode);static int		ConsoleOutputProc(ClientData instanceData,			    CONST char *buf, int toWrite, int *errorCode);static DWORD WINAPI	ConsoleReaderThread(LPVOID arg);static void		ConsoleSetupProc(ClientData clientData, int flags);static void		ConsoleWatchProc(ClientData instanceData, int mask);static DWORD WINAPI	ConsoleWriterThread(LPVOID arg);static void		ProcExitHandler(ClientData clientData);static int		WaitForRead(ConsoleInfo *infoPtr, int blocking);/* * This structure describes the channel type structure for command console * based IO. */static Tcl_ChannelType consoleChannelType = {    "console",			/* Type name. */    TCL_CHANNEL_VERSION_2,	/* v2 channel */    ConsoleCloseProc,		/* Close proc. */    ConsoleInputProc,		/* Input proc. */    ConsoleOutputProc,		/* Output proc. */    NULL,			/* Seek proc. */    NULL,			/* Set option proc. */    NULL,			/* Get option proc. */    ConsoleWatchProc,		/* Set up notifier to watch the channel. */    ConsoleGetHandleProc,	/* Get an OS handle from channel. */    NULL,			/* close2proc. */    ConsoleBlockModeProc,	/* Set blocking or non-blocking mode.*/    NULL,			/* flush proc. */    NULL,			/* handler proc. */};/* *---------------------------------------------------------------------- * * ConsoleInit -- * *	This function initializes the static variables for this file. * * Results: *	None. * * Side effects: *	Creates a new event source. * *---------------------------------------------------------------------- */static ThreadSpecificData *ConsoleInit(){    ThreadSpecificData *tsdPtr;    /*     * Check the initialized flag first, then check again in the mutex.     * This is a speed enhancement.     */    if (!initialized) {	Tcl_MutexLock(&consoleMutex);	if (!initialized) {	    initialized = 1;	    Tcl_CreateExitHandler(ProcExitHandler, NULL);	}	Tcl_MutexUnlock(&consoleMutex);    }    tsdPtr = (ThreadSpecificData *)TclThreadDataKeyGet(&dataKey);    if (tsdPtr == NULL) {	tsdPtr = TCL_TSD_INIT(&dataKey);	tsdPtr->firstConsolePtr = NULL;	Tcl_CreateEventSource(ConsoleSetupProc, ConsoleCheckProc, NULL);	Tcl_CreateThreadExitHandler(ConsoleExitHandler, NULL);    }    return tsdPtr;}/* *---------------------------------------------------------------------- * * ConsoleExitHandler -- * *	This function is called to cleanup the console module before *	Tcl is unloaded. * * Results: *	None. * * Side effects: *	Removes the console event source. * *---------------------------------------------------------------------- */static voidConsoleExitHandler(    ClientData clientData)	/* Old window proc */{    Tcl_DeleteEventSource(ConsoleSetupProc, ConsoleCheckProc, NULL);}/* *---------------------------------------------------------------------- * * ProcExitHandler -- * *	This function is called to cleanup the process list before *	Tcl is unloaded. * * Results: *	None. * * Side effects: *	Resets the process list. * *---------------------------------------------------------------------- */static voidProcExitHandler(    ClientData clientData)	/* Old window proc */{    Tcl_MutexLock(&consoleMutex);    initialized = 0;    Tcl_MutexUnlock(&consoleMutex);}/* *---------------------------------------------------------------------- * * ConsoleSetupProc -- * *	This procedure is invoked before Tcl_DoOneEvent blocks waiting *	for an event. * * Results: *	None. * * Side effects: *	Adjusts the block time if needed. * *---------------------------------------------------------------------- */voidConsoleSetupProc(    ClientData data,		/* Not used. */    int flags)			/* Event flags as passed to Tcl_DoOneEvent. */{    ConsoleInfo *infoPtr;    Tcl_Time blockTime = { 0, 0 };    int block = 1;    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);    if (!(flags & TCL_FILE_EVENTS)) {	return;    }        /*     * Look to see if any events are already pending.  If they are, poll.     */    for (infoPtr = tsdPtr->firstConsolePtr; infoPtr != NULL; 	    infoPtr = infoPtr->nextPtr) {	if (infoPtr->watchMask & TCL_WRITABLE) {	    if (WaitForSingleObject(infoPtr->writable, 0) != WAIT_TIMEOUT) {		block = 0;	    }	}	if (infoPtr->watchMask & TCL_READABLE) {	    if (WaitForRead(infoPtr, 0) >= 0) {		block = 0;	    }	}    }    if (!block) {	Tcl_SetMaxBlockTime(&blockTime);    }}/* *---------------------------------------------------------------------- * * ConsoleCheckProc -- * *	This procedure is called by Tcl_DoOneEvent to check the console *	event source for events.  * * Results: *	None. * * Side effects: *	May queue an event. * *---------------------------------------------------------------------- */static voidConsoleCheckProc(    ClientData data,		/* Not used. */    int flags)			/* Event flags as passed to Tcl_DoOneEvent. */{    ConsoleInfo *infoPtr;    ConsoleEvent *evPtr;    int needEvent;    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);    if (!(flags & TCL_FILE_EVENTS)) {	return;    }        /*     * Queue events for any ready consoles that don't already have events     * queued.     */    for (infoPtr = tsdPtr->firstConsolePtr; infoPtr != NULL; 	    infoPtr = infoPtr->nextPtr) {	if (infoPtr->flags & CONSOLE_PENDING) {	    continue;	}		/*	 * Queue an event if the console is signaled for reading or writing.	 */	needEvent = 0;	if (infoPtr->watchMask & TCL_WRITABLE) {	    if (WaitForSingleObject(infoPtr->writable, 0) != WAIT_TIMEOUT) {		needEvent = 1;	    }	}		if (infoPtr->watchMask & TCL_READABLE) {	    if (WaitForRead(infoPtr, 0) >= 0) {		needEvent = 1;	    }	}	if (needEvent) {	    infoPtr->flags |= CONSOLE_PENDING;	    evPtr = (ConsoleEvent *) ckalloc(sizeof(ConsoleEvent));	    evPtr->header.proc = ConsoleEventProc;	    evPtr->infoPtr = infoPtr;	    Tcl_QueueEvent((Tcl_Event *) evPtr, TCL_QUEUE_TAIL);	}    }}/* *---------------------------------------------------------------------- * * ConsoleBlockModeProc -- * *	Set blocking or non-blocking mode on channel. * * Results: *	0 if successful, errno when failed. * * Side effects: *	Sets the device into blocking or non-blocking mode. * *---------------------------------------------------------------------- */static intConsoleBlockModeProc(    ClientData instanceData,	/* Instance data for channel. */    int mode)			/* TCL_MODE_BLOCKING or                                 * TCL_MODE_NONBLOCKING. */{    ConsoleInfo *infoPtr = (ConsoleInfo *) instanceData;        /*     * Consoles on Windows can not be switched between blocking and nonblocking,     * hence we have to emulate the behavior. This is done in the input     * function by checking against a bit in the state. We set or unset the     * bit here to cause the input function to emulate the correct behavior.

⌨️ 快捷键说明

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