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

📄 tclwinconsole.c

📁 这是leon3处理器的交叉编译链
💻 C
📖 第 1 页 / 共 3 页
字号:
     */    if (mode == TCL_MODE_NONBLOCKING) {	infoPtr->flags |= CONSOLE_ASYNC;    } else {	infoPtr->flags &= ~(CONSOLE_ASYNC);    }    return 0;}/* *---------------------------------------------------------------------- * * ConsoleCloseProc -- * *	Closes a console based IO channel. * * Results: *	0 on success, errno otherwise. * * Side effects: *	Closes the physical channel. * *---------------------------------------------------------------------- */static intConsoleCloseProc(    ClientData instanceData,	/* Pointer to ConsoleInfo structure. */    Tcl_Interp *interp)		/* For error reporting. */{    ConsoleInfo *consolePtr = (ConsoleInfo *) instanceData;    int errorCode;    ConsoleInfo *infoPtr, **nextPtrPtr;    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);    errorCode = 0;        /*     * Clean up the background thread if necessary.  Note that this     * must be done before we can close the file, since the      * thread may be blocking trying to read from the console.     */        if (consolePtr->readThread) {	/*	 * Forcibly terminate the background thread.  We cannot rely on the	 * thread to cleanly terminate itself because we have no way of	 * closing the handle without blocking in the case where the	 * thread is in the middle of an I/O operation.  Note that we need	 * to guard against terminating the thread while it is in the	 * middle of Tcl_ThreadAlert because it won't be able to release	 * the notifier lock.	 */	Tcl_MutexLock(&consoleMutex);	TerminateThread(consolePtr->readThread, 0);	/*	 * Wait for the thread to terminate.  This ensures that we are	 * completely cleaned up before we leave this function. 	 */	WaitForSingleObject(consolePtr->readThread, INFINITE);	Tcl_MutexUnlock(&consoleMutex);	CloseHandle(consolePtr->readThread);	CloseHandle(consolePtr->readable);	CloseHandle(consolePtr->startReader);	consolePtr->readThread = NULL;    }    consolePtr->validMask &= ~TCL_READABLE;    /*     * Wait for the writer thread to finish the current buffer, then     * terminate the thread and close the handles.  If the channel is     * nonblocking, there should be no pending write operations.     */        if (consolePtr->writeThread) {	if (consolePtr->toWrite) {	    /*	     * We only need to wait if there is something to write.	     * This may prevent infinite wait on exit. [python bug 216289]	     */	    WaitForSingleObject(consolePtr->writable, INFINITE);	}	/*	 * Forcibly terminate the background thread.  We cannot rely on the	 * thread to cleanly terminate itself because we have no way of	 * closing the handle without blocking in the case where the	 * thread is in the middle of an I/O operation.  Note that we need	 * to guard against terminating the thread while it is in the	 * middle of Tcl_ThreadAlert because it won't be able to release	 * the notifier lock.	 */	Tcl_MutexLock(&consoleMutex);	TerminateThread(consolePtr->writeThread, 0);	/*	 * Wait for the thread to terminate.  This ensures that we are	 * completely cleaned up before we leave this function. 	 */	WaitForSingleObject(consolePtr->writeThread, INFINITE);	Tcl_MutexUnlock(&consoleMutex);	CloseHandle(consolePtr->writeThread);	CloseHandle(consolePtr->writable);	CloseHandle(consolePtr->startWriter);	consolePtr->writeThread = NULL;    }    consolePtr->validMask &= ~TCL_WRITABLE;    /*     * Don't close the Win32 handle if the handle is a standard channel     * during the exit process.  Otherwise, one thread may kill the stdio     * of another.     */    if (!TclInExit() 	    || ((GetStdHandle(STD_INPUT_HANDLE) != consolePtr->handle)		&& (GetStdHandle(STD_OUTPUT_HANDLE) != consolePtr->handle)		&& (GetStdHandle(STD_ERROR_HANDLE) != consolePtr->handle))) {	if (CloseHandle(consolePtr->handle) == FALSE) {	    TclWinConvertError(GetLastError());	    errorCode = errno;	}    }        consolePtr->watchMask &= consolePtr->validMask;    /*     * Remove the file from the list of watched files.     */    for (nextPtrPtr = &(tsdPtr->firstConsolePtr), infoPtr = *nextPtrPtr;	    infoPtr != NULL;	    nextPtrPtr = &infoPtr->nextPtr, infoPtr = *nextPtrPtr) {	if (infoPtr == (ConsoleInfo *)consolePtr) {	    *nextPtrPtr = infoPtr->nextPtr;	    break;	}    }    if (consolePtr->writeBuf != NULL) {	ckfree(consolePtr->writeBuf);	consolePtr->writeBuf = 0;    }    ckfree((char*) consolePtr);    return errorCode;}/* *---------------------------------------------------------------------- * * ConsoleInputProc -- * *	Reads input from the IO channel into the buffer given. Returns *	count of how many bytes were actually read, and an error indication. * * Results: *	A count of how many bytes were read is returned and an error *	indication is returned in an output argument. * * Side effects: *	Reads input from the actual channel. * *---------------------------------------------------------------------- */static intConsoleInputProc(    ClientData instanceData,		/* Console state. */    char *buf,				/* Where to store data read. */    int bufSize,			/* How much space is available                                         * in the buffer? */    int *errorCode)			/* Where to store error code. */{    ConsoleInfo *infoPtr = (ConsoleInfo *) instanceData;    DWORD count, bytesRead = 0;    int result;    *errorCode = 0;    /*     * Synchronize with the reader thread.     */        result = WaitForRead(infoPtr, (infoPtr->flags & CONSOLE_ASYNC) ? 0 : 1);        /*     * If an error occurred, return immediately.     */        if (result == -1) {	*errorCode = errno;	return -1;    }    if (infoPtr->readFlags & CONSOLE_BUFFERED) {	/*	 * Data is stored in the buffer.	 */	if (bufSize < (infoPtr->bytesRead - infoPtr->offset)) {	    memcpy(buf, &infoPtr->buffer[infoPtr->offset], (size_t) bufSize);	    bytesRead = bufSize;	    infoPtr->offset += bufSize;	} else {	    memcpy(buf, &infoPtr->buffer[infoPtr->offset], (size_t) bufSize);	    bytesRead = infoPtr->bytesRead - infoPtr->offset;	    /*	     * Reset the buffer	     */	    	    infoPtr->readFlags &= ~CONSOLE_BUFFERED;	    infoPtr->offset = 0;	}	return bytesRead;    }        /*     * Attempt to read bufSize bytes.  The read will return immediately     * if there is any data available.  Otherwise it will block until     * at least one byte is available or an EOF occurs.     */    if (ReadConsole(infoPtr->handle, (LPVOID) buf, (DWORD) bufSize, &count,		    (LPOVERLAPPED) NULL) == TRUE) {	buf[count] = '\0';	return count;    }    return -1;}/* *---------------------------------------------------------------------- * * ConsoleOutputProc -- * *	Writes the given output on the IO channel. Returns count of how *	many characters were actually written, and an error indication. * * Results: *	A count of how many characters were written is returned and an *	error indication is returned in an output argument. * * Side effects: *	Writes output on the actual channel. * *---------------------------------------------------------------------- */static intConsoleOutputProc(    ClientData instanceData,		/* Console state. */    CONST char *buf,			/* The data buffer. */    int toWrite,			/* How many bytes to write? */    int *errorCode)			/* Where to store error code. */{    ConsoleInfo *infoPtr = (ConsoleInfo *) instanceData;    DWORD bytesWritten, timeout;        *errorCode = 0;    timeout = (infoPtr->flags & CONSOLE_ASYNC) ? 0 : INFINITE;    if (WaitForSingleObject(infoPtr->writable, timeout) == WAIT_TIMEOUT) {	/*	 * The writer thread is blocked waiting for a write to complete	 * and the channel is in non-blocking mode.	 */	errno = EAGAIN;	goto error;    }        /*     * Check for a background error on the last write.     */    if (infoPtr->writeError) {	TclWinConvertError(infoPtr->writeError);	infoPtr->writeError = 0;	goto error;    }    if (infoPtr->flags & CONSOLE_ASYNC) {	/*	 * The console is non-blocking, so copy the data into the output	 * buffer and restart the writer thread.	 */	if (toWrite > infoPtr->writeBufLen) {	    /*	     * Reallocate the buffer to be large enough to hold the data.	     */	    if (infoPtr->writeBuf) {		ckfree(infoPtr->writeBuf);	    }	    infoPtr->writeBufLen = toWrite;	    infoPtr->writeBuf = ckalloc((unsigned int) toWrite);	}	memcpy(infoPtr->writeBuf, buf, (size_t) toWrite);	infoPtr->toWrite = toWrite;	ResetEvent(infoPtr->writable);	SetEvent(infoPtr->startWriter);	bytesWritten = toWrite;    } else {	/*	 * In the blocking case, just try to write the buffer directly.	 * This avoids an unnecessary copy.	 */	if (WriteFile(infoPtr->handle, (LPVOID) buf, (DWORD) toWrite,		&bytesWritten, (LPOVERLAPPED) NULL) == FALSE) {	    TclWinConvertError(GetLastError());	    goto error;	}    }    return bytesWritten;    error:    *errorCode = errno;    return -1;}/* *---------------------------------------------------------------------- * * ConsoleEventProc -- * *	This function is invoked by Tcl_ServiceEvent when a file event *	reaches the front of the event queue.  This procedure invokes *	Tcl_NotifyChannel on the console. * * Results: *	Returns 1 if the event was handled, meaning it should be removed *	from the queue.  Returns 0 if the event was not handled, meaning *	it should stay on the queue.  The only time the event isn't *	handled is if the TCL_FILE_EVENTS flag bit isn't set. * * Side effects: *	Whatever the notifier callback does. * *---------------------------------------------------------------------- */static intConsoleEventProc(    Tcl_Event *evPtr,		/* Event to service. */    int flags)			/* Flags that indicate what events to				 * handle, such as TCL_FILE_EVENTS. */{    ConsoleEvent *consoleEvPtr = (ConsoleEvent *)evPtr;    ConsoleInfo *infoPtr;    int mask;    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);    if (!(flags & TCL_FILE_EVENTS)) {	return 0;    }    /*     * Search through the list of watched consoles for the one whose handle     * matches the event.  We do this rather than simply dereferencing     * the handle in the event so that consoles can be deleted while the     * event is in the queue.     */    for (infoPtr = tsdPtr->firstConsolePtr; infoPtr != NULL;	    infoPtr = infoPtr->nextPtr) {	if (consoleEvPtr->infoPtr == infoPtr) {	    infoPtr->flags &= ~(CONSOLE_PENDING);	    break;	}    }    /*     * Remove stale events.     */    if (!infoPtr) {	return 1;    }    /*     * Check to see if the console is readable.  Note     * that we can't tell if a console is writable, so we always report it     * as being writable unless we have detected EOF.     */    mask = 0;    if (infoPtr->watchMask & TCL_WRITABLE) {	if (WaitForSingleObject(infoPtr->writable, 0) != WAIT_TIMEOUT) {	    mask = TCL_WRITABLE;	}    }    if (infoPtr->watchMask & TCL_READABLE) {	if (WaitForRead(infoPtr, 0) >= 0) {	    if (infoPtr->readFlags & CONSOLE_EOF) {		mask = TCL_READABLE;	    } else {		mask |= TCL_READABLE;	    }	}     }    /*     * Inform the channel of the events.     */    Tcl_NotifyChannel(infoPtr->channel, infoPtr->watchMask & mask);    return 1;}/*

⌨️ 快捷键说明

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