tclinterp.c

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

C
2,256
字号
            SlaveObjCmd, (ClientData) slaveInterp, SlaveObjCmdDeleteProc);    Tcl_InitHashTable(&slavePtr->aliasTable, TCL_STRING_KEYS);    Tcl_SetHashValue(hPtr, (ClientData) slavePtr);    Tcl_SetVar(slaveInterp, "tcl_interactive", "0", TCL_GLOBAL_ONLY);        /*     * Inherit the recursion limit.     */    ((Interp *) slaveInterp)->maxNestingDepth =	((Interp *) masterInterp)->maxNestingDepth ;    if (safe) {        if (Tcl_MakeSafe(slaveInterp) == TCL_ERROR) {            goto error;        }    } else {        if (Tcl_Init(slaveInterp) == TCL_ERROR) {            goto error;        }	/*	 * This will create the "memory" command in slave interpreters	 * if we compiled with TCL_MEM_DEBUG, otherwise it does nothing.	 */	Tcl_InitMemory(slaveInterp);    }    return slaveInterp;    error:    TclTransferResult(slaveInterp, TCL_ERROR, interp);    Tcl_DeleteInterp(slaveInterp);    return NULL;}/* *---------------------------------------------------------------------- * * SlaveObjCmd -- * *	Command to manipulate an interpreter, e.g. to send commands to it *	to be evaluated. One such command exists for each slave interpreter. * * Results: *	A standard Tcl result. * * Side effects: *	See user documentation for details. * *---------------------------------------------------------------------- */static intSlaveObjCmd(clientData, interp, objc, objv)    ClientData clientData;	/* Slave interpreter. */    Tcl_Interp *interp;		/* Current interpreter. */    int objc;			/* Number of arguments. */    Tcl_Obj *CONST objv[];	/* Argument objects. */{    Tcl_Interp *slaveInterp;    int index;    static CONST char *options[] = {        "alias",	"aliases",	"eval",		"expose",        "hide",		"hidden",	"issafe",	"invokehidden",        "marktrusted",	"recursionlimit", NULL    };    enum options {	OPT_ALIAS,	OPT_ALIASES,	OPT_EVAL,	OPT_EXPOSE,	OPT_HIDE,	OPT_HIDDEN,	OPT_ISSAFE,	OPT_INVOKEHIDDEN,	OPT_MARKTRUSTED, OPT_RECLIMIT    };        slaveInterp = (Tcl_Interp *) clientData;    if (slaveInterp == NULL) {	panic("SlaveObjCmd: interpreter has been deleted");    }    if (objc < 2) {        Tcl_WrongNumArgs(interp, 1, objv, "cmd ?arg ...?");        return TCL_ERROR;    }    if (Tcl_GetIndexFromObj(interp, objv[1], options, "option", 0,	    &index) != TCL_OK) {	return TCL_ERROR;    }    switch ((enum options) index) {	case OPT_ALIAS: {	    if (objc > 2) {		if (objc == 3) {		    return AliasDescribe(interp, slaveInterp, objv[2]);		}		if (Tcl_GetString(objv[3])[0] == '\0') {		    if (objc == 4) {			return AliasDelete(interp, slaveInterp, objv[2]);		    }		} else {		    return AliasCreate(interp, slaveInterp, interp, objv[2],			    objv[3], objc - 4, objv + 4);		}	    }	    Tcl_WrongNumArgs(interp, 2, objv,		    "aliasName ?targetName? ?args..?");            return TCL_ERROR;	}	case OPT_ALIASES: {	    if (objc != 2) {		Tcl_WrongNumArgs(interp, 2, objv, (char *) NULL);		return TCL_ERROR;	    }	    return AliasList(interp, slaveInterp);	}	case OPT_EVAL: {	    if (objc < 3) {		Tcl_WrongNumArgs(interp, 2, objv, "arg ?arg ...?");		return TCL_ERROR;	    }	    return SlaveEval(interp, slaveInterp, objc - 2, objv + 2);	}        case OPT_EXPOSE: {	    if ((objc < 3) || (objc > 4)) {		Tcl_WrongNumArgs(interp, 2, objv, "hiddenCmdName ?cmdName?");		return TCL_ERROR;	    }            return SlaveExpose(interp, slaveInterp, objc - 2, objv + 2);	}	case OPT_HIDE: {	    if ((objc < 3) || (objc > 4)) {		Tcl_WrongNumArgs(interp, 2, objv, "cmdName ?hiddenCmdName?");		return TCL_ERROR;	    }            return SlaveHide(interp, slaveInterp, objc - 2, objv + 2);	}        case OPT_HIDDEN: {	    if (objc != 2) {		Tcl_WrongNumArgs(interp, 2, objv, NULL);		return TCL_ERROR;	    }            return SlaveHidden(interp, slaveInterp);	}        case OPT_ISSAFE: {	    if (objc != 2) {		Tcl_WrongNumArgs(interp, 2, objv, (char *) NULL);		return TCL_ERROR;	    }	    Tcl_SetIntObj(Tcl_GetObjResult(interp), Tcl_IsSafe(slaveInterp));	    return TCL_OK;	}        case OPT_INVOKEHIDDEN: {	    int global, i, index;	    static CONST char *hiddenOptions[] = {		"-global",	"--",		NULL	    };	    enum hiddenOption {		OPT_GLOBAL,	OPT_LAST	    };	    global = 0;	    for (i = 2; i < objc; i++) {		if (Tcl_GetString(objv[i])[0] != '-') {		    break;		}		if (Tcl_GetIndexFromObj(interp, objv[i], hiddenOptions,			"option", 0, &index) != TCL_OK) {		    return TCL_ERROR;		}		if (index == OPT_GLOBAL) {		    global = 1;		} else {		    i++;		    break;		}	    }	    if (objc - i < 1) {		Tcl_WrongNumArgs(interp, 2, objv,			"?-global? ?--? cmd ?arg ..?");		return TCL_ERROR;	    }	    return SlaveInvokeHidden(interp, slaveInterp, global, objc - i,		    objv + i);	}	case OPT_MARKTRUSTED: {	    if (objc != 2) {		Tcl_WrongNumArgs(interp, 2, objv, NULL);		return TCL_ERROR;	    }            return SlaveMarkTrusted(interp, slaveInterp);	}	case OPT_RECLIMIT: {	    if (objc != 2 && objc != 3) {		Tcl_WrongNumArgs(interp, 2, objv, "?newlimit?");		return TCL_ERROR;	    }	    return SlaveRecursionLimit(interp, slaveInterp, objc - 2, objv + 2);	}    }    return TCL_ERROR;}/* *---------------------------------------------------------------------- * * SlaveObjCmdDeleteProc -- * *	Invoked when an object command for a slave interpreter is deleted; *	cleans up all state associated with the slave interpreter and destroys *	the slave interpreter. * * Results: *	None. * * Side effects: *	Cleans up all state associated with the slave interpreter and *	destroys the slave interpreter. * *---------------------------------------------------------------------- */static voidSlaveObjCmdDeleteProc(clientData)    ClientData clientData;		/* The SlaveRecord for the command. */{    Slave *slavePtr;			/* Interim storage for Slave record. */    Tcl_Interp *slaveInterp;		/* And for a slave interp. */    slaveInterp = (Tcl_Interp *) clientData;    slavePtr = &((InterpInfo *) ((Interp *) slaveInterp)->interpInfo)->slave;    /*     * Unlink the slave from its master interpreter.     */    Tcl_DeleteHashEntry(slavePtr->slaveEntryPtr);    /*     * Set to NULL so that when the InterpInfo is cleaned up in the slave     * it does not try to delete the command causing all sorts of grief.     * See SlaveRecordDeleteProc().     */    slavePtr->interpCmd = NULL;    if (slavePtr->slaveInterp != NULL) {	Tcl_DeleteInterp(slavePtr->slaveInterp);    }}/* *---------------------------------------------------------------------- * * SlaveEval -- * *	Helper function to evaluate a command in a slave interpreter. * * Results: *	A standard Tcl result. * * Side effects: *	Whatever the command does. * *---------------------------------------------------------------------- */static intSlaveEval(interp, slaveInterp, objc, objv)    Tcl_Interp *interp;		/* Interp for error return. */    Tcl_Interp *slaveInterp;	/* The slave interpreter in which command				 * will be evaluated. */    int objc;			/* Number of arguments. */    Tcl_Obj *CONST objv[];	/* Argument objects. */{    int result;    Tcl_Obj *objPtr;        Tcl_Preserve((ClientData) slaveInterp);    Tcl_AllowExceptions(slaveInterp);    if (objc == 1) {	result = Tcl_EvalObjEx(slaveInterp, objv[0], 0);    } else {	objPtr = Tcl_ConcatObj(objc, objv);	Tcl_IncrRefCount(objPtr);	result = Tcl_EvalObjEx(slaveInterp, objPtr, 0);	Tcl_DecrRefCount(objPtr);    }    TclTransferResult(slaveInterp, result, interp);    Tcl_Release((ClientData) slaveInterp);    return result;}/* *---------------------------------------------------------------------- * * SlaveExpose -- * *	Helper function to expose a command in a slave interpreter. * * Results: *	A standard Tcl result. * * Side effects: *	After this call scripts in the slave will be able to invoke *	the newly exposed command. * *---------------------------------------------------------------------- */static intSlaveExpose(interp, slaveInterp, objc, objv)    Tcl_Interp *interp;		/* Interp for error return. */    Tcl_Interp	*slaveInterp;	/* Interp in which command will be exposed. */    int objc;			/* Number of arguments. */    Tcl_Obj *CONST objv[];	/* Argument strings. */{    char *name;        if (Tcl_IsSafe(interp)) {	Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),		"permission denied: safe interpreter cannot expose commands",		(char *) NULL);	return TCL_ERROR;    }    name = Tcl_GetString(objv[(objc == 1) ? 0 : 1]);    if (Tcl_ExposeCommand(slaveInterp, Tcl_GetString(objv[0]),	    name) != TCL_OK) {	TclTransferResult(slaveInterp, TCL_ERROR, interp);	return TCL_ERROR;    }    return TCL_OK;}/* *---------------------------------------------------------------------- * * SlaveRecursionLimit -- * *	Helper function to set/query the Recursion limit of an interp * * Results: *	A standard Tcl result. * * Side effects: *      When (objc == 1), slaveInterp will be set to a new recursion *	limit of objv[0]. * *---------------------------------------------------------------------- */static intSlaveRecursionLimit(interp, slaveInterp, objc, objv)    Tcl_Interp *interp;		/* Interp for error return. */    Tcl_Interp	*slaveInterp;	/* Interp in which limit is set/queried. */    int objc;			/* Set or Query. */    Tcl_Obj *CONST objv[];	/* Argument strings. */{    Interp *iPtr;    int limit;    if (objc) {	if (Tcl_IsSafe(interp)) {	    Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),		    "permission denied: ",		    "safe interpreters cannot change recursion limit",		    (char *) NULL);	    return TCL_ERROR;	}	if (Tcl_GetIntFromObj(interp, objv[0], &limit) == TCL_ERROR) {	    return TCL_ERROR;	}	if (limit <= 0) {	    Tcl_SetObjResult(interp, Tcl_NewStringObj(		    "recursion limit must be > 0", -1));	    return TCL_ERROR;	}	Tcl_SetRecursionLimit(slaveInterp, limit);	iPtr = (Interp *) slaveInterp;	if (interp == slaveInterp && iPtr->numLevels > limit) {	    Tcl_SetObjResult(interp, Tcl_NewStringObj(		    "falling back due to new recursion limit", -1));	    return TCL_ERROR;	}	Tcl_SetObjResult(interp, objv[0]);        return TCL_OK;    } else {	limit = Tcl_SetRecursionLimit(slaveInterp, 0);	Tcl_SetObjResult(interp, Tcl_NewIntObj(limit));        return TCL_OK;    }}/* *---------------------------------------------------------------------- * * SlaveHide -- * *	Helper function to hide a command in a slave interpreter. * * Results: *	A standard Tcl result. * * Side effects: *	After this call scripts in the slave will no longer be able *	to invoke the named command. * *---------------------------------------------------------------------- */static intSlaveHide(interp, slaveInterp, objc, objv)    Tcl_Interp *interp;		/* Interp for error return. */    Tcl_Interp	*slaveInterp;	/* Interp in which command will be exposed. */    int objc;			/* Number of arguments. */    Tcl_Obj *CONST objv[];	/* Argument strings. */{    char *name;        if (Tcl_IsSafe(interp)) {	Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),		"permission denied: safe interpreter cannot hide commands",		(char *) NULL);	return TCL_ERROR;    }    name = Tcl_GetString(objv[(objc == 1) ? 0 : 1]);    if (Tcl_HideCommand(slaveInterp, Tcl_GetString(objv[0]),	    name) != TCL_OK) {	TclTransferResult(slaveInterp, TCL_ERROR, interp);	return TCL_ERROR;    }    return TCL_OK;}/* *---------------------------------------------------------------------- * * SlaveHidden -- * *	Helper function to compute list of hidden commands in a slave *	interpreter. * * Results: *	A standard Tcl result. * * Side effects: *	None. * *---------------------------------

⌨️ 快捷键说明

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