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

📄 tclwinconsole.c

📁 这是leon3处理器的交叉编译链
💻 C
📖 第 1 页 / 共 3 页
字号:
 *---------------------------------------------------------------------- * * ConsoleWatchProc -- * *	Called by the notifier to set up to watch for events on this *	channel. * * Results: *	None. * * Side effects: *	None. * *---------------------------------------------------------------------- */static voidConsoleWatchProc(    ClientData instanceData,		/* Console state. */    int mask)				/* What events to watch for, OR-ed                                         * combination of TCL_READABLE,                                         * TCL_WRITABLE and TCL_EXCEPTION. */{    ConsoleInfo **nextPtrPtr, *ptr;    ConsoleInfo *infoPtr = (ConsoleInfo *) instanceData;    int oldMask = infoPtr->watchMask;    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);    /*     * Since most of the work is handled by the background threads,     * we just need to update the watchMask and then force the notifier     * to poll once.      */    infoPtr->watchMask = mask & infoPtr->validMask;    if (infoPtr->watchMask) {	Tcl_Time blockTime = { 0, 0 };	if (!oldMask) {	    infoPtr->nextPtr = tsdPtr->firstConsolePtr;	    tsdPtr->firstConsolePtr = infoPtr;	}	Tcl_SetMaxBlockTime(&blockTime);    } else {	if (oldMask) {	    /*	     * Remove the console from the list of watched consoles.	     */	    for (nextPtrPtr = &(tsdPtr->firstConsolePtr), ptr = *nextPtrPtr;		 ptr != NULL;		 nextPtrPtr = &ptr->nextPtr, ptr = *nextPtrPtr) {		if (infoPtr == ptr) {		    *nextPtrPtr = ptr->nextPtr;		    break;		}	    }	}    }}/* *---------------------------------------------------------------------- * * ConsoleGetHandleProc -- * *	Called from Tcl_GetChannelHandle to retrieve OS handles from *	inside a command consoleline based channel. * * Results: *	Returns TCL_OK with the fd in handlePtr, or TCL_ERROR if *	there is no handle for the specified direction.  * * Side effects: *	None. * *---------------------------------------------------------------------- */static intConsoleGetHandleProc(    ClientData instanceData,	/* The console state. */    int direction,		/* TCL_READABLE or TCL_WRITABLE */    ClientData *handlePtr)	/* Where to store the handle.  */{    ConsoleInfo *infoPtr = (ConsoleInfo *) instanceData;    *handlePtr = (ClientData) infoPtr->handle;    return TCL_OK;}/* *---------------------------------------------------------------------- * * WaitForRead -- * *	Wait until some data is available, the console is at *	EOF or the reader thread is blocked waiting for data (if the *	channel is in non-blocking mode). * * Results: *	Returns 1 if console is readable.  Returns 0 if there is no data *	on the console, but there is buffered data.  Returns -1 if an *	error occurred.  If an error occurred, the threads may not *	be synchronized. * * Side effects: *	Updates the shared state flags.  If no error occurred, *      the reader thread is blocked waiting for a signal from the  *      main thread. * *---------------------------------------------------------------------- */static intWaitForRead(    ConsoleInfo *infoPtr,		/* Console state. */    int blocking)		/* Indicates whether call should be				 * blocking or not. */{    DWORD timeout, count;    HANDLE *handle = infoPtr->handle;    INPUT_RECORD input;        while (1) {	/*	 * Synchronize with the reader thread.	 */       	timeout = blocking ? INFINITE : 0;	if (WaitForSingleObject(infoPtr->readable, timeout) == WAIT_TIMEOUT) {	    /*	     * The reader thread is blocked waiting for data and the channel	     * is in non-blocking mode.	     */	    errno = EAGAIN;	    return -1;	}		/*	 * At this point, the two threads are synchronized, so it is safe	 * to access shared state.	 */		/*	 * If the console has hit EOF, it is always readable.	 */		if (infoPtr->readFlags & CONSOLE_EOF) {	    return 1;	}		if (PeekConsoleInput(handle, &input, 1, &count) == FALSE) {            /*	     * Check to see if the peek failed because of EOF.	     */	    	    TclWinConvertError(GetLastError());	    	    if (errno == EOF) {		infoPtr->readFlags |= CONSOLE_EOF;		return 1;	    }	    /*	     * Ignore errors if there is data in the buffer.	     */	    	    if (infoPtr->readFlags & CONSOLE_BUFFERED) {		return 0;	    } else {		return -1;	    }	}	/*	 * If there is data in the buffer, the console must be	 * readable (since it is a line-oriented device).	 */	if (infoPtr->readFlags & CONSOLE_BUFFERED) {	    return 1;	}		/*	 * There wasn't any data available, so reset the thread and	 * try again.	 */    	ResetEvent(infoPtr->readable);	SetEvent(infoPtr->startReader);    }}/* *---------------------------------------------------------------------- * * ConsoleReaderThread -- * *	This function runs in a separate thread and waits for input *	to become available on a console. * * Results: *	None. * * Side effects: *	Signals the main thread when input become available.  May *	cause the main thread to wake up by posting a message.  May *	one line from the console for each wait operation. * *---------------------------------------------------------------------- */static DWORD WINAPIConsoleReaderThread(LPVOID arg){    ConsoleInfo *infoPtr = (ConsoleInfo *)arg;    HANDLE *handle = infoPtr->handle;    DWORD count;    for (;;) {	/*	 * Wait for the main thread to signal before attempting to wait.	 */	WaitForSingleObject(infoPtr->startReader, INFINITE);	count = 0;	/* 	 * Look for data on the console, but first ignore any events	 * that are not KEY_EVENTs 	 */	if (ReadConsole(handle, infoPtr->buffer, CONSOLE_BUFFER_SIZE,		(LPDWORD) &infoPtr->bytesRead, NULL) != FALSE) {	    /*	     * Data was stored in the buffer.	     */	    	    infoPtr->readFlags |= CONSOLE_BUFFERED;	} else {	    DWORD err;	    err = GetLastError();	    	    if (err == EOF) {		infoPtr->readFlags = CONSOLE_EOF;	    }	}	/*	 * Signal the main thread by signalling the readable event and	 * then waking up the notifier thread.	 */	SetEvent(infoPtr->readable);	/*	 * Alert the foreground thread.  Note that we need to treat this like	 * a critical section so the foreground thread does not terminate	 * this thread while we are holding a mutex in the notifier code.	 */	Tcl_MutexLock(&consoleMutex);	Tcl_ThreadAlert(infoPtr->threadId);	Tcl_MutexUnlock(&consoleMutex);    }    return 0;			/* NOT REACHED */}/* *---------------------------------------------------------------------- * * ConsoleWriterThread -- * *	This function runs in a separate thread and writes data *	onto a console. * * Results: *	Always returns 0. * * Side effects: *	Signals the main thread when an output operation is completed. *	May cause the main thread to wake up by posting a message.   * *---------------------------------------------------------------------- */static DWORD WINAPIConsoleWriterThread(LPVOID arg){    ConsoleInfo *infoPtr = (ConsoleInfo *)arg;    HANDLE *handle = infoPtr->handle;    DWORD count, toWrite;    char *buf;    for (;;) {	/*	 * Wait for the main thread to signal before attempting to write.	 */	WaitForSingleObject(infoPtr->startWriter, INFINITE);	buf = infoPtr->writeBuf;	toWrite = infoPtr->toWrite;	/*	 * Loop until all of the bytes are written or an error occurs.	 */	while (toWrite > 0) {	    if (WriteFile(handle, buf, toWrite, &count, NULL) == FALSE) {		infoPtr->writeError = GetLastError();		break;	    } else {		toWrite -= count;		buf += count;	    }	}	/*	 * Signal the main thread by signalling the writable event and	 * then waking up the notifier thread.	 */		SetEvent(infoPtr->writable);	/*	 * Alert the foreground thread.  Note that we need to treat this like	 * a critical section so the foreground thread does not terminate	 * this thread while we are holding a mutex in the notifier code.	 */	Tcl_MutexLock(&consoleMutex);	Tcl_ThreadAlert(infoPtr->threadId);	Tcl_MutexUnlock(&consoleMutex);    }    return 0;			/* NOT REACHED */}/* *---------------------------------------------------------------------- * * TclWinOpenConsoleChannel -- * *	Constructs a Console channel for the specified standard OS handle. *      This is a helper function to break up the construction of  *      channels into File, Console, or Serial. * * Results: *	Returns the new channel, or NULL. * * Side effects: *	May open the channel * *---------------------------------------------------------------------- */Tcl_ChannelTclWinOpenConsoleChannel(handle, channelName, permissions)    HANDLE handle;    char *channelName;    int permissions;{    char encoding[4 + TCL_INTEGER_SPACE];    ConsoleInfo *infoPtr;    ThreadSpecificData *tsdPtr;    DWORD id;    tsdPtr = ConsoleInit();    /*     * See if a channel with this handle already exists.     */        infoPtr = (ConsoleInfo *) ckalloc((unsigned) sizeof(ConsoleInfo));    memset(infoPtr, 0, sizeof(ConsoleInfo));    infoPtr->validMask = permissions;    infoPtr->handle = handle;    wsprintfA(encoding, "cp%d", GetConsoleCP());        /*     * Use the pointer for the name of the result channel.     * This keeps the channel names unique, since some may share     * handles (stdin/stdout/stderr for instance).     */    wsprintfA(channelName, "file%lx", (int) infoPtr);        infoPtr->channel = Tcl_CreateChannel(&consoleChannelType, channelName,            (ClientData) infoPtr, permissions);    infoPtr->threadId = Tcl_GetCurrentThread();    if (permissions & TCL_READABLE) {	infoPtr->readable = CreateEvent(NULL, TRUE, TRUE, NULL);	infoPtr->startReader = CreateEvent(NULL, FALSE, FALSE, NULL);	infoPtr->readThread = CreateThread(NULL, 8000, ConsoleReaderThread,	        infoPtr, 0, &id);	SetThreadPriority(infoPtr->readThread, THREAD_PRIORITY_HIGHEST);     }    if (permissions & TCL_WRITABLE) {	infoPtr->writable = CreateEvent(NULL, TRUE, TRUE, NULL);	infoPtr->startWriter = CreateEvent(NULL, FALSE, FALSE, NULL);	infoPtr->writeThread = CreateThread(NULL, 8000, ConsoleWriterThread,	        infoPtr, 0, &id);    }    /*     * Files have default translation of AUTO and ^Z eof char, which     * means that a ^Z will be accepted as EOF when reading.     */        Tcl_SetChannelOption(NULL, infoPtr->channel, "-translation", "auto");    Tcl_SetChannelOption(NULL, infoPtr->channel, "-eofchar", "\032 {}");    Tcl_SetChannelOption(NULL, infoPtr->channel, "-encoding", encoding);    return infoPtr->channel;}

⌨️ 快捷键说明

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