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

📄 tclwinchan.c

📁 这是leon3处理器的交叉编译链
💻 C
📖 第 1 页 / 共 3 页
字号:
/*  * tclWinChan.c * *	Channel drivers for Windows channels based on files, command *	pipes and TCP sockets. * * Copyright (c) 1995-1997 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: tclWinChan.c,v 1.24 2002/07/08 10:08:58 vincentdarley Exp $ */#include "tclWinInt.h"/* * State flags used in the info structures below. */#define FILE_PENDING	(1<<0)	/* Message is pending in the queue. */#define FILE_ASYNC	(1<<1)	/* Channel is non-blocking. */#define FILE_APPEND	(1<<2)	/* File is in append mode. */#define FILE_TYPE_SERIAL  (FILE_TYPE_PIPE+1)#define FILE_TYPE_CONSOLE (FILE_TYPE_PIPE+2)/* * The following structure contains per-instance data for a file based channel. */typedef struct FileInfo {    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. */    HANDLE handle;		/* Input/output file. */    struct FileInfo *nextPtr;	/* Pointer to next registered file. */    int dirty;                  /* Boolean flag. Set if the OS may have data				 * pending on the channel */} FileInfo;typedef struct ThreadSpecificData {    /*     * List of all file channels currently open.     */    FileInfo *firstFilePtr;} ThreadSpecificData;static Tcl_ThreadDataKey dataKey;/* * The following structure is what is added to the Tcl event queue when * file events are generated. */typedef struct FileEvent {    Tcl_Event header;		/* Information that is standard for				 * all events. */    FileInfo *infoPtr;		/* Pointer to file info structure.  Note				 * that we still have to verify that the				 * file exists before dereferencing this				 * pointer. */} FileEvent;/* * Static routines for this file: */static int		FileBlockProc _ANSI_ARGS_((ClientData instanceData,			    int mode));static void		FileChannelExitHandler _ANSI_ARGS_((		            ClientData clientData));static void		FileCheckProc _ANSI_ARGS_((ClientData clientData,			    int flags));static int		FileCloseProc _ANSI_ARGS_((ClientData instanceData,		            Tcl_Interp *interp));static int		FileEventProc _ANSI_ARGS_((Tcl_Event *evPtr, 			    int flags));static int		FileGetHandleProc _ANSI_ARGS_((ClientData instanceData,		            int direction, ClientData *handlePtr));static ThreadSpecificData *FileInit _ANSI_ARGS_((void));static int		FileInputProc _ANSI_ARGS_((ClientData instanceData,	            	    char *buf, int toRead, int *errorCode));static int		FileOutputProc _ANSI_ARGS_((ClientData instanceData,			    CONST char *buf, int toWrite, int *errorCode));static int		FileSeekProc _ANSI_ARGS_((ClientData instanceData,			    long offset, int mode, int *errorCode));static Tcl_WideInt	FileWideSeekProc _ANSI_ARGS_((ClientData instanceData,			    Tcl_WideInt offset, int mode, int *errorCode));static void		FileSetupProc _ANSI_ARGS_((ClientData clientData,			    int flags));static void		FileWatchProc _ANSI_ARGS_((ClientData instanceData,		            int mask));			    /* * This structure describes the channel type structure for file based IO. */static Tcl_ChannelType fileChannelType = {    "file",			/* Type name. */    TCL_CHANNEL_VERSION_3,	/* v3 channel */    FileCloseProc,		/* Close proc. */    FileInputProc,		/* Input proc. */    FileOutputProc,		/* Output proc. */    FileSeekProc,		/* Seek proc. */    NULL,			/* Set option proc. */    NULL,			/* Get option proc. */    FileWatchProc,		/* Set up the notifier to watch the channel. */    FileGetHandleProc,		/* Get an OS handle from channel. */    NULL,			/* close2proc. */    FileBlockProc,		/* Set blocking or non-blocking mode.*/    NULL,			/* flush proc. */    NULL,			/* handler proc. */    FileWideSeekProc,		/* Wide seek proc. */};#ifdef HAVE_NO_SEHstatic void *ESP __attribute__ ((used));static void *EBP __attribute__ ((used));#endif /* HAVE_NO_SEH *//* *---------------------------------------------------------------------- * * FileInit -- * *	This function creates the window used to simulate file events. * * Results: *	None. * * Side effects: *	Creates a new window and creates an exit handler.  * *---------------------------------------------------------------------- */static ThreadSpecificData *FileInit(){    ThreadSpecificData *tsdPtr =	(ThreadSpecificData *)TclThreadDataKeyGet(&dataKey);    if (tsdPtr == NULL) {	tsdPtr = TCL_TSD_INIT(&dataKey);	tsdPtr->firstFilePtr = NULL;	Tcl_CreateEventSource(FileSetupProc, FileCheckProc, NULL);	Tcl_CreateThreadExitHandler(FileChannelExitHandler, NULL);    }    return tsdPtr;}/* *---------------------------------------------------------------------- * * FileChannelExitHandler -- * *	This function is called to cleanup the channel driver before *	Tcl is unloaded. * * Results: *	None. * * Side effects: *	Destroys the communication window. * *---------------------------------------------------------------------- */static voidFileChannelExitHandler(clientData)    ClientData clientData;	/* Old window proc */{    Tcl_DeleteEventSource(FileSetupProc, FileCheckProc, NULL);}/* *---------------------------------------------------------------------- * * FileSetupProc -- * *	This procedure is invoked before Tcl_DoOneEvent blocks waiting *	for an event. * * Results: *	None. * * Side effects: *	Adjusts the block time if needed. * *---------------------------------------------------------------------- */voidFileSetupProc(data, flags)    ClientData data;		/* Not used. */    int flags;			/* Event flags as passed to Tcl_DoOneEvent. */{    FileInfo *infoPtr;    Tcl_Time blockTime = { 0, 0 };    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);    if (!(flags & TCL_FILE_EVENTS)) {	return;    }        /*     * Check to see if there is a ready file.  If so, poll.     */    for (infoPtr = tsdPtr->firstFilePtr; infoPtr != NULL; 	    infoPtr = infoPtr->nextPtr) {	if (infoPtr->watchMask) {	    Tcl_SetMaxBlockTime(&blockTime);	    break;	}    }}/* *---------------------------------------------------------------------- * * FileCheckProc -- * *	This procedure is called by Tcl_DoOneEvent to check the file *	event source for events.  * * Results: *	None. * * Side effects: *	May queue an event. * *---------------------------------------------------------------------- */static voidFileCheckProc(data, flags)    ClientData data;		/* Not used. */    int flags;			/* Event flags as passed to Tcl_DoOneEvent. */{    FileEvent *evPtr;    FileInfo *infoPtr;    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);    if (!(flags & TCL_FILE_EVENTS)) {	return;    }        /*     * Queue events for any ready files that don't already have events     * queued (caused by persistent states that won't generate WinSock     * events).     */    for (infoPtr = tsdPtr->firstFilePtr; infoPtr != NULL; 	    infoPtr = infoPtr->nextPtr) {	if (infoPtr->watchMask && !(infoPtr->flags & FILE_PENDING)) {	    infoPtr->flags |= FILE_PENDING;	    evPtr = (FileEvent *) ckalloc(sizeof(FileEvent));	    evPtr->header.proc = FileEventProc;	    evPtr->infoPtr = infoPtr;	    Tcl_QueueEvent((Tcl_Event *) evPtr, TCL_QUEUE_TAIL);	}    }}/*---------------------------------------------------------------------- * * FileEventProc -- * *	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 file. * * 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 intFileEventProc(evPtr, flags)    Tcl_Event *evPtr;		/* Event to service. */    int flags;			/* Flags that indicate what events to				 * handle, such as TCL_FILE_EVENTS. */{    FileEvent *fileEvPtr = (FileEvent *)evPtr;    FileInfo *infoPtr;    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);    if (!(flags & TCL_FILE_EVENTS)) {	return 0;    }    /*     * Search through the list of watched files for the one whose handle     * matches the event.  We do this rather than simply dereferencing     * the handle in the event so that files can be deleted while the     * event is in the queue.     */    for (infoPtr = tsdPtr->firstFilePtr; infoPtr != NULL;	    infoPtr = infoPtr->nextPtr) {	if (fileEvPtr->infoPtr == infoPtr) {	    infoPtr->flags &= ~(FILE_PENDING);	    Tcl_NotifyChannel(infoPtr->channel, infoPtr->watchMask);	    break;	}    }    return 1;}/* *---------------------------------------------------------------------- * * FileBlockProc -- * *	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 intFileBlockProc(instanceData, mode)    ClientData instanceData;	/* Instance data for channel. */    int mode;			/* TCL_MODE_BLOCKING or                                 * TCL_MODE_NONBLOCKING. */{    FileInfo *infoPtr = (FileInfo *) instanceData;        /*     * Files 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 |= FILE_ASYNC;    } else {	infoPtr->flags &= ~(FILE_ASYNC);    }    return 0;}/* *---------------------------------------------------------------------- * * FileCloseProc -- * *	Closes the IO channel. * * Results: *	0 if successful, the value of errno if failed. * * Side effects: *	Closes the physical channel * *---------------------------------------------------------------------- */static intFileCloseProc(instanceData, interp)    ClientData instanceData;	/* Pointer to FileInfo structure. */    Tcl_Interp *interp;		/* Not used. */{    FileInfo *fileInfoPtr = (FileInfo *) instanceData;    FileInfo **nextPtrPtr;    int errorCode = 0;    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);    /*     * Remove the file from the watch list.     */    FileWatchProc(instanceData, 0);    /*     * 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) != fileInfoPtr->handle)		&& (GetStdHandle(STD_OUTPUT_HANDLE) != fileInfoPtr->handle)		&& (GetStdHandle(STD_ERROR_HANDLE) != fileInfoPtr->handle))) {	if (CloseHandle(fileInfoPtr->handle) == FALSE) {	    TclWinConvertError(GetLastError());	    errorCode = errno;	}    }    for (nextPtrPtr = &(tsdPtr->firstFilePtr); (*nextPtrPtr) != NULL;	 nextPtrPtr = &((*nextPtrPtr)->nextPtr)) {	if ((*nextPtrPtr) == fileInfoPtr) {	    (*nextPtrPtr) = fileInfoPtr->nextPtr;	    break;	}    }    ckfree((char *)fileInfoPtr);    return errorCode;}/* *---------------------------------------------------------------------- * * FileSeekProc -- * *	Seeks on a file-based 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. * *----------------------------------------------------------------------

⌨️ 快捷键说明

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