tclinterp.c

来自「tcl是工具命令语言」· C语言 代码 · 共 2,256 行 · 第 1/5 页

C
2,256
字号
	    targetObjPtr, objc, objv);    Tcl_DecrRefCount(slaveObjPtr);    Tcl_DecrRefCount(targetObjPtr);    return result;}/* *---------------------------------------------------------------------- * * Tcl_GetAlias -- * *	Gets information about an alias. * * Results: *	A standard Tcl result.  * * Side effects: *	None. * *---------------------------------------------------------------------- */intTcl_GetAlias(interp, aliasName, targetInterpPtr, targetNamePtr, argcPtr,        argvPtr)    Tcl_Interp *interp;			/* Interp to start search from. */    CONST char *aliasName;			/* Name of alias to find. */    Tcl_Interp **targetInterpPtr;	/* (Return) target interpreter. */    CONST char **targetNamePtr;		/* (Return) name of target command. */    int *argcPtr;			/* (Return) count of addnl args. */    CONST char ***argvPtr;		/* (Return) additional arguments. */{    InterpInfo *iiPtr;    Tcl_HashEntry *hPtr;    Alias *aliasPtr;    int i, objc;    Tcl_Obj **objv;        iiPtr = (InterpInfo *) ((Interp *) interp)->interpInfo;    hPtr = Tcl_FindHashEntry(&iiPtr->slave.aliasTable, aliasName);    if (hPtr == NULL) {        Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),                "alias \"", aliasName, "\" not found", (char *) NULL);	return TCL_ERROR;    }    aliasPtr = (Alias *) Tcl_GetHashValue(hPtr);    objc = aliasPtr->objc;    objv = &aliasPtr->objPtr;    if (targetInterpPtr != NULL) {	*targetInterpPtr = aliasPtr->targetInterp;    }    if (targetNamePtr != NULL) {	*targetNamePtr = Tcl_GetString(objv[0]);    }    if (argcPtr != NULL) {	*argcPtr = objc - 1;    }    if (argvPtr != NULL) {        *argvPtr = (CONST char **) 		ckalloc((unsigned) sizeof(CONST char *) * (objc - 1));        for (i = 1; i < objc; i++) {            *argvPtr[i - 1] = Tcl_GetString(objv[i]);        }    }    return TCL_OK;}/* *---------------------------------------------------------------------- * * Tcl_GetAliasObj -- * *	Object version: Gets information about an alias. * * Results: *	A standard Tcl result. * * Side effects: *	None. * *---------------------------------------------------------------------- */intTcl_GetAliasObj(interp, aliasName, targetInterpPtr, targetNamePtr, objcPtr,        objvPtr)    Tcl_Interp *interp;			/* Interp to start search from. */    CONST char *aliasName;		/* Name of alias to find. */    Tcl_Interp **targetInterpPtr;	/* (Return) target interpreter. */    CONST char **targetNamePtr;		/* (Return) name of target command. */    int *objcPtr;			/* (Return) count of addnl args. */    Tcl_Obj ***objvPtr;			/* (Return) additional args. */{    InterpInfo *iiPtr;    Tcl_HashEntry *hPtr;    Alias *aliasPtr;	    int objc;    Tcl_Obj **objv;    iiPtr = (InterpInfo *) ((Interp *) interp)->interpInfo;    hPtr = Tcl_FindHashEntry(&iiPtr->slave.aliasTable, aliasName);    if (hPtr == (Tcl_HashEntry *) NULL) {        Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),                "alias \"", aliasName, "\" not found", (char *) NULL);        return TCL_ERROR;    }    aliasPtr = (Alias *) Tcl_GetHashValue(hPtr);    objc = aliasPtr->objc;    objv = &aliasPtr->objPtr;    if (targetInterpPtr != (Tcl_Interp **) NULL) {        *targetInterpPtr = aliasPtr->targetInterp;    }    if (targetNamePtr != (CONST char **) NULL) {        *targetNamePtr = Tcl_GetString(objv[0]);    }    if (objcPtr != (int *) NULL) {        *objcPtr = objc - 1;    }    if (objvPtr != (Tcl_Obj ***) NULL) {        *objvPtr = objv + 1;    }    return TCL_OK;}/* *---------------------------------------------------------------------- * * TclPreventAliasLoop -- * *	When defining an alias or renaming a command, prevent an alias *	loop from being formed. * * Results: *	A standard Tcl object result. * * Side effects: *	If TCL_ERROR is returned, the function also stores an error message *	in the interpreter's result object. * * NOTE: *	This function is public internal (instead of being static to *	this file) because it is also used from TclRenameCommand. * *---------------------------------------------------------------------- */intTclPreventAliasLoop(interp, cmdInterp, cmd)    Tcl_Interp *interp;			/* Interp in which to report errors. */    Tcl_Interp *cmdInterp;		/* Interp in which the command is                                         * being defined. */    Tcl_Command cmd;                    /* Tcl command we are attempting                                         * to define. */{    Command *cmdPtr = (Command *) cmd;    Alias *aliasPtr, *nextAliasPtr;    Tcl_Command aliasCmd;    Command *aliasCmdPtr;    /*     * If we are not creating or renaming an alias, then it is     * always OK to create or rename the command.     */        if (cmdPtr->objProc != AliasObjCmd) {        return TCL_OK;    }    /*     * OK, we are dealing with an alias, so traverse the chain of aliases.     * If we encounter the alias we are defining (or renaming to) any in     * the chain then we have a loop.     */    aliasPtr = (Alias *) cmdPtr->objClientData;    nextAliasPtr = aliasPtr;    while (1) {	Tcl_Obj *cmdNamePtr;        /*         * If the target of the next alias in the chain is the same as         * the source alias, we have a loop.	 */	if (Tcl_InterpDeleted(nextAliasPtr->targetInterp)) {	    /*	     * The slave interpreter can be deleted while creating the alias.	     * [Bug #641195]	     */	    Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),		    "cannot define or rename alias \"",		    Tcl_GetString(aliasPtr->namePtr),		    "\": interpreter deleted", (char *) NULL);	    return TCL_ERROR;	}	cmdNamePtr = nextAliasPtr->objPtr;	aliasCmd = Tcl_FindCommand(nextAliasPtr->targetInterp,                Tcl_GetString(cmdNamePtr),		Tcl_GetGlobalNamespace(nextAliasPtr->targetInterp),		/*flags*/ 0);        if (aliasCmd == (Tcl_Command) NULL) {            return TCL_OK;        }	aliasCmdPtr = (Command *) aliasCmd;        if (aliasCmdPtr == cmdPtr) {            Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),		    "cannot define or rename alias \"",		    Tcl_GetString(aliasPtr->namePtr),		    "\": would create a loop", (char *) NULL);            return TCL_ERROR;        }        /*	 * Otherwise, follow the chain one step further. See if the target         * command is an alias - if so, follow the loop to its target         * command. Otherwise we do not have a loop.	 */        if (aliasCmdPtr->objProc != AliasObjCmd) {            return TCL_OK;        }        nextAliasPtr = (Alias *) aliasCmdPtr->objClientData;    }    /* NOTREACHED */}/* *---------------------------------------------------------------------- * * AliasCreate -- * *	Helper function to do the work to actually create an alias. * * Results: *	A standard Tcl result. * * Side effects: *	An alias command is created and entered into the alias table *	for the slave interpreter. * *---------------------------------------------------------------------- */static intAliasCreate(interp, slaveInterp, masterInterp, namePtr, targetNamePtr,	objc, objv)    Tcl_Interp *interp;		/* Interp for error reporting. */    Tcl_Interp *slaveInterp;	/* Interp where alias cmd will live or from				 * which alias will be deleted. */    Tcl_Interp *masterInterp;	/* Interp in which target command will be				 * invoked. */    Tcl_Obj *namePtr;		/* Name of alias cmd. */    Tcl_Obj *targetNamePtr;	/* Name of target cmd. */    int objc;			/* Additional arguments to store */    Tcl_Obj *CONST objv[];	/* with alias. */{    Alias *aliasPtr;    Tcl_HashEntry *hPtr;    Target *targetPtr;    Slave *slavePtr;    Master *masterPtr;    Tcl_Obj **prefv;    int new, i;    aliasPtr = (Alias *) ckalloc((unsigned) (sizeof(Alias)             + objc * sizeof(Tcl_Obj *)));    aliasPtr->namePtr		= namePtr;    Tcl_IncrRefCount(aliasPtr->namePtr);    aliasPtr->targetInterp	= masterInterp;    aliasPtr->objc = objc + 1;    prefv = &aliasPtr->objPtr;    *prefv = targetNamePtr;    Tcl_IncrRefCount(targetNamePtr);    for (i = 0; i < objc; i++) {	*(++prefv) = objv[i];	Tcl_IncrRefCount(objv[i]);    }    Tcl_Preserve(slaveInterp);    Tcl_Preserve(masterInterp);    aliasPtr->slaveCmd = Tcl_CreateObjCommand(slaveInterp,	    Tcl_GetString(namePtr), AliasObjCmd, (ClientData) aliasPtr,	    AliasObjCmdDeleteProc);    if (TclPreventAliasLoop(interp, slaveInterp,	    aliasPtr->slaveCmd) != TCL_OK) {	/*	 * Found an alias loop!	 The last call to Tcl_CreateObjCommand made	 * the alias point to itself.  Delete the command and its alias	 * record.  Be careful to wipe out its client data first, so the	 * command doesn't try to delete itself.	 */	Command *cmdPtr;		Tcl_DecrRefCount(aliasPtr->namePtr);	Tcl_DecrRefCount(targetNamePtr);	for (i = 0; i < objc; i++) {	    Tcl_DecrRefCount(objv[i]);	}		cmdPtr = (Command *) aliasPtr->slaveCmd;	cmdPtr->clientData = NULL;	cmdPtr->deleteProc = NULL;	cmdPtr->deleteData = NULL;	Tcl_DeleteCommandFromToken(slaveInterp, aliasPtr->slaveCmd);	ckfree((char *) aliasPtr);	/*	 * The result was already set by TclPreventAliasLoop.	 */	Tcl_Release(slaveInterp);	Tcl_Release(masterInterp);	return TCL_ERROR;    }    /*     * Make an entry in the alias table. If it already exists delete     * the alias command. Then retry.     */    slavePtr = &((InterpInfo *) ((Interp *) slaveInterp)->interpInfo)->slave;    while (1) {	Alias *oldAliasPtr;	char *string;		string = Tcl_GetString(namePtr);	hPtr = Tcl_CreateHashEntry(&slavePtr->aliasTable, string, &new);	if (new != 0) {	    break;	}	oldAliasPtr = (Alias *) Tcl_GetHashValue(hPtr);	Tcl_DeleteCommandFromToken(slaveInterp, oldAliasPtr->slaveCmd);    }    aliasPtr->aliasEntryPtr = hPtr;    Tcl_SetHashValue(hPtr, (ClientData) aliasPtr);        /*     * Create the new command. We must do it after deleting any old command,     * because the alias may be pointing at a renamed alias, as in:     *     * interp alias {} foo {} bar		# Create an alias "foo"     * rename foo zop				# Now rename the alias     * interp alias {} foo {} zop		# Now recreate "foo"...     */    targetPtr = (Target *) ckalloc((unsigned) sizeof(Target));    targetPtr->slaveCmd = aliasPtr->slaveCmd;    targetPtr->slaveInterp = slaveInterp;    Tcl_MutexLock(&cntMutex);    masterPtr = &((InterpInfo *) ((Interp *) masterInterp)->interpInfo)->master;    do {        hPtr = Tcl_CreateHashEntry(&masterPtr->targetTable,                (char *) aliasCounter, &new);	aliasCounter++;    } while (new == 0);    Tcl_MutexUnlock(&cntMutex);    Tcl_SetHashValue(hPtr, (ClientData) targetPtr);    aliasPtr->targetEntryPtr = hPtr;    Tcl_SetObjResult(interp, namePtr);    Tcl_Release(slaveInterp);    Tcl_Release(masterInterp);    return TCL_OK;}/* *---------------------------------------------------------------------- * * AliasDelete -- * *	Deletes the given alias from the slave interpreter given. * * Results: *	A standard Tcl result. * * Side effects: *	Deletes the alias from the slave interpreter. * *---------------------------------------------------------------------- */static intAliasDelete(interp, slaveInterp, namePtr)    Tcl_Interp *interp;		/* Interpreter for result & errors. */    Tcl_Interp *slaveInterp;	/* Interpreter containing alias. */    Tcl_Obj *namePtr;		/* Name of alias to delete. */{    Slave *slavePtr;    Alias *aliasPtr;    Tcl_HashEntry *hPtr;    /*     * If the alias has been renamed in the slave, the master can still use     * the original name (with which it was created) to find the alias to     * delete it.     */    slavePtr = &((InterpInfo *) ((Interp *) slaveInterp)->interpInfo)->slave;    hPtr = Tcl_FindHashEntry(&slavePtr->aliasTable, Tcl_GetString(namePtr));    if (hPtr == NULL) {	Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "alias \"",		Tcl_GetString(namePtr), "\" not found", NULL);        return TCL_ERROR;    }    aliasPtr = (Alias *) Tcl_GetHashValue(hPtr);    Tcl_DeleteCommandFromToken(slaveInterp, aliasPtr->slaveCmd);    return TCL_OK;}/* *---------------------------------------------------------------------- * * AliasDescribe -- * *	Sets the interpreter's result object to a Tcl list describing *	the given alias in the given interpreter: its target command *	and the additional arguments to prepend to any invocation *	of the alias. * * Results: *	A standard Tcl result. * * Side effects: *	None. * *---------------------------------------------------------------------- */static intAliasDescribe(interp, slaveInterp, namePtr)    Tcl_Interp *interp;		/* Interpreter for result & errors. */    Tcl_Interp *slaveInterp;	/* Interpreter containing alias. */    Tcl_Obj *namePtr;		/* Name of alias to describe. */{    Slave *slavePtr;    Tcl_HashEntry *hPtr;

⌨️ 快捷键说明

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