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

📄 tcltimer.c

📁 linux系统下的音频通信
💻 C
📖 第 1 页 / 共 3 页
字号:
    if (objc < 2) {	Tcl_WrongNumArgs(interp, 1, objv, "option ?arg arg ...?");	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.     */    if (assocPtr == NULL) {	assocPtr = (AfterAssocData *) ckalloc(sizeof(AfterAssocData));	assocPtr->interp = interp;	assocPtr->firstAfterPtr = NULL;	Tcl_SetAssocData(interp, "tclAfter", AfterCleanupProc,		(ClientData) assocPtr);	cmdInfo.proc = NULL;	cmdInfo.clientData = (ClientData) NULL;	cmdInfo.objProc = Tcl_AfterObjCmd;	cmdInfo.objClientData = (ClientData) assocPtr;	cmdInfo.deleteProc = NULL;	cmdInfo.deleteData = (ClientData) assocPtr;	Tcl_SetCommandInfo(interp, Tcl_GetStringFromObj(objv[0], &length),		&cmdInfo);    }    /*     * First lets see if the command was passed a number as the first argument.     */        arg = Tcl_GetStringFromObj(objv[1], &length);    if (isdigit(UCHAR(arg[0]))) {	if (Tcl_GetIntFromObj(interp, objv[1], &ms) != TCL_OK) {	    return TCL_ERROR;	}	if (ms < 0) {	    ms = 0;	}	if (objc == 2) {	    Tcl_Sleep(ms);	    return TCL_OK;	}	afterPtr = (AfterInfo *) ckalloc((unsigned) (sizeof(AfterInfo)));	afterPtr->assocPtr = assocPtr;	if (objc == 3) {	    arg = Tcl_GetStringFromObj(objv[2], &length);	    afterPtr->command = (char *) ckalloc((unsigned) (length + 1));	    strcpy(afterPtr->command, arg);	} else {	    Tcl_Obj *objPtr = Tcl_ConcatObj(objc-2, objv+2);	    arg = Tcl_GetStringFromObj(objPtr, &length);	    afterPtr->command = (char *) ckalloc((unsigned) (length + 1));	    strcpy(afterPtr->command, arg);	    Tcl_DecrRefCount(objPtr);	}	afterPtr->id = nextId;	nextId += 1;	afterPtr->token = Tcl_CreateTimerHandler(ms, AfterProc,		(ClientData) afterPtr);	afterPtr->nextPtr = assocPtr->firstAfterPtr;	assocPtr->firstAfterPtr = afterPtr;	sprintf(interp->result, "after#%d", afterPtr->id);	return TCL_OK;    }    /*     * If it's not a number it must be a subcommand.     */    result = Tcl_GetIndexFromObj(NULL, objv[1], subCmds, "option",            0, (int *) &index);    if (result != TCL_OK) {	Tcl_AppendResult(interp, "bad argument \"", arg,		"\": must be cancel, idle, info, or a number",		(char *) NULL);	return TCL_ERROR;    }    switch (index) {        case 0:		/* cancel */	    {		char *arg;		Tcl_Obj *objPtr = NULL;		if (objc < 3) {		    Tcl_WrongNumArgs(interp, 2, objv, "id|command");		    return TCL_ERROR;		}		if (objc == 3) {		    arg = Tcl_GetStringFromObj(objv[2], &length);		} else {		    objPtr = Tcl_ConcatObj(objc-2, objv+2);;		    arg = Tcl_GetStringFromObj(objPtr, &length);		}		for (afterPtr = assocPtr->firstAfterPtr; afterPtr != NULL;		     afterPtr = afterPtr->nextPtr) {		    if (strcmp(afterPtr->command, arg) == 0) {			break;		    }		}		if (afterPtr == NULL) {		    afterPtr = GetAfterEvent(assocPtr, arg);		}		if (objPtr != NULL) {		    Tcl_DecrRefCount(objPtr);		}		if (afterPtr != NULL) {		    if (afterPtr->token != NULL) {			Tcl_DeleteTimerHandler(afterPtr->token);		    } else {			Tcl_CancelIdleCall(AfterProc, (ClientData) afterPtr);		    }		    FreeAfterPtr(afterPtr);		}		break;	    }	case 1:		/* idle */	    if (objc < 3) {		Tcl_WrongNumArgs(interp, 2, objv, "script script ...");		return TCL_ERROR;	    }	    afterPtr = (AfterInfo *) ckalloc((unsigned) (sizeof(AfterInfo)));	    afterPtr->assocPtr = assocPtr;	    if (objc == 3) {		arg = Tcl_GetStringFromObj(objv[2], &length);		afterPtr->command = (char *) ckalloc((unsigned) length + 1);		strcpy(afterPtr->command, arg);	    } else {		Tcl_Obj *objPtr = Tcl_ConcatObj(objc-2, objv+2);;		arg = Tcl_GetStringFromObj(objPtr, &length);		afterPtr->command = (char *) ckalloc((unsigned) (length + 1));		strcpy(afterPtr->command, arg);		Tcl_DecrRefCount(objPtr);	    }	    afterPtr->id = nextId;	    nextId += 1;	    afterPtr->token = NULL;	    afterPtr->nextPtr = assocPtr->firstAfterPtr;	    assocPtr->firstAfterPtr = afterPtr;	    Tcl_DoWhenIdle(AfterProc, (ClientData) afterPtr);	    sprintf(interp->result, "after#%d", afterPtr->id);	    break;	case 2:		/* info */	    if (objc == 2) {		char buffer[30];	    		for (afterPtr = assocPtr->firstAfterPtr; afterPtr != NULL;		     afterPtr = afterPtr->nextPtr) {		    if (assocPtr->interp == interp) {			sprintf(buffer, "after#%d", afterPtr->id);			Tcl_AppendElement(interp, buffer);		    }		}		return TCL_OK;	    }	    if (objc != 3) {		Tcl_WrongNumArgs(interp, 2, objv, "?id?");		return TCL_ERROR;	    }	    arg = Tcl_GetStringFromObj(objv[2], &length);	    afterPtr = GetAfterEvent(assocPtr, arg);	    if (afterPtr == NULL) {		Tcl_AppendResult(interp, "event \"", arg,			"\" doesn't exist", (char *) NULL);		return TCL_ERROR;	    }	    Tcl_AppendElement(interp, afterPtr->command);	    Tcl_AppendElement(interp,		    (afterPtr->token == NULL) ? "idle" : "timer");	    break;    }    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 *GetAfterEvent(assocPtr, string)    AfterAssocData *assocPtr;	/* Points to "after"-related information for				 * this interpreter. */    char *string;		/* Textual identifier for after event, such				 * as "after#6". */{    AfterInfo *afterPtr;    int id;    char *end;    if (strncmp(string, "after#", 6) != 0) {	return NULL;    }    string += 6;    id = strtoul(string, &end, 10);    if ((end == string) || (*end != 0)) {	return NULL;    }    for (afterPtr = assocPtr->firstAfterPtr; afterPtr != NULL;	    afterPtr = afterPtr->nextPtr) {	if (afterPtr->id == id) {	    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 voidAfterProc(clientData)    ClientData clientData;	/* Describes command to execute. */{    AfterInfo *afterPtr = (AfterInfo *) clientData;    AfterAssocData *assocPtr = afterPtr->assocPtr;    AfterInfo *prevPtr;    int result;    Tcl_Interp *interp;    /*     * 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.     */    if (assocPtr->firstAfterPtr == afterPtr) {	assocPtr->firstAfterPtr = afterPtr->nextPtr;    } else {	for (prevPtr = assocPtr->firstAfterPtr; prevPtr->nextPtr != afterPtr;		prevPtr = prevPtr->nextPtr) {	    /* Empty loop body. */	}	prevPtr->nextPtr = afterPtr->nextPtr;    }    /*     * Execute the callback.     */    interp = assocPtr->interp;    Tcl_Preserve((ClientData) interp);    result = Tcl_GlobalEval(interp, afterPtr->command);    if (result != TCL_OK) {	Tcl_AddErrorInfo(interp, "\n    (\"after\" script)");	Tcl_BackgroundError(interp);    }    Tcl_Release((ClientData) interp);        /*     * Free the memory for the callback.     */    ckfree(afterPtr->command);    ckfree((char *) afterPtr);}/* *---------------------------------------------------------------------- * * 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 voidFreeAfterPtr(afterPtr)    AfterInfo *afterPtr;		/* Command to be deleted. */{    AfterInfo *prevPtr;    AfterAssocData *assocPtr = afterPtr->assocPtr;    if (assocPtr->firstAfterPtr == afterPtr) {	assocPtr->firstAfterPtr = afterPtr->nextPtr;    } else {	for (prevPtr = assocPtr->firstAfterPtr; prevPtr->nextPtr != afterPtr;		prevPtr = prevPtr->nextPtr) {	    /* Empty loop body. */	}	prevPtr->nextPtr = afterPtr->nextPtr;    }    ckfree(afterPtr->command);    ckfree((char *) afterPtr);}/* *---------------------------------------------------------------------- * * 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 voidAfterCleanupProc(clientData, interp)    ClientData clientData;	/* Points to AfterAssocData for the				 * interpreter. */    Tcl_Interp *interp;		/* Interpreter that is being deleted. */{    AfterAssocData *assocPtr = (AfterAssocData *) clientData;    AfterInfo *afterPtr;    while (assocPtr->firstAfterPtr != NULL) {	afterPtr = assocPtr->firstAfterPtr;	assocPtr->firstAfterPtr = afterPtr->nextPtr;	if (afterPtr->token != NULL) {	    Tcl_DeleteTimerHandler(afterPtr->token);	} else {	    Tcl_CancelIdleCall(AfterProc, (ClientData) afterPtr);	}	ckfree(afterPtr->command);	ckfree((char *) afterPtr);    }    ckfree((char *) assocPtr);}

⌨️ 快捷键说明

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