/*
* tclEvent.c --
*
* This file provides basic event-managing facilities for Tcl,
* including an event queue, and mechanisms for attaching
* callbacks to certain events.
*
* It also contains the command procedures for the commands
* "after", "vwait", and "update".
*
* Copyright (c) 1990-1994 The Regents of the University of California.
* Copyright (c) 1994-1995 Sun Microsystems, Inc.
*
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
* SCCS: @(#) tclEvent.c 1.132 96/11/12 11:52:27
*/
#include "tclInt.h"
#include "tclPort.h"
/*
* For each file registered in a call to Tcl_CreateFileHandler,
* there is one record of the following type. All of these records
* are chained together into a single list.
*/
typedef struct FileHandler {
* FileHandlerCheckProc checked this file. */
* Tcl_CreateFileHandler. This is NULL
* if the handler was created by
* Tcl_CreateFileHandler2. */
* about (NULL for end of list). */
} FileHandler;
/* List of all file handlers. */
static int fileEventSourceCreated = 0;
/* Zero means that the file event source
* hasn't been registerd with the Tcl
* notifier yet. */
/*
* The following structure is what is added to the Tcl event queue when
* file handlers are ready to fire.
*/
typedef struct FileHandlerEvent {
* all events. */
* to find the FileHandler structure for
* the file (can't point directly to the
* FileHandler structure because it could
* go away while the event is queued). */
/*
* For each timer callback that's pending (either regular or "modal"),
* there is one record of the following type. The normal handlers
* (created by Tcl_CreateTimerHandler) are chained together in a
* list sorted by time (earliest event first).
*/
typedef struct TimerHandler {
* deleted. Not used in modal
* timeouts. */
* end of queue. */
} TimerHandler;
/* First event in queue. */
* hasn't yet been registered with the
* Tcl notifier. */
/*
* The information below describes a stack of modal timeouts managed by
* Tcl_CreateModalTimer and Tcl_DeleteModalTimer. Only the first element
* in the list is used at any given time.
*/
/*
* The following structure is what's added to the Tcl event queue when
* timer handlers are ready to fire.
*/
typedef struct TimerEvent {
* all events. */
* time or earlier are ready
* to fire. */
} TimerEvent;
/*
* There is one of the following structures for each of the
* handlers declared in a call to Tcl_DoWhenIdle. All of the
* currently-active handlers are linked together into a list.
*/
typedef struct IdleHandler {
* recently-created ones. */
} IdleHandler;
/* First in list of all idle handlers. */
/* Last in list (or NULL for empty list). */
* of IdleHandler structures. Increments
* each time Tcl_DoOneEvent starts calling
* idle handlers, so that all old handlers
* can be called without calling any of the
* new ones created by old ones. */
/*
* The data structure below is used by the "after" command to remember
* the command to be executed later. All of the pending "after" commands
* for an interpreter are linked together in a list.
*/
typedef struct AfterInfo {
/* Pointer to the "tclAfter" assocData for
* the interp in which command will be
* executed. */
* be freed when structure is deallocated. */
* cancel it. */
* means that the command is run as an
* idle handler rather than as a timer
* handler. NULL means this is an "after
* idle" handler rather than a
* timer handler. */
* this interpreter. */
int interpType;
} AfterInfo;
/*
* One of the following structures is associated with each interpreter
* for which an "after" command has ever been invoked. A pointer to
* this structure is stored in the AssocData for the "tclAfter" key.
*/
typedef struct AfterAssocData {
* registered. */
* still pending for this interpreter, or
* NULL if none. */
/*
* The data structure below is used to report background errors. One
* such structure is allocated for each error; it holds information
* about the interpreter and the error until bgerror can be invoked
* later as an idle handler.
*/
typedef struct BgError {
* means this error report has been cancelled
* (a previous report generated a break). */
* the error occurred). Malloc-ed. */
* (malloc-ed). */
* (malloc-ed). */
* reports for this interpreter, or NULL
* for end of list. */
} BgError;
/*
* One of the structures below is associated with the "tclBgError"
* assoc data for each interpreter. It keeps track of the head and
* tail of the list of pending background errors for the interpreter.
*/
typedef struct ErrAssocData {
* waiting to be processed for this
* interpreter (NULL if none). */
* waiting to be processed for this
* interpreter (NULL if none). */
} ErrAssocData;
/*
* For each exit handler created with a call to Tcl_CreateExitHandler
* there is a structure of the following type:
*/
typedef struct ExitHandler {
* this application, or NULL for end of list. */
} ExitHandler;
/* First in list of all exit handlers for
* application. */
/*
* Structures of the following type are used during the execution
* of Tcl_WaitForFile, to keep track of the file and timeout.
*/
typedef struct FileWait {
* etc.) */
* Tcl_WaitForFile. */
* the last time through the event loop. */
* the desired conditions is present or the
* timeout period has elapsed. */
} FileWait;
/*
* The following variable is a "secret" indication to Tcl_Exit that
* it should dump out the state of memory before exiting. If the
* value is non-NULL, it gives the name of the file in which to
* dump memory usage information.
*/
/*
* This variable is set to 1 when Tcl_Exit is called, and at the end of
* its work, it is reset to 0. The variable is checked by TclInExit() to
* allow different behavior for exit-time processing, e.g. in closing of
* files and pipes.
*/
static int tclInExit = 0;
/*
* Prototypes for procedures referenced only in this file:
*/
Tcl_Interp *interp));
Tcl_Interp *interp));
static void FileHandlerCheckProc _ANSI_ARGS_((
int flags));
static void FileHandlerSetupProc _ANSI_ARGS_((
char *string));
static void TimerHandlerCheckProc _ANSI_ARGS_((
int flags));
static void TimerHandlerSetupProc _ANSI_ARGS_((
int flags));
/*
*--------------------------------------------------------------
*
* Tcl_CreateFileHandler --
*
* Arrange for a given procedure to be invoked whenever
* a given file becomes readable or writable.
*
* Results:
* None.
*
* Side effects:
* From now on, whenever the I/O channel given by file becomes
* ready in the way indicated by mask, proc will be invoked.
* See the manual entry for details on the calling sequence
* to proc. If file is already registered then the old mask
* and proc and clientData values will be replaced with
* new ones.
*
*--------------------------------------------------------------
*/
void
int mask; /* OR'ed combination of TCL_READABLE,
* TCL_WRITABLE, and TCL_EXCEPTION:
* indicates conditions under which
* proc should be called. */
* selected event. */
{
if (!fileEventSourceCreated) {
(ClientData) NULL);
}
/*
* Make sure the file isn't already registered. Create a
* new record in the normal case where there's no existing
* record.
*/
break;
}
}
}
/*
* The remainder of the initialization below is done regardless
* of whether or not this is a new record or a modification of
* an old one.
*/
}
/*
*--------------------------------------------------------------
*
* Tcl_DeleteFileHandler --
*
* Cancel a previously-arranged callback arrangement for
* a file.
*
* Results:
* None.
*
* Side effects:
* If a callback was previously registered on file, remove it.
*
*--------------------------------------------------------------
*/
void
* callback procedure. */
{
/*
* Find the entry for the given file (and return if there
* isn't one).
*/
return;
}
break;
}
}
/*
* Clean up information in the callback record.
*/
} else {
}
}
/*
*----------------------------------------------------------------------
*
* FileHandlerExitProc --
*
* Cleanup procedure to delete the file event source during exit
* cleanup.
*
* Results:
* None.
*
* Side effects:
* Destroys the file event source.
*
*----------------------------------------------------------------------
*/
/* ARGSUSED */
static void
{
(ClientData) NULL);
}
/*
*----------------------------------------------------------------------
*
* FileHandlerSetupProc --
*
* This procedure is part of the "event source" for file handlers.
* It is invoked by Tcl_DoOneEvent before it calls select (or
* whatever it uses to wait).
*
* Results:
* None.
*
* Side effects:
* Tells the notifier which files should be waited for.
*
*----------------------------------------------------------------------
*/
static void
int flags; /* Flags passed to Tk_DoOneEvent:
* if it doesn't include
* TCL_FILE_EVENTS then we do
* nothing. */
{
if (!(flags & TCL_FILE_EVENTS)) {
return;
}
}
}
}
/*
*----------------------------------------------------------------------
*
* FileHandlerCheckProc --
*
* This procedure is the second part of the "event source" for
* file handlers. It is invoked by Tcl_DoOneEvent after it calls
* select (or whatever it uses to wait for events).
*
* Results:
* None.
*
* Side effects:
* Makes entries on the Tcl event queue for each file that is
* now ready.
*
*----------------------------------------------------------------------
*/
static void
int flags; /* Flags passed to Tk_DoOneEvent:
* if it doesn't include
* TCL_FILE_EVENTS then we do
* nothing. */
{
if (!(flags & TCL_FILE_EVENTS)) {
return;
}
sizeof(FileHandlerEvent));
}
}
}
}
/*
*----------------------------------------------------------------------
*
* FileHandlerEventProc --
*
* This procedure is called by Tcl_DoOneEvent when a file event
* reaches the front of the event queue. This procedure is responsible
* for actually handling the event by invoking the callback for the
* file handler.
*
* 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 file handler's callback procedure does
*
*----------------------------------------------------------------------
*/
static int
int flags; /* Flags that indicate what events to
* handle, such as TCL_FILE_EVENTS. */
{
int mask;
if (!(flags & TCL_FILE_EVENTS)) {
return 0;
}
/*
* Search through the file handlers to find the one whose handle matches
* the event. We do this rather than keeping a pointer to the file
* handler directly in the event, so that the handler can be deleted
* while the event is queued without leaving a dangling pointer.
*/
continue;
}
/*
* The code is tricky for two reasons:
* 1. The file handler's desired events could have changed
* since the time when the event was queued, so AND the
* ready mask with the desired mask.
* 2. The file could have been closed and re-opened since
* the time when the event was queued. This is why the
* ready mask is stored in the file handler rather than
* the queued event: it will be zeroed when a new
* file handler is created for the newly opened file.
*/
if (mask != 0) {
}
break;
}
return 1;
}
/*
*--------------------------------------------------------------
*
* Tcl_CreateTimerHandler --
*
* Arrange for a given procedure to be invoked at a particular
* time in the future.
*
* Results:
* The return value is a token for the timer event, which
* may be used to delete the event before it fires.
*
* Side effects:
* When milliseconds have elapsed, proc will be invoked
* exactly once.
*
*--------------------------------------------------------------
*/
int milliseconds; /* How many milliseconds to wait
* before invoking proc. */
{
static int id = 0;
if (!timerEventSourceCreated) {
(ClientData) NULL);
}
/*
* Compute when the event should fire.
*/
}
/*
* Fill in other fields for the event.
*/
id++;
/*
* Add the event to the queue in the correct position
* (ordered by event firing time).
*/
break;
}
}
} else {
}
return timerHandlerPtr->token;
}
/*
*--------------------------------------------------------------
*
* Tcl_DeleteTimerHandler --
*
* Delete a previously-registered timer handler.
*
* Results:
* None.
*
* Side effects:
* Destroy the timer callback identified by TimerToken,
* so that its associated procedure will not be called.
* If the callback has already fired, or if the given
* token doesn't exist, then nothing happens.
*
*--------------------------------------------------------------
*/
void
* Tcl_DeleteTimerHandler. */
{
continue;
}
} else {
}
ckfree((char *) timerHandlerPtr);
return;
}
}
/*
*--------------------------------------------------------------
*
* Tcl_CreateModalTimeout --
*
* Arrange for a given procedure to be invoked at a particular
* time in the future, independently of all other timer events.
*
* Results:
* None.
*
* Side effects:
* When milliseconds have elapsed, proc will be invoked
* exactly once.
*
*--------------------------------------------------------------
*/
void
int milliseconds; /* How many milliseconds to wait
* before invoking proc. */
{
if (!timerEventSourceCreated) {
(ClientData) NULL);
}
/*
* Compute when the timeout should fire and fill in the other fields
* of the handler.
*/
}
/*
* Push the handler on the top of the modal stack.
*/
}
/*
*--------------------------------------------------------------
*
* Tcl_DeleteModalTimeout --
*
* Remove the topmost modal timer handler from the stack of
* modal handlers.
*
* Results:
* None.
*
* Side effects:
* Destroys the topmost modal timeout handler, which must
* match proc and clientData.
*
*--------------------------------------------------------------
*/
void
{
panic("Tcl_DeleteModalTimeout found timeout stack corrupted");
}
ckfree((char *) timerHandlerPtr);
}
/*
*----------------------------------------------------------------------
*
* TimerHandlerSetupProc --
*
* This procedure is part of the "event source" for timers.
* It is invoked by Tcl_DoOneEvent before it calls select (or
* whatever it uses to wait).
*
* Results:
* None.
*
* Side effects:
* Tells the notifier how long to sleep if it decides to block.
*
*----------------------------------------------------------------------
*/
static void
int flags; /* Flags passed to Tk_DoOneEvent:
* if it doesn't include
* TCL_TIMER_EVENTS then we only
* consider modal timers. */
{
/*
* Find the timer handler (regular or modal) that fires first.
*/
if (!(flags & TCL_TIMER_EVENTS)) {
}
if (timerHandlerPtr != NULL) {
}
}
} else {
}
if (timerHandlerPtr == NULL) {
return;
}
}
}
}
/*
*----------------------------------------------------------------------
*
* TimerHandlerCheckProc --
*
* This procedure is the second part of the "event source" for
* file handlers. It is invoked by Tcl_DoOneEvent after it calls
* select (or whatever it uses to wait for events).
*
* Results:
* None.
*
* Side effects:
* Makes entries on the Tcl event queue for each file that is
* now ready.
*
*----------------------------------------------------------------------
*/
static void
int flags; /* Flags passed to Tk_DoOneEvent:
* if it doesn't include
* TCL_TIMER_EVENTS then we only
* consider modal timeouts. */
{
triggered = 0;
gotTime = 0;
gotTime = 1;
triggered = 1;
}
}
if (timerHandlerPtr != NULL) {
if (!gotTime) {
}
triggered = 1;
}
}
if (triggered) {
}
}
/*
*----------------------------------------------------------------------
*
* TimerHandlerExitProc --
*
* Callback invoked during exit cleanup to destroy the timer event
* source.
*
* Results:
* None.
*
* Side effects:
* Destroys the timer event source.
*
*----------------------------------------------------------------------
*/
/* ARGSUSED */
static void
{
(ClientData) NULL);
}
/*
*----------------------------------------------------------------------
*
* TimerHandlerEventProc --
*
* This procedure is called by Tcl_DoOneEvent when a timer event
* reaches the front of the event queue. This procedure handles
* the event by invoking the callbacks for all timers that are
* ready.
*
* 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_TIMER_EVENTS flag bit isn't set.
*
* Side effects:
* Whatever the timer handler callback procedures do.
*
*----------------------------------------------------------------------
*/
static int
int flags; /* Flags that indicate what events to
* handle, such as TCL_FILE_EVENTS. */
{
/*
* Invoke the current modal timeout first, if there is one and
* it has triggered.
*/
if (firstModalHandlerPtr != NULL) {
}
}
/*
* Invoke any normal timers that have fired.
*/
if (!(flags & TCL_TIMER_EVENTS)) {
return 1;
}
while (1) {
if (timerHandlerPtr == NULL) {
break;
}
break;
}
/*
* Remove the handler from the queue before invoking it,
* to avoid potential reentrancy problems.
*/
ckfree((char *) timerHandlerPtr);
}
return 1;
}
/*
*--------------------------------------------------------------
*
* Tcl_DoWhenIdle --
*
* Arrange for proc to be invoked the next time the system is
* idle (i.e., just before the next time that Tcl_DoOneEvent
* would have to wait for something to happen).
*
* Results:
* None.
*
* Side effects:
* Proc will eventually be called, with clientData as argument.
* See the manual entry for details.
*
*--------------------------------------------------------------
*/
void
{
if (lastIdlePtr == NULL) {
} else {
}
}
/*
*----------------------------------------------------------------------
*
* Tcl_CancelIdleCall --
*
* If there are any when-idle calls requested to a given procedure
* with given clientData, cancel all of them.
*
* Results:
* None.
*
* Side effects:
* If the proc/clientData combination were on the when-idle list,
* they are removed so that they will never be called.
*
*----------------------------------------------------------------------
*/
void
{
} else {
}
return;
}
}
}
}
/*
*----------------------------------------------------------------------
*
* TclIdlePending --
*
* This function is called by the notifier subsystem to determine
* whether there are any idle handlers currently scheduled.
*
* Results:
* Returns 0 if the idle list is empty, otherwise it returns 1.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
int
{
}
/*
*----------------------------------------------------------------------
*
* TclServiceIdle --
*
* This procedure is invoked by the notifier when it becomes idle.
*
* Results:
* The return value is 1 if the procedure actually found an idle
* handler to invoke. If no handler was found then 0 is returned.
*
* Side effects:
* Invokes all pending idle handlers.
*
*----------------------------------------------------------------------
*/
int
{
int oldGeneration;
int foundIdle;
return 0;
}
foundIdle = 0;
/*
* The code below is trickier than it may look, for the following
* reasons:
*
* 1. New handlers can get added to the list while the current
* one is being processed. If new ones get added, we don't
* want to process them during this pass through the list (want
* to check for other work to do first). This is implemented
* using the generation number in the handler: new handlers
* will have a different generation than any of the ones currently
* on the list.
* 2. The handler can call Tcl_DoOneEvent, so we have to remove
* the handler from the list before calling it. Otherwise an
* infinite loop could result.
* 3. Tcl_CancelIdleCall can be called to remove an element from
* the list while a handler is executing, so the list could
* change structure during the call.
*/
lastIdlePtr = NULL;
}
foundIdle = 1;
}
return foundIdle;
}
/*
*----------------------------------------------------------------------
*
* Tcl_BackgroundError --
*
* This procedure is invoked to handle errors that occur in Tcl
* commands that are invoked in "background" (e.g. from event or
* timer bindings).
*
* Results:
* None.
*
* Side effects:
* The command "bgerror" is invoked later as an idle handler to
* process the error, passing it the error message. If that fails,
* then an error message is output on stderr.
*
*----------------------------------------------------------------------
*/
void
* occurred. */
{
char *varValue;
/*
* The Tcl_AddErrorInfo call below (with an empty string) ensures that
* errorInfo gets properly set. It's needed in cases where the error
* came from a utility procedure like Tcl_GetVar instead of Tcl_Eval;
* in these cases errorInfo still won't have been set when this
* procedure is called.
*/
+ 1));
}
varValue = "";
}
(Tcl_InterpDeleteProc **) NULL);
/*
* This is the first time a background error has occurred in
* this interpreter. Create associated data to keep track of
* pending error reports.
*/
(ClientData) assocPtr);
}
} else {
}
}
/*
*----------------------------------------------------------------------
*
* HandleBgErrors --
*
* This procedure is invoked as an idle handler to process all of
* the accumulated background errors.
*
* Results:
* None.
*
* Side effects:
* Depends on what actions "bgerror" takes for the errors.
*
*----------------------------------------------------------------------
*/
static void
{
char *command;
int code;
goto doneWithReport;
}
/*
* Restore important state variables to what they were at
* the time the error occurred.
*/
/*
* Create and invoke the bgerror command.
*/
argv[0] = "bgerror";
/*
* We have to get the error output channel at the latest possible
* time, because the eval (above) might have changed the channel.
*/
"\"bgerror\" is an invalid command name or ambiguous abbreviation")
== 0) {
} else {
"bgerror failed to handle background error.\n",
-1);
-1);
}
}
/*
* Break means cancel any remaining error reports for this
* interpreter.
*/
}
}
}
/*
* Discard the command and the information about the error report.
*/
}
}
/*
*----------------------------------------------------------------------
*
* BgErrorDeleteProc --
*
* This procedure is associated with the "tclBgError" assoc data
* for an interpreter; it is invoked when the interpreter is
* deleted in order to free the information assoicated with any
* pending error reports.
*
* Results:
* None.
*
* Side effects:
* Background error information is freed: if there were any
* pending error reports, they are cancelled.
*
*----------------------------------------------------------------------
*/
static void
{
}
}
/*
*----------------------------------------------------------------------
*
* Tcl_CreateExitHandler --
*
* Arrange for a given procedure to be invoked just before the
* application exits.
*
* Results:
* None.
*
* Side effects:
* Proc will be invoked with clientData as argument when the
* application exits.
*
*----------------------------------------------------------------------
*/
void
{
}
/*
*----------------------------------------------------------------------
*
* Tcl_DeleteExitHandler --
*
* This procedure cancels an existing exit handler matching proc
* and clientData, if such a handler exits.
*
* Results:
* None.
*
* Side effects:
* If there is an exit handler corresponding to proc and clientData
* then it is cancelled; if no such handler exists then nothing
* happens.
*
*----------------------------------------------------------------------
*/
void
{
} else {
}
return;
}
}
}
/*
*----------------------------------------------------------------------
*
* Tcl_Exit --
*
* This procedure is called to terminate the application.
*
* Results:
* None.
*
* Side effects:
* All existing exit handlers are invoked, then the application
* ends.
*
*----------------------------------------------------------------------
*/
void
int status; /* Exit status for application; typically
* 0 for normal return, 1 for error return. */
{
tclInExit = 1;
/*
* Be careful to remove the handler from the list before invoking
* its callback. This protects us against double-freeing if the
* callback should call Tcl_DeleteExitHandler on itself.
*/
}
#ifdef TCL_MEM_DEBUG
if (tclMemDumpFileName != NULL) {
}
#endif
tclInExit = 0;
}
/*
*----------------------------------------------------------------------
*
* TclInExit --
*
* Determines if we are in the middle of exit-time cleanup.
*
* Results:
* If we are in the middle of exiting, 1, otherwise 0.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
int
{
return tclInExit;
}
/*
*----------------------------------------------------------------------
*
* Tcl_AfterCmd --
*
* This procedure is invoked to process the "after" Tcl command.
* See the user documentation for details on what it does.
*
* Results:
* A standard Tcl result.
*
* Side effects:
* See the user documentation.
*
*----------------------------------------------------------------------
*/
/* ARGSUSED */
int
* this interpreter, or NULL if the assocData
* hasn't been created yet.*/
int argc; /* Number of arguments. */
char **argv; /* Argument strings. */
{
/*
* The variable below is used to generate unique identifiers for
* after commands. This id can wrap around, which can potentially
* cause problems. However, there are not likely to be problems
* in practice, because after commands can only be requested to
* about a month in the future, and wrap-around is unlikely to
* occur in less than about 1-10 years. Thus it's unlikely that
* any old ids will still be around when wrap-around occurs.
*/
int ms;
if (argc < 2) {
return TCL_ERROR;
}
/*
* Create the "after" information associated for this interpreter,
* if it doesn't already exist. Associate it with the command too,
* so that it will be passed in as the ClientData argument in the
* future.
*/
(ClientData) assocPtr);
}
/*
* Parse the command.
*/
return TCL_ERROR;
}
if (ms < 0) {
ms = 0;
}
if (argc == 2) {
return TCL_OK;
}
if (argc == 3) {
} else {
}
nextId += 1;
(ClientData) afterPtr);
char *arg;
if (argc < 3) {
return TCL_ERROR;
}
if (argc == 3) {
} else {
}
break;
}
}
}
}
} else {
}
}
&& (length >= 2)) {
if (argc < 3) {
return TCL_ERROR;
}
if (argc == 3) {
} else {
}
nextId += 1;
&& (length >= 2)) {
if (argc == 2) {
}
}
return TCL_OK;
}
if (argc != 3) {
return TCL_ERROR;
}
"\" doesn't exist", (char *) NULL);
return TCL_ERROR;
}
} else {
"\": must be cancel, idle, info, or a number",
(char *) NULL);
return TCL_ERROR;
}
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
* GetAfterEvent --
*
* This procedure parses an "after" id such as "after#4" and
* returns a pointer to the AfterInfo structure.
*
* Results:
* The return value is either a pointer to an AfterInfo structure,
* if one is found that corresponds to "string" and is for interp,
* or NULL if no corresponding after event can be found.
*
* Side effects:
* None.
*
*----------------------------------------------------------------------
*/
static AfterInfo *
* this interpreter. */
char *string; /* Textual identifier for after event, such
* as "after#6". */
{
int id;
char *end;
return NULL;
}
string += 6;
return NULL;
}
return afterPtr;
}
}
return NULL;
}
/*
*----------------------------------------------------------------------
*
* AfterProc --
*
* Timer callback to execute commands registered with the
* "after" command.
*
* Results:
* None.
*
* Side effects:
* Executes whatever command was specified. If the command
* returns an error, then the command "bgerror" is invoked
* to process the error; if bgerror fails then information
* about the error is output on stderr.
*
*----------------------------------------------------------------------
*/
static void
{
int result;
/*
* First remove the callback from our list of callbacks; otherwise
* someone could delete the callback while it's being executed, which
* could cause a core dump.
*/
} else {
/* Empty loop body. */
}
}
/*
* Execute the callback.
*/
}
/*
* Free the memory for the callback.
*/
}
/*
*----------------------------------------------------------------------
*
* FreeAfterPtr --
*
* This procedure removes an "after" command from the list of
* those that are pending and frees its resources. This procedure
* does *not* cancel the timer handler; if that's needed, the
* caller must do it.
*
* Results:
* None.
*
* Side effects:
* The memory associated with afterPtr is released.
*
*----------------------------------------------------------------------
*/
static void
{
} else {
/* Empty loop body. */
}
}
}
/*
*----------------------------------------------------------------------
*
* AfterCleanupProc --
*
* This procedure is invoked whenever an interpreter is deleted
* to cleanup the AssocData for "tclAfter".
*
* Results:
* None.
*
* Side effects:
* After commands are removed.
*
*----------------------------------------------------------------------
*/
/* ARGSUSED */
static void
* interpreter. */
{
} else {
}
}
}
/*
*----------------------------------------------------------------------
*
* Tcl_VwaitCmd --
*
* This procedure is invoked to process the "vwait" Tcl command.
* See the user documentation for details on what it does.
*
* Results:
* A standard Tcl result.
*
* Side effects:
* See the user documentation.
*
*----------------------------------------------------------------------
*/
/* ARGSUSED */
int
int argc; /* Number of arguments. */
char **argv; /* Argument strings. */
{
if (argc != 2) {
return TCL_ERROR;
}
return TCL_ERROR;
};
done = 0;
foundEvent = 1;
while (!done && foundEvent) {
foundEvent = Tcl_DoOneEvent(0);
}
/*
* Clear out the interpreter's result, since it may have been set
* by event handlers.
*/
if (!foundEvent) {
"\": would wait forever", (char *) NULL);
return TCL_ERROR;
}
return TCL_OK;
}
/* ARGSUSED */
static char *
char *name1; /* Name of variable. */
char *name2; /* Second part of variable name. */
int flags; /* Information about what happened. */
{
*donePtr = 1;
return (char *) NULL;
}
/*
*----------------------------------------------------------------------
*
* Tcl_UpdateCmd --
*
* This procedure is invoked to process the "update" Tcl command.
* See the user documentation for details on what it does.
*
* Results:
* A standard Tcl result.
*
* Side effects:
* See the user documentation.
*
*----------------------------------------------------------------------
*/
/* ARGSUSED */
int
int argc; /* Number of arguments. */
char **argv; /* Argument strings. */
{
* compiler warnings. */
if (argc == 1) {
} else if (argc == 2) {
"\": must be idletasks", (char *) NULL);
return TCL_ERROR;
}
} else {
return TCL_ERROR;
}
while (Tcl_DoOneEvent(flags) != 0) {
/* Empty loop body */
}
/*
* Must clear the interpreter's result because event handlers could
* have executed commands.
*/
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
* TclWaitForFile --
*
* This procedure waits synchronously for a file to become readable
* or writable, with an optional timeout.
*
* Results:
* The return value is an OR'ed combination of TCL_READABLE,
* TCL_WRITABLE, and TCL_EXCEPTION, indicating the conditions
* that are present on file at the time of the return. This
* procedure will not return until either "timeout" milliseconds
* have elapsed or at least one of the conditions given by mask
* has occurred for file (a return value of 0 means that a timeout
* occurred). No normal events will be serviced during the
* execution of this procedure.
*
* Side effects:
* Time passes.
*
*----------------------------------------------------------------------
*/
int
int mask; /* What to wait for: OR'ed combination of
* TCL_READABLE, TCL_WRITABLE, and
* TCL_EXCEPTION. */
int timeout; /* Maximum amount of time to wait for one
* of the conditions in mask to occur, in
* milliseconds. A value of 0 means don't
* wait at all, and a value of -1 means
* wait forever. */
{
int present;
/*
* If there is a non-zero finite timeout, compute the time when
* we give up.
*/
if (timeout > 0) {
TclpGetTime(&now);
}
}
/*
* Loop in a mini-event loop of our own, waiting for either the
* file to become ready or a timeout to occur.
*/
while (1) {
if (timeout > 0) {
}
}
} else if (timeout == 0) {
} else {
}
if (present != 0) {
break;
}
if (timeout == 0) {
break;
}
TclpGetTime(&now);
break;
}
}
return present;
}