📄 tclmacchan.c
字号:
return errorCode;}/* *---------------------------------------------------------------------- * * CommonGetHandle -- * * Called from Tcl_GetChannelFile to retrieve OS handles from inside * a file based channel. * * Results: * The appropriate handle or NULL if not present. * * Side effects: * None. * *---------------------------------------------------------------------- */static intCommonGetHandle( ClientData instanceData, /* The file state. */ int direction, /* Which handle to retrieve? */ ClientData *handlePtr){ if ((direction == TCL_READABLE) || (direction == TCL_WRITABLE)) { *handlePtr = (ClientData) ((FileState*)instanceData)->fileRef; return TCL_OK; } return TCL_ERROR;}/* *---------------------------------------------------------------------- * * StdIOInput -- * * 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. * *---------------------------------------------------------------------- */intStdIOInput( ClientData instanceData, /* Unused. */ char *buf, /* Where to store data read. */ int bufSize, /* How much space is available * in the buffer? */ int *errorCode) /* Where to store error code. */{ int fd; int bytesRead; /* How many bytes were read? */ *errorCode = 0; errno = 0; fd = (int) ((FileState*)instanceData)->fileRef; bytesRead = read(fd, buf, (size_t) bufSize); if (bytesRead > -1) { return bytesRead; } *errorCode = errno; return -1;}/* *---------------------------------------------------------------------- * * StdIOOutput-- * * 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 intStdIOOutput( ClientData instanceData, /* Unused. */ char *buf, /* The data buffer. */ int toWrite, /* How many bytes to write? */ int *errorCode) /* Where to store error code. */{ int written; int fd; *errorCode = 0; errno = 0; fd = (int) ((FileState*)instanceData)->fileRef; written = write(fd, buf, (size_t) toWrite); if (written > -1) { return written; } *errorCode = errno; return -1;}/* *---------------------------------------------------------------------- * * StdIOSeek -- * * Seeks on an IO channel. Returns the new position. * * Results: * -1 if failed, the new position if successful. If failed, it * also sets *errorCodePtr to the error code. * * Side effects: * Moves the location at which the channel will be accessed in * future operations. * *---------------------------------------------------------------------- */static intStdIOSeek( ClientData instanceData, /* Unused. */ long offset, /* Offset to seek to. */ int mode, /* Relative to where * should we seek? */ int *errorCodePtr) /* To store error code. */{ int newLoc; int fd; *errorCodePtr = 0; fd = (int) ((FileState*)instanceData)->fileRef; newLoc = lseek(fd, offset, mode); if (newLoc > -1) { return newLoc; } *errorCodePtr = errno; return -1;}/* *---------------------------------------------------------------------- * * Tcl_PidObjCmd -- * * This procedure is invoked to process the "pid" Tcl command. * See the user documentation for details on what it does. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ /* ARGSUSED */intTcl_PidObjCmd(dummy, interp, objc, objv) ClientData dummy; /* Not used. */ Tcl_Interp *interp; /* Current interpreter. */ int objc; /* Number of arguments. */ Tcl_Obj *CONST *objv; /* Argument strings. */{ ProcessSerialNumber psn; char buf[20]; Tcl_Channel chan; Tcl_Obj *resultPtr; if (objc > 2) { Tcl_WrongNumArgs(interp, 1, objv, "?channelId?"); return TCL_ERROR; } if (objc == 1) { resultPtr = Tcl_GetObjResult(interp); GetCurrentProcess(&psn); sprintf(buf, "0x%08x%08x", psn.highLongOfPSN, psn.lowLongOfPSN); Tcl_SetStringObj(resultPtr, buf, -1); } else { chan = Tcl_GetChannel(interp, Tcl_GetStringFromObj(objv[1], NULL), NULL); if (chan == (Tcl_Channel) NULL) { return TCL_ERROR; } /* * We can't create pipelines on the Mac so * this will always return an empty list. */ } return TCL_OK;}/* *---------------------------------------------------------------------- * * 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( int type) /* One of TCL_STDIN, TCL_STDOUT, TCL_STDERR. */{ Tcl_Channel channel = NULL; int fd = 0; /* Initializations needed to prevent */ int mode = 0; /* compiler warning (used before set). */ char *bufMode = NULL; char channelName[20]; int channelPermissions; FileState *fileState; /* * If the channels were not created yet, create them now and * store them in the static variables. */ switch (type) { case TCL_STDIN: fd = 0; channelPermissions = TCL_READABLE; bufMode = "line"; break; case TCL_STDOUT: fd = 1; channelPermissions = TCL_WRITABLE; bufMode = "line"; break; case TCL_STDERR: fd = 2; channelPermissions = TCL_WRITABLE; bufMode = "none"; break; default: panic("TclGetDefaultStdChannel: Unexpected channel type"); break; } sprintf(channelName, "console%d", (int) fd); fileState = (FileState *) ckalloc((unsigned) sizeof(FileState)); channel = Tcl_CreateChannel(&consoleChannelType, channelName, (ClientData) fileState, channelPermissions); fileState->fileChan = channel; fileState->fileRef = fd; /* * Set up the normal channel options for stdio handles. */ Tcl_SetChannelOption(NULL, channel, "-translation", "cr"); Tcl_SetChannelOption(NULL, channel, "-buffering", bufMode); return channel;}/* *---------------------------------------------------------------------- * * 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( 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? */{ Tcl_Channel chan; int mode; char *nativeName; Tcl_DString buffer; int errorCode; mode = GetOpenMode(interp, modeString); if (mode == -1) { return NULL; } nativeName = Tcl_TranslateFileName(interp, fileName, &buffer); if (nativeName == NULL) { return NULL; } chan = OpenFileChannel(nativeName, mode, permissions, &errorCode); Tcl_DStringFree(&buffer); if (chan == NULL) { Tcl_SetErrno(errorCode); if (interp != (Tcl_Interp *) NULL) { Tcl_AppendResult(interp, "couldn't open \"", fileName, "\": ", Tcl_PosixError(interp), (char *) NULL); } return NULL; } return chan;}/* *---------------------------------------------------------------------- * * OpenFileChannel-- * * Opens a Macintosh file and creates a Tcl channel to control it. * * Results: * A Tcl channel. * * Side effects: * Will open a Macintosh file. * *---------------------------------------------------------------------- */static Tcl_ChannelOpenFileChannel( char *fileName, /* Name of file to open. */ int mode, /* Mode for opening file. */ int permissions, /* If the open involves creating a * file, with what modes to create * it? */ int *errorCodePtr) /* Where to store error code. */{ int channelPermissions; Tcl_Channel chan; char macPermision; FSSpec fileSpec; OSErr err; short fileRef; FileState *fileState; char channelName[64]; /* * Note we use fsRdWrShPerm instead of fsRdWrPerm which allows shared * writes on a file. This isn't common on a mac but is common with * Windows and UNIX and the feature is used by Tcl. */ switch (mode & (TCL_RDONLY | TCL_WRONLY | TCL_RDWR)) { case TCL_RDWR: channelPermissions = (TCL_READABLE | TCL_WRITABLE); macPermision = fsRdWrShPerm; break; case TCL_WRONLY: /* * Mac's fsRdPerm permission actually defaults to fsRdWrPerm because * the Mac OS doesn't realy support write only access. We explicitly * set the permission fsRdWrShPerm so that we can have shared write * access. */ channelPermissions = TCL_WRITABLE; macPermision = fsRdWrShPerm; break; case TCL_RDONLY: default: channelPermissions = TCL_READABLE; macPermision = fsRdPerm; break; } err = FSpLocationFromPath(strlen(fileName), fileName, &fileSpec); if ((err != noErr) && (err != fnfErr)) { *errorCodePtr = errno = TclMacOSErrorToPosixError(err); Tcl_SetErrno(errno); return NULL; } if ((err == fnfErr) && (mode & TCL_CREAT)) { err = HCreate(fileSpec.vRefNum, fileSpec.parID, fileSpec.name, 'MPW ', 'TEXT'); if (err != noErr) { *errorCodePtr = errno = TclMacOSErrorToPosixError(err); Tcl_SetErrno(errno); return NULL; } } else if ((mode & TCL_CREAT) && (mode & TCL_EXCL)) { *errorCodePtr = errno = EEXIST; Tcl_SetErrno(errno); return NULL; } err = HOpenDF(fileSpec.vRefNum, fileSpec.parID, fileSpec.name, macPermision, &fileRef); if (err != noErr) { *errorCodePtr = errno = TclMacOSErrorToPosixError(err); Tcl_SetErrno(errno); return NULL; } if (mode & TCL_TRUNC) { SetEOF(fileRef, 0); } sprintf(channelName, "file%d", (int) fileRef); fileState = (FileState *) ckalloc((unsigned) sizeof(FileState)); chan = Tcl_CreateChannel(&fileChannelType, channelName, (ClientData) fileState, channelPermissions); if (chan == (Tcl_Channel) NULL) { *errorCodePtr = errno = EFAULT; Tcl_SetErrno(errno); FSClose(fileRef); ckfree((char *) fileState); return NULL; } fileState->fileChan = chan; fileState->volumeRef = fileSpec.vRefNum; fileState->fileRef = fileRef; fileState->pending = 0; fileState->watchMask = 0; if (mode & TCL_ALWAYS_APPEND) { fileState->appendMode = true; } else { fileState->appendMode = false; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -