📄 tclwinchan.c
字号:
} else { len = strlen(optionName); } if ((len == 0) || ((len > 1) && (strncmp(optionName, "-mode", len) == 0))) { if (GetCommState(infoPtr->handle, &dcb) == 0) { /* * shouldn't we flag an error instead ? */ Tcl_DStringAppendElement(dsPtr, ""); } else { char parity; char *stop; char buf[32]; parity = 'n'; if (dcb.Parity < 4) { parity = "noems"[dcb.Parity]; } stop = (dcb.StopBits == ONESTOPBIT) ? "1" : (dcb.StopBits == ONE5STOPBITS) ? "1.5" : "2"; wsprintf(buf, "%d,%c,%d,%s", dcb.BaudRate, parity, dcb.ByteSize, stop); Tcl_DStringAppendElement(dsPtr, buf); } return TCL_OK; } else { return Tcl_BadChannelOption(interp, optionName, "mode"); }}/* *---------------------------------------------------------------------- * * TclpOpenFileChannel -- * * Open an File based channel on Unix systems. * * Results: * The new channel or NULL. If NULL, the output argument * errorCodePtr is set to a POSIX error. * * Side effects: * May open the channel and may cause creation of a file on the * file system. * *---------------------------------------------------------------------- */Tcl_ChannelTclpOpenFileChannel(interp, fileName, modeString, permissions) Tcl_Interp *interp; /* Interpreter for error reporting; * can be NULL. */ char *fileName; /* Name of file to open. */ char *modeString; /* A list of POSIX open modes or * a string such as "rw". */ int permissions; /* If the open involves creating a * file, with what modes to create * it? */{ FileInfo *infoPtr; int seekFlag, mode, channelPermissions; DWORD accessMode, createMode, shareMode, flags; char *nativeName; Tcl_DString buffer; DCB dcb; Tcl_ChannelType *channelTypePtr; HANDLE handle; if (!initialized) { FileInit(); } mode = TclGetOpenMode(interp, modeString, &seekFlag); if (mode == -1) { return NULL; } nativeName = Tcl_TranslateFileName(interp, fileName, &buffer); if (nativeName == NULL) { return NULL; } switch (mode & (O_RDONLY | O_WRONLY | O_RDWR)) { case O_RDONLY: accessMode = GENERIC_READ; channelPermissions = TCL_READABLE; break; case O_WRONLY: accessMode = GENERIC_WRITE; channelPermissions = TCL_WRITABLE; break; case O_RDWR: accessMode = (GENERIC_READ | GENERIC_WRITE); channelPermissions = (TCL_READABLE | TCL_WRITABLE); break; default: panic("TclpOpenFileChannel: invalid mode value"); break; } /* * Map the creation flags to the NT create mode. */ switch (mode & (O_CREAT | O_EXCL | O_TRUNC)) { case (O_CREAT | O_EXCL): case (O_CREAT | O_EXCL | O_TRUNC): createMode = CREATE_NEW; break; case (O_CREAT | O_TRUNC): createMode = CREATE_ALWAYS; break; case O_CREAT: createMode = OPEN_ALWAYS; break; case O_TRUNC: case (O_TRUNC | O_EXCL): createMode = TRUNCATE_EXISTING; break; default: createMode = OPEN_EXISTING; break; } /* * If the file is being created, get the file attributes from the * permissions argument, else use the existing file attributes. */ if (mode & O_CREAT) { if (permissions & S_IWRITE) { flags = FILE_ATTRIBUTE_NORMAL; } else { flags = FILE_ATTRIBUTE_READONLY; } } else { flags = GetFileAttributes(nativeName); if (flags == 0xFFFFFFFF) { flags = 0; } } /* * Set up the file sharing mode. We want to allow simultaneous access. */ shareMode = FILE_SHARE_READ | FILE_SHARE_WRITE; /* * Now we get to create the file. */ handle = CreateFile(nativeName, accessMode, shareMode, NULL, createMode, flags, (HANDLE) NULL); if (handle == INVALID_HANDLE_VALUE) { DWORD err; openerr: err = GetLastError(); if ((err & 0xffffL) == ERROR_OPEN_FAILED) { err = (mode & O_CREAT) ? ERROR_FILE_EXISTS : ERROR_FILE_NOT_FOUND; } TclWinConvertError(err); if (interp != (Tcl_Interp *) NULL) { Tcl_AppendResult(interp, "couldn't open \"", fileName, "\": ", Tcl_PosixError(interp), (char *) NULL); } Tcl_DStringFree(&buffer); return NULL; } if (GetFileType(handle) == FILE_TYPE_CHAR) { dcb.DCBlength = sizeof( DCB ) ; if (GetCommState(handle, &dcb)) { /* * This is a com port. Reopen it with the correct modes. */ COMMTIMEOUTS cto; CloseHandle(handle); handle = CreateFile(nativeName, accessMode, 0, NULL, OPEN_EXISTING, flags, NULL); if (handle == INVALID_HANDLE_VALUE) { goto openerr; } /* * FileInit the com port. */ SetCommMask(handle, EV_RXCHAR); SetupComm(handle, 4096, 4096); PurgeComm(handle, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR); cto.ReadIntervalTimeout = MAXDWORD; cto.ReadTotalTimeoutMultiplier = 0; cto.ReadTotalTimeoutConstant = 0; cto.WriteTotalTimeoutMultiplier = 0; cto.WriteTotalTimeoutConstant = 0; SetCommTimeouts(handle, &cto); GetCommState(handle, &dcb); SetCommState(handle, &dcb); channelTypePtr = &comChannelType; } else { channelTypePtr = &fileChannelType; } } else { channelTypePtr = &fileChannelType; } Tcl_DStringFree(&buffer); infoPtr = (FileInfo *) ckalloc((unsigned) sizeof(FileInfo)); infoPtr->nextPtr = firstFilePtr; firstFilePtr = infoPtr; infoPtr->validMask = channelPermissions; infoPtr->watchMask = 0; infoPtr->flags = (mode & O_APPEND) ? FILE_APPEND : 0; infoPtr->handle = handle; sprintf(channelName, "file%d", (int) handle); infoPtr->channel = Tcl_CreateChannel(channelTypePtr, channelName, (ClientData) infoPtr, channelPermissions); if (seekFlag) { if (Tcl_Seek(infoPtr->channel, 0, SEEK_END) < 0) { if (interp != (Tcl_Interp *) NULL) { Tcl_AppendResult(interp, "could not seek to end of file on \"", channelName, "\": ", Tcl_PosixError(interp), (char *) NULL); } Tcl_Close(NULL, infoPtr->channel); return NULL; } } /* * Files have default translation of AUTO and ^Z eof char, which * means that a ^Z will be appended to them at close. */ Tcl_SetChannelOption(NULL, infoPtr->channel, "-translation", "auto"); Tcl_SetChannelOption(NULL, infoPtr->channel, "-eofchar", "\032 {}"); return infoPtr->channel;}/* *---------------------------------------------------------------------- * * Tcl_MakeFileChannel -- * * Creates a Tcl_Channel from an existing platform specific file * handle. * * Results: * The Tcl_Channel created around the preexisting file. * * Side effects: * None. * *---------------------------------------------------------------------- */Tcl_ChannelTcl_MakeFileChannel(handle, mode) ClientData handle; /* OS level handle */ int mode; /* ORed combination of TCL_READABLE and * TCL_WRITABLE to indicate file mode. */{ char channelName[20]; FileInfo *infoPtr; if (!initialized) { FileInit(); } if (mode == 0) { return NULL; } sprintf(channelName, "file%d", (int) handle); /* * See if a channel with this handle already exists. */ for (infoPtr = firstFilePtr; infoPtr != NULL; infoPtr = infoPtr->nextPtr) { if (infoPtr->handle == (HANDLE) handle) { return (mode == infoPtr->validMask) ? infoPtr->channel : NULL; } } infoPtr = (FileInfo *) ckalloc((unsigned) sizeof(FileInfo)); infoPtr->nextPtr = firstFilePtr; firstFilePtr = infoPtr; infoPtr->validMask = mode; infoPtr->watchMask = 0; infoPtr->flags = 0; infoPtr->handle = (HANDLE) handle; infoPtr->channel = Tcl_CreateChannel(&fileChannelType, channelName, (ClientData) infoPtr, mode); /* * Windows files have AUTO translation mode and ^Z eof char on input. */ Tcl_SetChannelOption(NULL, infoPtr->channel, "-translation", "auto"); Tcl_SetChannelOption(NULL, infoPtr->channel, "-eofchar", "\032 {}"); return infoPtr->channel;}/* *---------------------------------------------------------------------- * * TclGetDefaultStdChannel -- * * Constructs a channel for the specified standard OS handle. * * Results: * Returns the specified default standard channel, or NULL. * * Side effects: * May cause the creation of a standard channel and the underlying * file. * *---------------------------------------------------------------------- */Tcl_ChannelTclGetDefaultStdChannel(type) int type; /* One of TCL_STDIN, TCL_STDOUT, TCL_STDERR. */{ Tcl_Channel channel; HANDLE handle; int mode; char *bufMode; DWORD handleId; /* Standard handle to retrieve. */ switch (type) { case TCL_STDIN: handleId = STD_INPUT_HANDLE; mode = TCL_READABLE; bufMode = "line"; break; case TCL_STDOUT: handleId = STD_OUTPUT_HANDLE; mode = TCL_WRITABLE; bufMode = "line"; break; case TCL_STDERR: handleId = STD_ERROR_HANDLE; mode = TCL_WRITABLE; bufMode = "none"; break; default: panic("TclGetDefaultStdChannel: Unexpected channel type"); break; } handle = GetStdHandle(handleId); /* * Note that we need to check for 0 because Windows will return 0 if this * is not a console mode application, even though this is not a valid * handle. */ if ((handle == INVALID_HANDLE_VALUE) || (handle == 0)) { return NULL; } channel = Tcl_MakeFileChannel(handle, mode); /* * Set up the normal channel options for stdio handles. */ if ((Tcl_SetChannelOption((Tcl_Interp *) NULL, channel, "-translation", "auto") == TCL_ERROR) || (Tcl_SetChannelOption((Tcl_Interp *) NULL, channel, "-eofchar", "\032 {}") == TCL_ERROR) || (Tcl_SetChannelOption((Tcl_Interp *) NULL, channel, "-buffering", bufMode) == TCL_ERROR)) { Tcl_Close((Tcl_Interp *) NULL, channel); return (Tcl_Channel) NULL; } return channel;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -