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

📄 tclexecute.c

📁 tcl是工具命令语言
💻 C
📖 第 1 页 / 共 5 页
字号:
/*  * tclExecute.c -- * *	This file contains procedures that execute byte-compiled Tcl *	commands. * * Copyright (c) 1996-1997 Sun Microsystems, Inc. * Copyright (c) 1998-2000 by Scriptics Corporation. * Copyright (c) 2001 by Kevin B. Kenny.  All rights reserved. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * * RCS: @(#) $Id: tclExecute.c,v 1.94 2003/02/19 14:33:39 msofer Exp $ */#include "tclInt.h"#include "tclCompile.h"#ifndef TCL_NO_MATH#   include "tclMath.h"#endif/* * The stuff below is a bit of a hack so that this file can be used * in environments that include no UNIX, i.e. no errno.  Just define * errno here. */#ifndef TCL_GENERIC_ONLY#   include "tclPort.h"#else /* TCL_GENERIC_ONLY */#   ifndef NO_FLOAT_H#	include <float.h>#   else /* NO_FLOAT_H */#	ifndef NO_VALUES_H#	    include <values.h>#	endif /* !NO_VALUES_H */#   endif /* !NO_FLOAT_H */#   define NO_ERRNO_H#endif /* !TCL_GENERIC_ONLY */#ifdef NO_ERRNO_Hint errno;#   define EDOM   33#   define ERANGE 34#endif/* * Need DBL_MAX for IS_INF() macro... */#ifndef DBL_MAX#   ifdef MAXDOUBLE#	define DBL_MAX MAXDOUBLE#   else /* !MAXDOUBLE *//* * This value is from the Solaris headers, but doubles seem to be the * same size everywhere.  Long doubles aren't, but we don't use those. */#	define DBL_MAX 1.79769313486231570e+308#   endif /* MAXDOUBLE */#endif /* !DBL_MAX *//* * Boolean flag indicating whether the Tcl bytecode interpreter has been * initialized. */static int execInitialized = 0;TCL_DECLARE_MUTEX(execMutex)#ifdef TCL_COMPILE_DEBUG/* * Variable that controls whether execution tracing is enabled and, if so, * what level of tracing is desired: *    0: no execution tracing *    1: trace invocations of Tcl procs only *    2: trace invocations of all (not compiled away) commands *    3: display each instruction executed * This variable is linked to the Tcl variable "tcl_traceExec". */int tclTraceExec = 0;#endif/* * Mapping from expression instruction opcodes to strings; used for error * messages. Note that these entries must match the order and number of the * expression opcodes (e.g., INST_LOR) in tclCompile.h. */static char *operatorStrings[] = {    "||", "&&", "|", "^", "&", "==", "!=", "<", ">", "<=", ">=", "<<", ">>",    "+", "-", "*", "/", "%", "+", "-", "~", "!",    "BUILTIN FUNCTION", "FUNCTION",    "", "", "", "", "", "", "", "", "eq", "ne",};/* * Mapping from Tcl result codes to strings; used for error and debugging * messages.  */#ifdef TCL_COMPILE_DEBUGstatic char *resultStrings[] = {    "TCL_OK", "TCL_ERROR", "TCL_RETURN", "TCL_BREAK", "TCL_CONTINUE"};#endif/* * These are used by evalstats to monitor object usage in Tcl. */#ifdef TCL_COMPILE_STATSlong		tclObjsAlloced = 0;long		tclObjsFreed   = 0;#define TCL_MAX_SHARED_OBJ_STATS 5long		tclObjsShared[TCL_MAX_SHARED_OBJ_STATS] = { 0, 0, 0, 0, 0 };#endif /* TCL_COMPILE_STATS *//* * Macros for testing floating-point values for certain special cases. Test * for not-a-number by comparing a value against itself; test for infinity * by comparing against the largest floating-point value. */#define IS_NAN(v) ((v) != (v))#define IS_INF(v) (((v) > DBL_MAX) || ((v) < -DBL_MAX))/* * The new macro for ending an instruction; note that a * reasonable C-optimiser will resolve all branches * at compile time. (result) is always a constant; the macro  * NEXT_INST_F handles constant (nCleanup), NEXT_INST_V is * resolved at runtime for variable (nCleanup). * * ARGUMENTS: *    pcAdjustment: how much to increment pc *    nCleanup: how many objects to remove from the stack *    result: 0 indicates no object should be pushed on the *       stack; otherwise, push objResultPtr. If (result < 0), *       objResultPtr already has the correct reference count. */#define NEXT_INST_F(pcAdjustment, nCleanup, result) \     if (nCleanup == 0) {\	 if (result != 0) {\	     if ((result) > 0) {\		 PUSH_OBJECT(objResultPtr);\	     } else {\		 stackPtr[++stackTop] = objResultPtr;\	     }\	 } \	 pc += (pcAdjustment);\	 goto cleanup0;\     } else if (result != 0) {\	 if ((result) > 0) {\	     Tcl_IncrRefCount(objResultPtr);\	 }\	 pc += (pcAdjustment);\	 switch (nCleanup) {\	     case 1: goto cleanup1_pushObjResultPtr;\	     case 2: goto cleanup2_pushObjResultPtr;\	     default: panic("ERROR: bad usage of macro NEXT_INST_F");\	 }\     } else {\	 pc += (pcAdjustment);\	 switch (nCleanup) {\	     case 1: goto cleanup1;\	     case 2: goto cleanup2;\	     default: panic("ERROR: bad usage of macro NEXT_INST_F");\	 }\     }#define NEXT_INST_V(pcAdjustment, nCleanup, result) \    pc += (pcAdjustment);\    cleanup = (nCleanup);\    if (result) {\	if ((result) > 0) {\	    Tcl_IncrRefCount(objResultPtr);\	}\	goto cleanupV_pushObjResultPtr;\    } else {\	goto cleanupV;\    }/* * Macros used to cache often-referenced Tcl evaluation stack information * in local variables. Note that a DECACHE_STACK_INFO()-CACHE_STACK_INFO() * pair must surround any call inside TclExecuteByteCode (and a few other * procedures that use this scheme) that could result in a recursive call * to TclExecuteByteCode. */#define CACHE_STACK_INFO() \    stackPtr = eePtr->stackPtr; \    stackTop = eePtr->stackTop#define DECACHE_STACK_INFO() \    eePtr->stackTop = stackTop/* * Macros used to access items on the Tcl evaluation stack. PUSH_OBJECT * increments the object's ref count since it makes the stack have another * reference pointing to the object. However, POP_OBJECT does not decrement * the ref count. This is because the stack may hold the only reference to * the object, so the object would be destroyed if its ref count were * decremented before the caller had a chance to, e.g., store it in a * variable. It is the caller's responsibility to decrement the ref count * when it is finished with an object. * * WARNING! It is essential that objPtr only appear once in the PUSH_OBJECT * macro. The actual parameter might be an expression with side effects, * and this ensures that it will be executed only once.  */    #define PUSH_OBJECT(objPtr) \    Tcl_IncrRefCount(stackPtr[++stackTop] = (objPtr))    #define POP_OBJECT() \    (stackPtr[stackTop--])/* * Macros used to trace instruction execution. The macros TRACE, * TRACE_WITH_OBJ, and O2S are only used inside TclExecuteByteCode. * O2S is only used in TRACE* calls to get a string from an object. */#ifdef TCL_COMPILE_DEBUG#   define TRACE(a) \    if (traceInstructions) { \        fprintf(stdout, "%2d: %2d (%u) %s ", iPtr->numLevels, stackTop, \	       (unsigned int)(pc - codePtr->codeStart), \	       GetOpcodeName(pc)); \	printf a; \    }#   define TRACE_APPEND(a) \    if (traceInstructions) { \	printf a; \    }#   define TRACE_WITH_OBJ(a, objPtr) \    if (traceInstructions) { \        fprintf(stdout, "%2d: %2d (%u) %s ", iPtr->numLevels, stackTop, \	       (unsigned int)(pc - codePtr->codeStart), \	       GetOpcodeName(pc)); \	printf a; \        TclPrintObject(stdout, objPtr, 30); \        fprintf(stdout, "\n"); \    }#   define O2S(objPtr) \    (objPtr ? TclGetString(objPtr) : "")#else /* !TCL_COMPILE_DEBUG */#   define TRACE(a)#   define TRACE_APPEND(a) #   define TRACE_WITH_OBJ(a, objPtr)#   define O2S(objPtr)#endif /* TCL_COMPILE_DEBUG *//* * Most of the code to support working with wide values is factored * out here because it greatly reduces the number of conditionals * through the rest of the file.  Note that this needs to be * conditional because we do not want to alter Tcl's behaviour on * native-64bit platforms... */#ifndef TCL_WIDE_INT_IS_LONG#define W0	Tcl_LongAsWide(0)/* * Macro to read a string containing either a wide or an int and * decide which it is while decoding it at the same time.  This * enforces the policy that integer constants between LONG_MIN and * LONG_MAX (inclusive) are represented by normal longs, and integer * constants outside that range are represented by wide ints. * * GET_WIDE_OR_INT is the same as REQUIRE_WIDE_OR_INT except it never * generates an error message. */#define REQUIRE_WIDE_OR_INT(resultVar, objPtr, longVar, wideVar)	\    (resultVar) = Tcl_GetWideIntFromObj(interp, (objPtr), &(wideVar));	\    if ((resultVar) == TCL_OK && (wideVar) >= Tcl_LongAsWide(LONG_MIN)	\	    && (wideVar) <= Tcl_LongAsWide(LONG_MAX)) {			\	(objPtr)->typePtr = &tclIntType;				\	(objPtr)->internalRep.longValue = (longVar)			\		= Tcl_WideAsLong(wideVar);				\    }#define GET_WIDE_OR_INT(resultVar, objPtr, longVar, wideVar)		\    (resultVar) = Tcl_GetWideIntFromObj((Tcl_Interp *) NULL, (objPtr),	\	    &(wideVar));						\    if ((resultVar) == TCL_OK && (wideVar) >= Tcl_LongAsWide(LONG_MIN)	\	    && (wideVar) <= Tcl_LongAsWide(LONG_MAX)) {			\	(objPtr)->typePtr = &tclIntType;				\	(objPtr)->internalRep.longValue = (longVar)			\		= Tcl_WideAsLong(wideVar);				\    }#define IS_INTEGER_TYPE(typePtr)					\	((typePtr) == &tclIntType || (typePtr) == &tclWideIntType)/* * Extract a double value from a general numeric object. */#define GET_DOUBLE_VALUE(doubleVar, objPtr, typePtr)			\    if ((typePtr) == &tclIntType) {					\	(doubleVar) = (double) (objPtr)->internalRep.longValue;		\    } else if ((typePtr) == &tclWideIntType) {				\	(doubleVar) = Tcl_WideAsDouble((objPtr)->internalRep.wideValue);\    } else {								\	(doubleVar) = (objPtr)->internalRep.doubleValue;		\    }/* * Combined with REQUIRE_WIDE_OR_INT, this gets a long value from * an obj. */#define FORCE_LONG(objPtr, longVar, wideVar)				\    if ((objPtr)->typePtr == &tclWideIntType) {				\	(longVar) = Tcl_WideAsLong(wideVar);				\    }/* * For tracing that uses wide values. */#define LLTRACE(a)			TRACE(a)#define LLTRACE_WITH_OBJ(a,b)		TRACE_WITH_OBJ(a,b)#define LLD				"%" TCL_LL_MODIFIER "d"#else /* TCL_WIDE_INT_IS_LONG *//* * Versions of the above that do not use wide values. */#define REQUIRE_WIDE_OR_INT(resultVar, objPtr, longVar, wideVar)	\    (resultVar) = Tcl_GetLongFromObj(interp, (objPtr), &(longVar));#define GET_WIDE_OR_INT(resultVar, objPtr, longVar, wideVar)		\    (resultVar) = Tcl_GetLongFromObj((Tcl_Interp *) NULL, (objPtr),	\	    &(longVar));#define IS_INTEGER_TYPE(typePtr) ((typePtr) == &tclIntType)#define GET_DOUBLE_VALUE(doubleVar, objPtr, typePtr)			\    if ((typePtr) == &tclIntType) {					\	(doubleVar) = (double) (objPtr)->internalRep.longValue;		\    } else {								\	(doubleVar) = (objPtr)->internalRep.doubleValue;		\    }#define FORCE_LONG(objPtr, longVar, wideVar)#define LLTRACE(a)#define LLTRACE_WITH_OBJ(a,b)#endif /* TCL_WIDE_INT_IS_LONG */#define IS_NUMERIC_TYPE(typePtr)					\	(IS_INTEGER_TYPE(typePtr) || (typePtr) == &tclDoubleType)/* * Declarations for local procedures to this file: */static int		TclExecuteByteCode _ANSI_ARGS_((Tcl_Interp *interp,			    ByteCode *codePtr));static int		ExprAbsFunc _ANSI_ARGS_((Tcl_Interp *interp,			    ExecEnv *eePtr, ClientData clientData));static int		ExprBinaryFunc _ANSI_ARGS_((Tcl_Interp *interp,			    ExecEnv *eePtr, ClientData clientData));static int		ExprCallMathFunc _ANSI_ARGS_((Tcl_Interp *interp,			    ExecEnv *eePtr, int objc, Tcl_Obj **objv));static int		ExprDoubleFunc _ANSI_ARGS_((Tcl_Interp *interp,			    ExecEnv *eePtr, ClientData clientData));static int		ExprIntFunc _ANSI_ARGS_((Tcl_Interp *interp,			    ExecEnv *eePtr, ClientData clientData));static int		ExprRandFunc _ANSI_ARGS_((Tcl_Interp *interp,			    ExecEnv *eePtr, ClientData clientData));static int		ExprRoundFunc _ANSI_ARGS_((Tcl_Interp *interp,			    ExecEnv *eePtr, ClientData clientData));static int		ExprSrandFunc _ANSI_ARGS_((Tcl_Interp *interp,			    ExecEnv *eePtr, ClientData clientData));static int		ExprUnaryFunc _ANSI_ARGS_((Tcl_Interp *interp,			    ExecEnv *eePtr, ClientData clientData));#ifndef TCL_WIDE_INT_IS_LONGstatic int		ExprWideFunc _ANSI_ARGS_((Tcl_Interp *interp,			    ExecEnv *eePtr, ClientData clientData));#endif /* TCL_WIDE_INT_IS_LONG */#ifdef TCL_COMPILE_STATSstatic int              EvalStatsCmd _ANSI_ARGS_((ClientData clientData,                            Tcl_Interp *interp, int objc,			    Tcl_Obj *CONST objv[]));#endif /* TCL_COMPILE_STATS */#ifdef TCL_COMPILE_DEBUGstatic char *		GetOpcodeName _ANSI_ARGS_((unsigned char *pc));#endif /* TCL_COMPILE_DEBUG */static ExceptionRange *	GetExceptRangeForPc _ANSI_ARGS_((unsigned char *pc,			    int catchOnly, ByteCode* codePtr));static char *		GetSrcInfoForPc _ANSI_ARGS_((unsigned char *pc,        		    ByteCode* codePtr, int *lengthPtr));static void		GrowEvaluationStack _ANSI_ARGS_((ExecEnv *eePtr));static void		IllegalExprOperandType _ANSI_ARGS_((			    Tcl_Interp *interp, unsigned char *pc,			    Tcl_Obj *opndPtr));static void		InitByteCodeExecution _ANSI_ARGS_((			    Tcl_Interp *interp));#ifdef TCL_COMPILE_DEBUGstatic void		PrintByteCodeInfo _ANSI_ARGS_((ByteCode *codePtr));static char *		StringForResultCode _ANSI_ARGS_((int result));static void		ValidatePcAndStackTop _ANSI_ARGS_((			    ByteCode *codePtr, unsigned char *pc,			    int stackTop, int stackLowerBound));#endif /* TCL_COMPILE_DEBUG */static int		VerifyExprObjType _ANSI_ARGS_((Tcl_Interp *interp,			    Tcl_Obj *objPtr));/* * Table describing the built-in math functions. Entries in this table are * indexed by the values of the INST_CALL_BUILTIN_FUNC instruction's * operand byte. */BuiltinFunc tclBuiltinFuncTable[] = {#ifndef TCL_NO_MATH    {"acos", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) acos},    {"asin", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) asin},    {"atan", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) atan},    {"atan2", 2, {TCL_DOUBLE, TCL_DOUBLE}, ExprBinaryFunc, (ClientData) atan2},    {"ceil", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) ceil},    {"cos", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) cos},    {"cosh", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) cosh},    {"exp", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) exp},    {"floor", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) floor},    {"fmod", 2, {TCL_DOUBLE, TCL_DOUBLE}, ExprBinaryFunc, (ClientData) fmod},    {"hypot", 2, {TCL_DOUBLE, TCL_DOUBLE}, ExprBinaryFunc, (ClientData) hypot},    {"log", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) log},    {"log10", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) log10},    {"pow", 2, {TCL_DOUBLE, TCL_DOUBLE}, ExprBinaryFunc, (ClientData) pow},    {"sin", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) sin},    {"sinh", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) sinh},    {"sqrt", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) sqrt},    {"tan", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) tan},    {"tanh", 1, {TCL_DOUBLE}, ExprUnaryFunc, (ClientData) tanh},#endif    {"abs", 1, {TCL_EITHER}, ExprAbsFunc, 0},

⌨️ 快捷键说明

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