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

📄 tclwinpipe.c

📁 这是leon3处理器的交叉编译链
💻 C
📖 第 1 页 / 共 5 页
字号:
	}	strcpy(fullName, Tcl_WinTCharToUtf((TCHAR *) nativeFullPath, -1, &ds));	Tcl_DStringFree(&ds);	ext = strrchr(fullName, '.');	if ((ext != NULL) && (stricmp(ext, ".bat") == 0)) {	    applType = APPL_DOS;	    break;	}		hFile = (*tclWinProcs->createFileProc)((TCHAR *) nativeFullPath, 		GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 		FILE_ATTRIBUTE_NORMAL, NULL);	if (hFile == INVALID_HANDLE_VALUE) {	    continue;	}	header.e_magic = 0;	ReadFile(hFile, (void *) &header, sizeof(header), &read, NULL);	if (header.e_magic != IMAGE_DOS_SIGNATURE) {	    /* 	     * Doesn't have the magic number for relocatable executables.  If 	     * filename ends with .com, assume it's a DOS application anyhow.	     * Note that we didn't make this assumption at first, because some	     * supposed .com files are really 32-bit executables with all the	     * magic numbers and everything.  	     */	    CloseHandle(hFile);	    if ((ext != NULL) && (stricmp(ext, ".com") == 0)) {		applType = APPL_DOS;		break;	    }	    continue;	}	if (header.e_lfarlc != sizeof(header)) {	    /* 	     * All Windows 3.X and Win32 and some DOS programs have this value	     * set here.  If it doesn't, assume that since it already had the 	     * other magic number it was a DOS application.	     */	    CloseHandle(hFile);	    applType = APPL_DOS;	    break;	}	/* 	 * The DWORD at header.e_lfanew points to yet another magic number.	 */	buf[0] = '\0';	SetFilePointer(hFile, header.e_lfanew, NULL, FILE_BEGIN);	ReadFile(hFile, (void *) buf, 2, &read, NULL);	CloseHandle(hFile);	if ((buf[0] == 'N') && (buf[1] == 'E')) {	    applType = APPL_WIN3X;	} else if ((buf[0] == 'P') && (buf[1] == 'E')) {	    applType = APPL_WIN32;	} else {	    /*	     * Strictly speaking, there should be a test that there	     * is an 'L' and 'E' at buf[0..1], to identify the type as 	     * DOS, but of course we ran into a DOS executable that 	     * _doesn't_ have the magic number -- specifically, one	     * compiled using the Lahey Fortran90 compiler.	     */	    applType = APPL_DOS;	}	break;    }    Tcl_DStringFree(&nameBuf);    if (applType == APPL_NONE) {	TclWinConvertError(GetLastError());	Tcl_AppendResult(interp, "couldn't execute \"", originalName,		"\": ", Tcl_PosixError(interp), (char *) NULL);	return APPL_NONE;    }    if ((applType == APPL_DOS) || (applType == APPL_WIN3X)) {	/* 	 * Replace long path name of executable with short path name for 	 * 16-bit applications.  Otherwise the application may not be able	 * to correctly parse its own command line to separate off the 	 * application name from the arguments.	 */	(*tclWinProcs->getShortPathNameProc)((TCHAR *) nativeFullPath, 		nativeFullPath, MAX_PATH);	strcpy(fullName, Tcl_WinTCharToUtf((TCHAR *) nativeFullPath, -1, &ds));	Tcl_DStringFree(&ds);    }    return applType;}/*     *---------------------------------------------------------------------- * * BuildCommandLine -- * *	The command line arguments are stored in linePtr separated *	by spaces, in a form that CreateProcess() understands.  Special  *	characters in individual arguments from argv[] must be quoted  *	when being stored in cmdLine. * * Results: *	None. * * Side effects: *	None. * *---------------------------------------------------------------------- */static voidBuildCommandLine(    CONST char *executable,	/* Full path of executable (including 				 * extension).  Replacement for argv[0]. */    int argc,			/* Number of arguments. */    CONST char **argv,		/* Argument strings in UTF. */    Tcl_DString *linePtr)	/* Initialized Tcl_DString that receives the				 * command line (TCHAR). */{    CONST char *arg, *start, *special;    int quote, i;    Tcl_DString ds;    Tcl_DStringInit(&ds);    /*     * Prime the path.     */        Tcl_DStringAppend(&ds, Tcl_DStringValue(linePtr), -1);        for (i = 0; i < argc; i++) {	if (i == 0) {	    arg = executable;	} else {	    arg = argv[i];	    Tcl_DStringAppend(&ds, " ", 1);	}	quote = 0;	if (arg[0] == '\0') {	    quote = 1;	} else {	    for (start = arg; *start != '\0'; start++) {		if (isspace(*start)) { /* INTL: ISO space. */		    quote = 1;		    break;		}	    }	}	if (quote) {	    Tcl_DStringAppend(&ds, "\"", 1);	}	start = arg;	    	for (special = arg; ; ) {	    if ((*special == '\\') && 		    (special[1] == '\\' || special[1] == '"')) {		Tcl_DStringAppend(&ds, start, special - start);		start = special;		while (1) {		    special++;		    if (*special == '"') {			/* 			 * N backslashes followed a quote -> insert 			 * N * 2 + 1 backslashes then a quote.			 */			Tcl_DStringAppend(&ds, start, special - start);			break;		    }		    if (*special != '\\') {			break;		    }		}		Tcl_DStringAppend(&ds, start, special - start);		start = special;	    }	    if (*special == '"') {		Tcl_DStringAppend(&ds, start, special - start);		Tcl_DStringAppend(&ds, "\\\"", 2);		start = special + 1;	    }	    if (*special == '{') {		Tcl_DStringAppend(&ds, start, special - start);		Tcl_DStringAppend(&ds, "\\{", 2);		start = special + 1;	    }	    if (*special == '\0') {		break;	    }	    special++;	}	Tcl_DStringAppend(&ds, start, special - start);	if (quote) {	    Tcl_DStringAppend(&ds, "\"", 1);	}    }    Tcl_DStringFree(linePtr);    Tcl_WinUtfToTChar(Tcl_DStringValue(&ds), Tcl_DStringLength(&ds), linePtr);    Tcl_DStringFree(&ds);}/* *---------------------------------------------------------------------- * * TclpCreateCommandChannel -- * *	This function is called by Tcl_OpenCommandChannel to perform *	the platform specific channel initialization for a command *	channel. * * Results: *	Returns a new channel or NULL on failure. * * Side effects: *	Allocates a new channel. * *---------------------------------------------------------------------- */Tcl_ChannelTclpCreateCommandChannel(    TclFile readFile,		/* If non-null, gives the file for reading. */    TclFile writeFile,		/* If non-null, gives the file for writing. */    TclFile errorFile,		/* If non-null, gives the file where errors				 * can be read. */    int numPids,		/* The number of pids in the pid array. */    Tcl_Pid *pidPtr)		/* An array of process identifiers. */{    char channelName[16 + TCL_INTEGER_SPACE];    int channelId;    DWORD id;    PipeInfo *infoPtr = (PipeInfo *) ckalloc((unsigned) sizeof(PipeInfo));    PipeInit();    infoPtr->watchMask = 0;    infoPtr->flags = 0;    infoPtr->readFlags = 0;    infoPtr->readFile = readFile;    infoPtr->writeFile = writeFile;    infoPtr->errorFile = errorFile;    infoPtr->numPids = numPids;    infoPtr->pidPtr = pidPtr;    infoPtr->writeBuf = 0;    infoPtr->writeBufLen = 0;    infoPtr->writeError = 0;    /*     * Use one of the fds associated with the channel as the     * channel id.     */    if (readFile) {	channelId = (int) ((WinFile*)readFile)->handle;    } else if (writeFile) {	channelId = (int) ((WinFile*)writeFile)->handle;    } else if (errorFile) {	channelId = (int) ((WinFile*)errorFile)->handle;    } else {	channelId = 0;    }    infoPtr->validMask = 0;    infoPtr->threadId = Tcl_GetCurrentThread();    if (readFile != NULL) {	/*	 * Start the background reader thread.	 */	infoPtr->readable = CreateEvent(NULL, TRUE, TRUE, NULL);	infoPtr->startReader = CreateEvent(NULL, FALSE, FALSE, NULL);	infoPtr->stopReader = CreateEvent(NULL, TRUE, FALSE, NULL);	infoPtr->readThread = CreateThread(NULL, 512, PipeReaderThread,		infoPtr, 0, &id);	SetThreadPriority(infoPtr->readThread, THREAD_PRIORITY_HIGHEST);         infoPtr->validMask |= TCL_READABLE;    } else {	infoPtr->readThread = 0;    }    if (writeFile != NULL) {	/*	 * Start the background writer thread.	 */	infoPtr->writable = CreateEvent(NULL, TRUE, TRUE, NULL);	infoPtr->startWriter = CreateEvent(NULL, FALSE, FALSE, NULL);	infoPtr->writeThread = CreateThread(NULL, 512, PipeWriterThread,		infoPtr, 0, &id);	SetThreadPriority(infoPtr->readThread, THREAD_PRIORITY_HIGHEST);         infoPtr->validMask |= TCL_WRITABLE;    }    /*     * For backward compatibility with previous versions of Tcl, we     * use "file%d" as the base name for pipes even though it would     * be more natural to use "pipe%d".     * Use the pointer to keep the channel names unique, in case     * channels share handles (stdin/stdout).     */    wsprintfA(channelName, "file%lx", infoPtr);    infoPtr->channel = Tcl_CreateChannel(&pipeChannelType, channelName,            (ClientData) infoPtr, infoPtr->validMask);    /*     * Pipes have AUTO translation mode on Windows and ^Z eof char, which     * means that a ^Z will be appended to them at close. This is needed     * for Windows programs that expect a ^Z at EOF.     */    Tcl_SetChannelOption((Tcl_Interp *) NULL, infoPtr->channel,	    "-translation", "auto");    Tcl_SetChannelOption((Tcl_Interp *) NULL, infoPtr->channel,	    "-eofchar", "\032 {}");    return infoPtr->channel;}/* *---------------------------------------------------------------------- * * TclGetAndDetachPids -- * *	Stores a list of the command PIDs for a command channel in *	the interp's result. * * Results: *	None. * * Side effects: *	Modifies the interp's result. * *---------------------------------------------------------------------- */voidTclGetAndDetachPids(    Tcl_Interp *interp,    Tcl_Channel chan){    PipeInfo *pipePtr;    Tcl_ChannelType *chanTypePtr;    int i;    char buf[TCL_INTEGER_SPACE];    /*     * Punt if the channel is not a command channel.     */    chanTypePtr = Tcl_GetChannelType(chan);    if (chanTypePtr != &pipeChannelType) {        return;    }    pipePtr = (PipeInfo *) Tcl_GetChannelInstanceData(chan);    for (i = 0; i < pipePtr->numPids; i++) {        wsprintfA(buf, "%lu", TclpGetPid(pipePtr->pidPtr[i]));        Tcl_AppendElement(interp, buf);        Tcl_DetachPids(1, &(pipePtr->pidPtr[i]));    }    if (pipePtr->numPids > 0) {        ckfree((char *) pipePtr->pidPtr);        pipePtr->numPids = 0;    }}/* *---------------------------------------------------------------------- * * PipeBlockModeProc -- * *	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 intPipeBlockModeProc(    ClientData instanceData,	/* Instance data for channel. */    int mode)			/* TCL_MODE_BLOCKING or                                 * TCL_MODE_NONBLOCKING. */{    PipeInfo *infoPtr = (PipeInfo *) instanceData;        /*     * Pipes 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.     */    if (mode == TCL_MODE_NONBLOCKING) {	infoPtr->flags |= PIPE_ASYNC;    } else {	infoPtr->flags &= ~(PIPE_ASYNC);    }    return 0;}/* *---------------------------------------------------------------------- * * PipeClose2Proc -- * *	Closes a pipe based IO channel. * * Results: *	0 on success, errno otherwise. * * Side effects: *	Closes the physical channel. * *---------------------------------------------------------------------- */static intPipeClose2Proc(    ClientData instanceData,	/* Pointer to PipeInfo structure. */    Tcl_Interp *interp,		/* For error reporting. */    int flags)			/* Flags that indicate which side to close. */{    PipeInfo *pipePtr = (PipeInfo *) instanceData;    Tcl_Channel errChan;    int errorCode, result;    PipeInfo *infoPtr, **nextPtrPtr;    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);    DWORD exitCode;    errorCode = 0;    if ((!flags || (flags == TCL_CLOSE_READ))	    && (pipePtr->readFile != NULL)) {	/*	 * 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 pipe.	 */	if (pipePtr->readThread) {	    /*	     * The thread may already have closed on it's own.  Check it's	     * exit code.	     */	    GetExitCodeThread(pipePtr->readThread, &exitCode);	    if (exitCode == STILL_ACTIVE) {		/*		 * Set the stop event so that if the reader thread is blocked		 * in PipeReaderThread on WaitForMultipleEvents, it will exit		 * cleanly.		 */

⌨️ 快捷键说明

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