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

📄 tclexecute.c

📁 tcl是工具命令语言
💻 C
📖 第 1 页 / 共 5 页
字号:
    {"double", 1, {TCL_EITHER}, ExprDoubleFunc, 0},    {"int", 1, {TCL_EITHER}, ExprIntFunc, 0},    {"rand", 0, {TCL_EITHER}, ExprRandFunc, 0},	/* NOTE: rand takes no args. */    {"round", 1, {TCL_EITHER}, ExprRoundFunc, 0},    {"srand", 1, {TCL_INT}, ExprSrandFunc, 0},#ifdef TCL_WIDE_INT_IS_LONG    {"wide", 1, {TCL_EITHER}, ExprIntFunc, 0},#else    {"wide", 1, {TCL_EITHER}, ExprWideFunc, 0},#endif /* TCL_WIDE_INT_IS_LONG */    {0},};/* *---------------------------------------------------------------------- * * InitByteCodeExecution -- * *	This procedure is called once to initialize the Tcl bytecode *	interpreter. * * Results: *	None. * * Side effects: *	This procedure initializes the array of instruction names. If *	compiling with the TCL_COMPILE_STATS flag, it initializes the *	array that counts the executions of each instruction and it *	creates the "evalstats" command. It also establishes the link  *      between the Tcl "tcl_traceExec" and C "tclTraceExec" variables. * *---------------------------------------------------------------------- */static voidInitByteCodeExecution(interp)    Tcl_Interp *interp;		/* Interpreter for which the Tcl variable				 * "tcl_traceExec" is linked to control				 * instruction tracing. */{#ifdef TCL_COMPILE_DEBUG    if (Tcl_LinkVar(interp, "tcl_traceExec", (char *) &tclTraceExec,		    TCL_LINK_INT) != TCL_OK) {	panic("InitByteCodeExecution: can't create link for tcl_traceExec variable");    }#endif#ifdef TCL_COMPILE_STATS        Tcl_CreateObjCommand(interp, "evalstats", EvalStatsCmd,	    (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);#endif /* TCL_COMPILE_STATS */}/* *---------------------------------------------------------------------- * * TclCreateExecEnv -- * *	This procedure creates a new execution environment for Tcl bytecode *	execution. An ExecEnv points to a Tcl evaluation stack. An ExecEnv *	is typically created once for each Tcl interpreter (Interp *	structure) and recursively passed to TclExecuteByteCode to execute *	ByteCode sequences for nested commands. * * Results: *	A newly allocated ExecEnv is returned. This points to an empty *	evaluation stack of the standard initial size. * * Side effects: *	The bytecode interpreter is also initialized here, as this *	procedure will be called before any call to TclExecuteByteCode. * *---------------------------------------------------------------------- */#define TCL_STACK_INITIAL_SIZE 2000ExecEnv *TclCreateExecEnv(interp)    Tcl_Interp *interp;		/* Interpreter for which the execution				 * environment is being created. */{    ExecEnv *eePtr = (ExecEnv *) ckalloc(sizeof(ExecEnv));    Tcl_Obj **stackPtr;    stackPtr = (Tcl_Obj **)	ckalloc((size_t) (TCL_STACK_INITIAL_SIZE * sizeof(Tcl_Obj *)));    /*     * Use the bottom pointer to keep a reference count; the      * execution environment holds a reference.     */    stackPtr++;    eePtr->stackPtr = stackPtr;    stackPtr[-1] = (Tcl_Obj *) ((char *) 1);    eePtr->stackTop = -1;    eePtr->stackEnd = (TCL_STACK_INITIAL_SIZE - 2);    eePtr->errorInfo = Tcl_NewStringObj("::errorInfo", -1);    Tcl_IncrRefCount(eePtr->errorInfo);    eePtr->errorCode = Tcl_NewStringObj("::errorCode", -1);    Tcl_IncrRefCount(eePtr->errorCode);    Tcl_MutexLock(&execMutex);    if (!execInitialized) {	TclInitAuxDataTypeTable();	InitByteCodeExecution(interp);	execInitialized = 1;    }    Tcl_MutexUnlock(&execMutex);    return eePtr;}#undef TCL_STACK_INITIAL_SIZE/* *---------------------------------------------------------------------- * * TclDeleteExecEnv -- * *	Frees the storage for an ExecEnv. * * Results: *	None. * * Side effects: *	Storage for an ExecEnv and its contained storage (e.g. the *	evaluation stack) is freed. * *---------------------------------------------------------------------- */voidTclDeleteExecEnv(eePtr)    ExecEnv *eePtr;		/* Execution environment to free. */{    if (eePtr->stackPtr[-1] == (Tcl_Obj *) ((char *) 1)) {	ckfree((char *) (eePtr->stackPtr-1));    } else {	panic("ERROR: freeing an execEnv whose stack is still in use.\n");    }    TclDecrRefCount(eePtr->errorInfo);    TclDecrRefCount(eePtr->errorCode);    ckfree((char *) eePtr);}/* *---------------------------------------------------------------------- * * TclFinalizeExecution -- * *	Finalizes the execution environment setup so that it can be *	later reinitialized. * * Results: *	None. * * Side effects: *	After this call, the next time TclCreateExecEnv will be called *	it will call InitByteCodeExecution. * *---------------------------------------------------------------------- */voidTclFinalizeExecution(){    Tcl_MutexLock(&execMutex);    execInitialized = 0;    Tcl_MutexUnlock(&execMutex);    TclFinalizeAuxDataTypeTable();}/* *---------------------------------------------------------------------- * * GrowEvaluationStack -- * *	This procedure grows a Tcl evaluation stack stored in an ExecEnv. * * Results: *	None. * * Side effects: *	The size of the evaluation stack is doubled. * *---------------------------------------------------------------------- */static voidGrowEvaluationStack(eePtr)    register ExecEnv *eePtr; /* Points to the ExecEnv with an evaluation			      * stack to enlarge. */{    /*     * The current Tcl stack elements are stored from eePtr->stackPtr[0]     * to eePtr->stackPtr[eePtr->stackEnd] (inclusive).     */    int currElems = (eePtr->stackEnd + 1);    int newElems  = 2*currElems;    int currBytes = currElems * sizeof(Tcl_Obj *);    int newBytes  = 2*currBytes;    Tcl_Obj **newStackPtr = (Tcl_Obj **) ckalloc((unsigned) newBytes);    Tcl_Obj **oldStackPtr = eePtr->stackPtr;    /*     * We keep the stack reference count as a (char *), as that     * works nicely as a portable pointer-sized counter.     */    char *refCount = (char *) oldStackPtr[-1];    /*     * Copy the existing stack items to the new stack space, free the old     * storage if appropriate, and record the refCount of the new stack     * held by the environment.     */     newStackPtr++;    memcpy((VOID *) newStackPtr, (VOID *) oldStackPtr,	   (size_t) currBytes);    if (refCount == (char *) 1) {	ckfree((VOID *) (oldStackPtr-1));    } else {	/*	 * Remove the reference corresponding to the	 * environment pointer.	 */		oldStackPtr[-1] = (Tcl_Obj *) (refCount-1);    }    eePtr->stackPtr = newStackPtr;    eePtr->stackEnd = (newElems - 2); /* index of last usable item */    newStackPtr[-1] = (Tcl_Obj *) ((char *) 1);	}/* *-------------------------------------------------------------- * * Tcl_ExprObj -- * *	Evaluate an expression in a Tcl_Obj. * * Results: *	A standard Tcl object result. If the result is other than TCL_OK, *	then the interpreter's result contains an error message. If the *	result is TCL_OK, then a pointer to the expression's result value *	object is stored in resultPtrPtr. In that case, the object's ref *	count is incremented to reflect the reference returned to the *	caller; the caller is then responsible for the resulting object *	and must, for example, decrement the ref count when it is finished *	with the object. * * Side effects: *	Any side effects caused by subcommands in the expression, if any. *	The interpreter result is not modified unless there is an error. * *-------------------------------------------------------------- */intTcl_ExprObj(interp, objPtr, resultPtrPtr)    Tcl_Interp *interp;		/* Context in which to evaluate the				 * expression. */    register Tcl_Obj *objPtr;	/* Points to Tcl object containing				 * expression to evaluate. */    Tcl_Obj **resultPtrPtr;	/* Where the Tcl_Obj* that is the expression				 * result is stored if no errors occur. */{    Interp *iPtr = (Interp *) interp;    CompileEnv compEnv;		/* Compilation environment structure				 * allocated in frame. */    LiteralTable *localTablePtr = &(compEnv.localLitTable);    register ByteCode *codePtr = NULL;    				/* Tcl Internal type of bytecode.				 * Initialized to avoid compiler warning. */    AuxData *auxDataPtr;    LiteralEntry *entryPtr;    Tcl_Obj *saveObjPtr;    char *string;    int length, i, result;    /*     * First handle some common expressions specially.     */    string = Tcl_GetStringFromObj(objPtr, &length);    if (length == 1) {	if (*string == '0') {	    *resultPtrPtr = Tcl_NewLongObj(0);	    Tcl_IncrRefCount(*resultPtrPtr);	    return TCL_OK;	} else if (*string == '1') {	    *resultPtrPtr = Tcl_NewLongObj(1);	    Tcl_IncrRefCount(*resultPtrPtr);	    return TCL_OK;	}    } else if ((length == 2) && (*string == '!')) {	if (*(string+1) == '0') {	    *resultPtrPtr = Tcl_NewLongObj(1);	    Tcl_IncrRefCount(*resultPtrPtr);	    return TCL_OK;	} else if (*(string+1) == '1') {	    *resultPtrPtr = Tcl_NewLongObj(0);	    Tcl_IncrRefCount(*resultPtrPtr);	    return TCL_OK;	}    }    /*     * Get the ByteCode from the object. If it exists, make sure it hasn't     * been invalidated by, e.g., someone redefining a command with a     * compile procedure (this might make the compiled code wrong). If     * necessary, convert the object to be a ByteCode object and compile it.     * Also, if the code was compiled in/for a different interpreter, we     * recompile it.     *     * Precompiled expressions, however, are immutable and therefore     * they are not recompiled, even if the epoch has changed.     *     */    if (objPtr->typePtr == &tclByteCodeType) {	codePtr = (ByteCode *) objPtr->internalRep.otherValuePtr;	if (((Interp *) *codePtr->interpHandle != iPtr)	        || (codePtr->compileEpoch != iPtr->compileEpoch)) {            if (codePtr->flags & TCL_BYTECODE_PRECOMPILED) {                if ((Interp *) *codePtr->interpHandle != iPtr) {                    panic("Tcl_ExprObj: compiled expression jumped interps");                }	        codePtr->compileEpoch = iPtr->compileEpoch;            } else {                (*tclByteCodeType.freeIntRepProc)(objPtr);                objPtr->typePtr = (Tcl_ObjType *) NULL;            }	}    }    if (objPtr->typePtr != &tclByteCodeType) {	TclInitCompileEnv(interp, &compEnv, string, length);	result = TclCompileExpr(interp, string, length, &compEnv);	/*	 * Free the compilation environment's literal table bucket array if	 * it was dynamically allocated. 	 */	if (localTablePtr->buckets != localTablePtr->staticBuckets) {	    ckfree((char *) localTablePtr->buckets);	}    	if (result != TCL_OK) {	    /*	     * Compilation errors. Free storage allocated for compilation.	     */#ifdef TCL_COMPILE_DEBUG	    TclVerifyLocalLiteralTable(&compEnv);#endif /*TCL_COMPILE_DEBUG*/	    entryPtr = compEnv.literalArrayPtr;	    for (i = 0;  i < compEnv.literalArrayNext;  i++) {		TclReleaseLiteral(interp, entryPtr->objPtr);		entryPtr++;	    }#ifdef TCL_COMPILE_DEBUG	    TclVerifyGlobalLiteralTable(iPtr);#endif /*TCL_COMPILE_DEBUG*/    	    auxDataPtr = compEnv.auxDataArrayPtr;	    for (i = 0;  i < compEnv.auxDataArrayNext;  i++) {		if (auxDataPtr->type->freeProc != NULL) {		    auxDataPtr->type->freeProc(auxDataPtr->clientData);		}		auxDataPtr++;	    }	    TclFreeCompileEnv(&compEnv);	    return result;	}	/*	 * Successful compilation. If the expression yielded no	 * instructions, push an zero object as the expression's result.	 */	    	if (compEnv.codeNext == compEnv.codeStart) {	    TclEmitPush(TclRegisterLiteral(&compEnv, "0", 1, /*onHeap*/ 0),	            &compEnv);	}	    	/*	 * Add a "done" instruction as the last instruction and change the	 * object into a ByteCode object. Ownership of the literal objects	 * and aux data items is given to the ByteCode object.	 */	compEnv.numSrcBytes = iPtr->termOffset;	TclEmitOpcode(INST_DONE, &compEnv);	TclInitByteCodeObj(objPtr, &compEnv);	TclFreeCompileEnv(&compEnv);	codePtr = (ByteCode *) objPtr->internalRep.otherValuePtr;#ifdef TCL_COMPILE_DEBUG	if (tclTraceCompile == 2) {	    TclPrintByteCodeObj(interp, objPtr);	}#endif /* TCL_COMPILE_DEBUG */    }    /*     * Execute the expression after first saving the interpreter's result.     */        saveObjPtr = Tcl_GetObjResult(interp);    Tcl_IncrRefCount(saveObjPtr);    Tcl_ResetResult(interp);    /*     * Increment the code's ref count while it is being executed. If     * afterwards no references to it remain, free the code.     */        codePtr->refCount++;    result = TclExecuteByteCode(interp, codePtr);    codePtr->refCount--;    if (codePtr->refCount <= 0) {	TclCleanupByteCode(codePtr);	objPtr->typePtr = NULL;	objPtr->internalRep.otherValuePtr = NULL;    }        /*

⌨️ 快捷键说明

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