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

📄 tclevent.c

📁 linux系统下的音频通信
💻 C
📖 第 1 页 / 共 2 页
字号:
/*  * tclEvent.c -- * *	This file implements some general event related interfaces including *	background errors, exit handlers, and the "vwait" and "update" *	command procedures.  * * Copyright (c) 1990-1994 The Regents of the University of California. * Copyright (c) 1994-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. * * SCCS: @(#) tclEvent.c 1.153 97/08/11 20:22:31 */#include "tclInt.h"#include "tclPort.h"/* * 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 {    Tcl_Interp *interp;		/* Interpreter in which error occurred.  NULL				 * means this error report has been cancelled				 * (a previous report generated a break). */    char *errorMsg;		/* The error message (interp->result when				 * the error occurred).  Malloc-ed. */    char *errorInfo;		/* Value of the errorInfo variable				 * (malloc-ed). */    char *errorCode;		/* Value of the errorCode variable				 * (malloc-ed). */    struct BgError *nextPtr;	/* Next in list of all pending error				 * 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 {    BgError *firstBgPtr;	/* First in list of all background errors				 * waiting to be processed for this				 * interpreter (NULL if none). */    BgError *lastBgPtr;		/* Last in list of all background errors				 * 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 {    Tcl_ExitProc *proc;		/* Procedure to call when process exits. */    ClientData clientData;	/* One word of information to pass to proc. */    struct ExitHandler *nextPtr;/* Next in list of all exit handlers for				 * this application, or NULL for end of list. */} ExitHandler;static ExitHandler *firstExitPtr = NULL;				/* First in list of all exit handlers for				 * application. *//* * 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. */char *tclMemDumpFileName = NULL;/* * 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: */static void		BgErrorDeleteProc _ANSI_ARGS_((ClientData clientData,			    Tcl_Interp *interp));static void		HandleBgErrors _ANSI_ARGS_((ClientData clientData));static char *		VwaitVarProc _ANSI_ARGS_((ClientData clientData,			    Tcl_Interp *interp, char *name1, char *name2,			    int flags));/* *---------------------------------------------------------------------- * * 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. * *---------------------------------------------------------------------- */voidTcl_BackgroundError(interp)    Tcl_Interp *interp;		/* Interpreter in which an error has				 * occurred. */{    BgError *errPtr;    char *errResult, *varValue;    ErrAssocData *assocPtr;    /*     * 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.     */    Tcl_AddErrorInfo(interp, "");    errResult = TclGetStringFromObj(Tcl_GetObjResult(interp), (int *) NULL);	    errPtr = (BgError *) ckalloc(sizeof(BgError));    errPtr->interp = interp;    errPtr->errorMsg = (char *) ckalloc((unsigned) (strlen(errResult) + 1));    strcpy(errPtr->errorMsg, errResult);    varValue = Tcl_GetVar(interp, "errorInfo", TCL_GLOBAL_ONLY);    if (varValue == NULL) {	varValue = errPtr->errorMsg;    }    errPtr->errorInfo = (char *) ckalloc((unsigned) (strlen(varValue) + 1));    strcpy(errPtr->errorInfo, varValue);    varValue = Tcl_GetVar(interp, "errorCode", TCL_GLOBAL_ONLY);    if (varValue == NULL) {	varValue = "";    }    errPtr->errorCode = (char *) ckalloc((unsigned) (strlen(varValue) + 1));    strcpy(errPtr->errorCode, varValue);    errPtr->nextPtr = NULL;    assocPtr = (ErrAssocData *) Tcl_GetAssocData(interp, "tclBgError",	    (Tcl_InterpDeleteProc **) NULL);    if (assocPtr == NULL) {	/*	 * This is the first time a background error has occurred in	 * this interpreter.  Create associated data to keep track of	 * pending error reports.	 */	assocPtr = (ErrAssocData *) ckalloc(sizeof(ErrAssocData));	assocPtr->firstBgPtr = NULL;	assocPtr->lastBgPtr = NULL;	Tcl_SetAssocData(interp, "tclBgError", BgErrorDeleteProc,		(ClientData) assocPtr);    }    if (assocPtr->firstBgPtr == NULL) {	assocPtr->firstBgPtr = errPtr;	Tcl_DoWhenIdle(HandleBgErrors, (ClientData) assocPtr);    } else {	assocPtr->lastBgPtr->nextPtr = errPtr;    }    assocPtr->lastBgPtr = errPtr;    Tcl_ResetResult(interp);}/* *---------------------------------------------------------------------- * * 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 voidHandleBgErrors(clientData)    ClientData clientData;	/* Pointer to ErrAssocData structure. */{    Tcl_Interp *interp;    char *command;    char *argv[2];    int code;    BgError *errPtr;    ErrAssocData *assocPtr = (ErrAssocData *) clientData;    Tcl_Channel errChannel;    Tcl_Preserve((ClientData) assocPtr);        while (assocPtr->firstBgPtr != NULL) {	interp = assocPtr->firstBgPtr->interp;	if (interp == NULL) {	    goto doneWithInterp;	}	/*	 * Restore important state variables to what they were at	 * the time the error occurred.	 */	Tcl_SetVar(interp, "errorInfo", assocPtr->firstBgPtr->errorInfo,		TCL_GLOBAL_ONLY);	Tcl_SetVar(interp, "errorCode", assocPtr->firstBgPtr->errorCode,		TCL_GLOBAL_ONLY);	/*	 * Create and invoke the bgerror command.	 */	argv[0] = "bgerror";	argv[1] = assocPtr->firstBgPtr->errorMsg;	command = Tcl_Merge(2, argv);	Tcl_AllowExceptions(interp);        Tcl_Preserve((ClientData) interp);	code = Tcl_GlobalEval(interp, command);	ckfree(command);	if (code == TCL_ERROR) {            /*             * If the interpreter is safe, we look for a hidden command             * named "bgerror" and call that with the error information.             * Otherwise, simply ignore the error. The rationale is that             * this could be an error caused by a malicious applet trying             * to cause an infinite barrage of error messages. The hidden             * "bgerror" command can be used by a security policy to             * interpose on such attacks and e.g. kill the applet after a             * few attempts.             */            if (Tcl_IsSafe(interp)) {                Tcl_HashTable *hTblPtr;                Tcl_HashEntry *hPtr;                hTblPtr = (Tcl_HashTable *) Tcl_GetAssocData(interp,                        "tclHiddenCmds", NULL);                if (hTblPtr == (Tcl_HashTable *) NULL) {                    goto doneWithInterp;                }                hPtr = Tcl_FindHashEntry(hTblPtr, "bgerror");                if (hPtr == (Tcl_HashEntry *) NULL) {                    goto doneWithInterp;                }                /*                 * OK, the hidden command "bgerror" exists, invoke it.                 */                argv[0] = "bgerror";                argv[1] = ckalloc((unsigned)                        strlen(assocPtr->firstBgPtr->errorMsg));                strcpy(argv[1], assocPtr->firstBgPtr->errorMsg);                (void) TclInvoke(interp, 2, argv, TCL_INVOKE_HIDDEN);                ckfree(argv[1]);                goto doneWithInterp;            }             /*             * We have to get the error output channel at the latest possible             * time, because the eval (above) might have changed the channel.             */                        errChannel = Tcl_GetStdChannel(TCL_STDERR);            if (errChannel != (Tcl_Channel) NULL) {                if (strcmp(interp->result,           "\"bgerror\" is an invalid command name or ambiguous abbreviation")                        == 0) {                    Tcl_Write(errChannel, assocPtr->firstBgPtr->errorInfo, -1);                    Tcl_Write(errChannel, "\n", -1);                } else {                    Tcl_Write(errChannel,                            "bgerror failed to handle background error.\n",                            -1);                    Tcl_Write(errChannel, "    Original error: ", -1);                    Tcl_Write(errChannel, assocPtr->firstBgPtr->errorMsg,                            -1);                    Tcl_Write(errChannel, "\n", -1);                    Tcl_Write(errChannel, "    Error in bgerror: ", -1);                    Tcl_Write(errChannel, interp->result, -1);                    Tcl_Write(errChannel, "\n", -1);                }                Tcl_Flush(errChannel);            }	} else if (code == TCL_BREAK) {	    /*	     * Break means cancel any remaining error reports for this	     * interpreter.	     */	    for (errPtr = assocPtr->firstBgPtr; errPtr != NULL;		    errPtr = errPtr->nextPtr) {		if (errPtr->interp == interp) {		    errPtr->interp = NULL;		}	    }	}	/*	 * Discard the command and the information about the error report.	 */doneWithInterp:	if (assocPtr->firstBgPtr) {	    ckfree(assocPtr->firstBgPtr->errorMsg);	    ckfree(assocPtr->firstBgPtr->errorInfo);	    ckfree(assocPtr->firstBgPtr->errorCode);	    errPtr = assocPtr->firstBgPtr->nextPtr;	    ckfree((char *) assocPtr->firstBgPtr);	    assocPtr->firstBgPtr = errPtr;	}                if (interp != NULL) {            Tcl_Release((ClientData) interp);        }    }    assocPtr->lastBgPtr = NULL;    Tcl_Release((ClientData) assocPtr);}

⌨️ 快捷键说明

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