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

📄 tclwinpipe.c

📁 这是leon3处理器的交叉编译链
💻 C
📖 第 1 页 / 共 5 页
字号:
/*  * tclWinPipe.c -- * *	This file implements the Windows-specific exec pipeline functions, *	the "pipe" channel driver, and the "pid" Tcl command. * * Copyright (c) 1996-1997 by Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * * RCS: @(#) $Id: tclWinPipe.c,v 1.25 2002/06/17 20:05:49 andreas_kupries 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 pipeMutex locks around access to the initialized and procList variables, * and it is used to protect background threads from being terminated while * they are using APIs that hold locks. */TCL_DECLARE_MUTEX(pipeMutex)/* * The following defines identify the various types of applications that  * run under windows.  There is special case code for the various types. */#define APPL_NONE	0#define APPL_DOS	1#define APPL_WIN3X	2#define APPL_WIN32	3/* * The following constants and structures are used to encapsulate the state * of various types of files used in a pipeline. * This used to have a 1 && 2 that supported Win32s. */#define WIN_FILE 3		/* Basic Win32 file. *//* * This structure encapsulates the common state associated with all file * types used in a pipeline. */typedef struct WinFile {    int type;			/* One of the file types defined above. */    HANDLE handle;		/* Open file handle. */} WinFile;/* * This list is used to map from pids to process handles. */typedef struct ProcInfo {    HANDLE hProcess;    DWORD dwProcessId;    struct ProcInfo *nextPtr;} ProcInfo;static ProcInfo *procList;/* * Bit masks used in the flags field of the PipeInfo structure below. */#define PIPE_PENDING	(1<<0)	/* Message is pending in the queue. */#define PIPE_ASYNC	(1<<1)	/* Channel is non-blocking. *//* * Bit masks used in the sharedFlags field of the PipeInfo structure below. */#define PIPE_EOF	(1<<2)	/* Pipe has reached EOF. */#define PIPE_EXTRABYTE	(1<<3)	/* The reader thread has consumed one byte. *//* * This structure describes per-instance data for a pipe based channel. */typedef struct PipeInfo {    struct PipeInfo *nextPtr;	/* Pointer to next registered pipe. */    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. */    TclFile readFile;		/* Output from pipe. */    TclFile writeFile;		/* Input from pipe. */    TclFile errorFile;		/* Error output from pipe. */    int numPids;		/* Number of processes attached to pipe. */    Tcl_Pid *pidPtr;		/* Pids of attached processes. */    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 pipe. */    HANDLE startReader;		/* Auto-reset event used by the main thread to				 * signal when the reader thread should attempt				 * to read from the pipe. */    HANDLE stopReader;		/* Manual-reset event used to alert the reader				 * thread to fall-out and exit */    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.  */    char extraByte;		/* Buffer for extra character consumed by				 * reader thread.  This byte is shared with				 * the reader thread so access must be				 * synchronized with the readable object. */} PipeInfo;typedef struct ThreadSpecificData {    /*     * The following pointer refers to the head of the list of pipes     * that are being watched for file events.     */        PipeInfo *firstPipePtr;} ThreadSpecificData;static Tcl_ThreadDataKey dataKey;/* * The following structure is what is added to the Tcl event queue when * pipe events are generated. */typedef struct PipeEvent {    Tcl_Event header;		/* Information that is standard for				 * all events. */    PipeInfo *infoPtr;		/* Pointer to pipe info structure.  Note				 * that we still have to verify that the				 * pipe exists before dereferencing this				 * pointer. */} PipeEvent;/* * Declarations for functions used only in this file. */static int		ApplicationType(Tcl_Interp *interp,			    const char *fileName, char *fullName);static void		BuildCommandLine(const char *executable, int argc, 			    CONST char **argv, Tcl_DString *linePtr);static BOOL		HasConsole(void);static int		PipeBlockModeProc(ClientData instanceData, int mode);static void		PipeCheckProc(ClientData clientData, int flags);static int		PipeClose2Proc(ClientData instanceData,			    Tcl_Interp *interp, int flags);static int		PipeEventProc(Tcl_Event *evPtr, int flags);static void		PipeExitHandler(ClientData clientData);static int		PipeGetHandleProc(ClientData instanceData,			    int direction, ClientData *handlePtr);static void		PipeInit(void);static int		PipeInputProc(ClientData instanceData, char *buf,			    int toRead, int *errorCode);static int		PipeOutputProc(ClientData instanceData,			    CONST char *buf, int toWrite, int *errorCode);static DWORD WINAPI	PipeReaderThread(LPVOID arg);static void		PipeSetupProc(ClientData clientData, int flags);static void		PipeWatchProc(ClientData instanceData, int mask);static DWORD WINAPI	PipeWriterThread(LPVOID arg);static void		ProcExitHandler(ClientData clientData);static int		TempFileName(WCHAR name[MAX_PATH]);static int		WaitForRead(PipeInfo *infoPtr, int blocking);/* * This structure describes the channel type structure for command pipe * based IO. */static Tcl_ChannelType pipeChannelType = {    "pipe",			/* Type name. */    TCL_CHANNEL_VERSION_2,	/* v2 channel */    TCL_CLOSE2PROC,		/* Close proc. */    PipeInputProc,		/* Input proc. */    PipeOutputProc,		/* Output proc. */    NULL,			/* Seek proc. */    NULL,			/* Set option proc. */    NULL,			/* Get option proc. */    PipeWatchProc,		/* Set up notifier to watch the channel. */    PipeGetHandleProc,		/* Get an OS handle from channel. */    PipeClose2Proc,		/* close2proc */    PipeBlockModeProc,		/* Set blocking or non-blocking mode.*/    NULL,			/* flush proc. */    NULL,			/* handler proc. */};/* *---------------------------------------------------------------------- * * PipeInit -- * *	This function initializes the static variables for this file. * * Results: *	None. * * Side effects: *	Creates a new event source. * *---------------------------------------------------------------------- */static voidPipeInit(){    ThreadSpecificData *tsdPtr;    /*     * Check the initialized flag first, then check again in the mutex.     * This is a speed enhancement.     */    if (!initialized) {	Tcl_MutexLock(&pipeMutex);	if (!initialized) {	    initialized = 1;	    procList = NULL;	    Tcl_CreateExitHandler(ProcExitHandler, NULL);	}	Tcl_MutexUnlock(&pipeMutex);    }    tsdPtr = (ThreadSpecificData *)TclThreadDataKeyGet(&dataKey);    if (tsdPtr == NULL) {	tsdPtr = TCL_TSD_INIT(&dataKey);	tsdPtr->firstPipePtr = NULL;	Tcl_CreateEventSource(PipeSetupProc, PipeCheckProc, NULL);	Tcl_CreateThreadExitHandler(PipeExitHandler, NULL);    }}/* *---------------------------------------------------------------------- * * PipeExitHandler -- * *	This function is called to cleanup the pipe module before *	Tcl is unloaded. * * Results: *	None. * * Side effects: *	Removes the pipe event source. * *---------------------------------------------------------------------- */static voidPipeExitHandler(    ClientData clientData)	/* Old window proc */{    Tcl_DeleteEventSource(PipeSetupProc, PipeCheckProc, 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(&pipeMutex);    initialized = 0;    Tcl_MutexUnlock(&pipeMutex);}/* *---------------------------------------------------------------------- * * PipeSetupProc -- * *	This procedure is invoked before Tcl_DoOneEvent blocks waiting *	for an event. * * Results: *	None. * * Side effects: *	Adjusts the block time if needed. * *---------------------------------------------------------------------- */voidPipeSetupProc(    ClientData data,		/* Not used. */    int flags)			/* Event flags as passed to Tcl_DoOneEvent. */{    PipeInfo *infoPtr;    Tcl_Time blockTime = { 0, 0 };    int block = 1;    WinFile *filePtr;    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->firstPipePtr; infoPtr != NULL; 	    infoPtr = infoPtr->nextPtr) {	if (infoPtr->watchMask & TCL_WRITABLE) {	    filePtr = (WinFile*) infoPtr->writeFile;	    if (WaitForSingleObject(infoPtr->writable, 0) != WAIT_TIMEOUT) {		block = 0;	    }	}	if (infoPtr->watchMask & TCL_READABLE) {	    filePtr = (WinFile*) infoPtr->readFile;	    if (WaitForRead(infoPtr, 0) >= 0) {		block = 0;	    }	}    }    if (!block) {	Tcl_SetMaxBlockTime(&blockTime);    }}/* *---------------------------------------------------------------------- * * PipeCheckProc -- * *	This procedure is called by Tcl_DoOneEvent to check the pipe *	event source for events.  * * Results: *	None. * * Side effects: *	May queue an event. * *---------------------------------------------------------------------- */static voidPipeCheckProc(    ClientData data,		/* Not used. */    int flags)			/* Event flags as passed to Tcl_DoOneEvent. */{    PipeInfo *infoPtr;    PipeEvent *evPtr;    WinFile *filePtr;    int needEvent;    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);    if (!(flags & TCL_FILE_EVENTS)) {	return;    }        /*     * Queue events for any ready pipes that don't already have events     * queued.     */    for (infoPtr = tsdPtr->firstPipePtr; infoPtr != NULL; 	    infoPtr = infoPtr->nextPtr) {	if (infoPtr->flags & PIPE_PENDING) {	    continue;	}		/*	 * Queue an event if the pipe is signaled for reading or writing.	 */	needEvent = 0;	filePtr = (WinFile*) infoPtr->writeFile;	if ((infoPtr->watchMask & TCL_WRITABLE) &&		(WaitForSingleObject(infoPtr->writable, 0) != WAIT_TIMEOUT)) {	    needEvent = 1;	}		filePtr = (WinFile*) infoPtr->readFile;	if ((infoPtr->watchMask & TCL_READABLE) &&		(WaitForRead(infoPtr, 0) >= 0)) {	    needEvent = 1;	}	if (needEvent) {	    infoPtr->flags |= PIPE_PENDING;	    evPtr = (PipeEvent *) ckalloc(sizeof(PipeEvent));	    evPtr->header.proc = PipeEventProc;	    evPtr->infoPtr = infoPtr;	    Tcl_QueueEvent((Tcl_Event *) evPtr, TCL_QUEUE_TAIL);	}    }}/* *---------------------------------------------------------------------- * * TclWinMakeFile -- * *	This function constructs a new TclFile from a given data and *	type value. * * Results: *	Returns a newly allocated WinFile as a TclFile. * * Side effects: *	None. * *---------------------------------------------------------------------- */TclFileTclWinMakeFile(    HANDLE handle)		/* Type-specific data. */

⌨️ 快捷键说明

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