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

📄 tclcompexpr.c

📁 linux系统下的音频通信
💻 C
📖 第 1 页 / 共 5 页
字号:
/*  * tclCompExpr.c -- * *	This file contains the code to compile Tcl expressions. * * Copyright (c) 1996-1997 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * * SCCS: @(#) tclCompExpr.c 1.34 97/11/03 14:29:18 */#include "tclInt.h"#include "tclCompile.h"/* * 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 arrange to use * the errno from tclExecute.c here. */#ifndef TCL_GENERIC_ONLY#include "tclPort.h"#else#define NO_ERRNO_H#endif#ifdef NO_ERRNO_Hextern int errno;			/* Use errno from tclExecute.c. */#define ERANGE 34#endif/* * Boolean variable that controls whether expression compilation tracing * is enabled. */#ifdef TCL_COMPILE_DEBUGstatic int traceCompileExpr = 0;#endif /* TCL_COMPILE_DEBUG *//* * The ExprInfo structure describes the state of compiling an expression. * A pointer to an ExprInfo record is passed among the routines in * this module. */typedef struct ExprInfo {    int token;			/* Type of the last token parsed in expr.				 * See below for definitions. Corresponds				 * to the characters just before next. */    int objIndex;		/* If token is a literal value, the index of				 * an object holding the value in the code's				 * object table; otherwise is NULL. */    char *funcName;		/* If the token is FUNC_NAME, points to the				 * first character of the math function's				 * name; otherwise is NULL. */    char *next;			/* Position of the next character to be				 * scanned in the expression string. */    char *originalExpr;		/* The entire expression that was originally				 * passed to Tcl_ExprString et al. */    char *lastChar;		/* Pointer to terminating null in				 * originalExpr. */    int hasOperators;		/* Set 1 if the expr has operators; 0 if				 * expr is only a primary. If 1 after				 * compiling an expr, a tryCvtToNumeric				 * instruction is emitted to convert the				 * primary to a number if possible. */    int exprIsJustVarRef;	/* Set 1 if the expr consists of just a				 * variable reference as in the expression				 * of "if $b then...". Otherwise 0. If 1 the				 * expr is compiled out-of-line in order to				 * implement expr's 2 level substitution				 * semantics properly. */    int exprIsComparison;	/* Set 1 if the top-level operator in the				 * expr is a comparison. Otherwise 0. If 1,				 * because the operands might be strings,				 * the expr is compiled out-of-line in order				 * to implement expr's 2 level substitution				 * semantics properly. */} ExprInfo;/* * Definitions of the different tokens that appear in expressions. The order * of these must match the corresponding entries in the operatorStrings * array below. */#define LITERAL		0#define FUNC_NAME	(LITERAL + 1)#define OPEN_BRACKET	(LITERAL + 2)#define CLOSE_BRACKET	(LITERAL + 3)#define OPEN_PAREN	(LITERAL + 4)#define CLOSE_PAREN	(LITERAL + 5)#define DOLLAR		(LITERAL + 6)#define QUOTE		(LITERAL + 7)#define COMMA		(LITERAL + 8)#define END		(LITERAL + 9)#define UNKNOWN		(LITERAL + 10)/* * Binary operators: */#define MULT		(UNKNOWN + 1)#define DIVIDE		(MULT + 1)#define MOD		(MULT + 2)#define PLUS		(MULT + 3)#define MINUS		(MULT + 4)#define LEFT_SHIFT	(MULT + 5)#define RIGHT_SHIFT	(MULT + 6)#define LESS		(MULT + 7)#define GREATER		(MULT + 8)#define LEQ		(MULT + 9)#define GEQ		(MULT + 10)#define EQUAL		(MULT + 11)#define NEQ		(MULT + 12)#define BIT_AND		(MULT + 13)#define BIT_XOR		(MULT + 14)#define BIT_OR		(MULT + 15)#define AND		(MULT + 16)#define OR		(MULT + 17)#define QUESTY		(MULT + 18)#define COLON		(MULT + 19)/* * Unary operators. Unary minus and plus are represented by the (binary) * tokens MINUS and PLUS. */#define NOT		(COLON + 1)#define BIT_NOT		(NOT + 1)/* * Mapping from tokens to strings; used for debugging messages. These * entries must match the order and number of the token definitions above. */#ifdef TCL_COMPILE_DEBUGstatic char *tokenStrings[] = {    "LITERAL", "FUNCNAME",    "[", "]", "(", ")", "$", "\"", ",", "END", "UNKNOWN",    "*", "/", "%", "+", "-",    "<<", ">>", "<", ">", "<=", ">=", "==", "!=",    "&", "^", "|", "&&", "||", "?", ":",    "!", "~"};#endif /* TCL_COMPILE_DEBUG *//* * Declarations for local procedures to this file: */static int		CompileAddExpr _ANSI_ARGS_((Tcl_Interp *interp,			    ExprInfo *infoPtr, int flags,			    CompileEnv *envPtr));static int		CompileBitAndExpr _ANSI_ARGS_((Tcl_Interp *interp,			    ExprInfo *infoPtr, int flags,			    CompileEnv *envPtr));static int		CompileBitOrExpr _ANSI_ARGS_((Tcl_Interp *interp,			    ExprInfo *infoPtr, int flags,			    CompileEnv *envPtr));static int		CompileBitXorExpr _ANSI_ARGS_((Tcl_Interp *interp,			    ExprInfo *infoPtr, int flags,			    CompileEnv *envPtr));static int		CompileCondExpr _ANSI_ARGS_((Tcl_Interp *interp,			    ExprInfo *infoPtr, int flags,			    CompileEnv *envPtr));static int		CompileEqualityExpr _ANSI_ARGS_((Tcl_Interp *interp,			    ExprInfo *infoPtr, int flags,			    CompileEnv *envPtr));static int		CompileLandExpr _ANSI_ARGS_((Tcl_Interp *interp,			    ExprInfo *infoPtr, int flags,			    CompileEnv *envPtr));static int		CompileLorExpr _ANSI_ARGS_((Tcl_Interp *interp,			    ExprInfo *infoPtr, int flags,			    CompileEnv *envPtr));static int		CompileMathFuncCall _ANSI_ARGS_((Tcl_Interp *interp,			    ExprInfo *infoPtr, int flags,			    CompileEnv *envPtr));static int		CompileMultiplyExpr _ANSI_ARGS_((Tcl_Interp *interp,			    ExprInfo *infoPtr, int flags,			    CompileEnv *envPtr));static int		CompilePrimaryExpr _ANSI_ARGS_((Tcl_Interp *interp,			    ExprInfo *infoPtr, int flags,			    CompileEnv *envPtr));static int		CompileRelationalExpr _ANSI_ARGS_((    			    Tcl_Interp *interp, ExprInfo *infoPtr,			    int flags, CompileEnv *envPtr));static int		CompileShiftExpr _ANSI_ARGS_((Tcl_Interp *interp,			    ExprInfo *infoPtr, int flags,			    CompileEnv *envPtr));static int		CompileUnaryExpr _ANSI_ARGS_((Tcl_Interp *interp,			    ExprInfo *infoPtr, int flags,			    CompileEnv *envPtr));static int		GetToken _ANSI_ARGS_((Tcl_Interp *interp,			    ExprInfo *infoPtr, CompileEnv *envPtr));/* * Macro used to debug the execution of the recursive descent parser used * to compile expressions. */#ifdef TCL_COMPILE_DEBUG#define HERE(production, level) \    if (traceCompileExpr) { \	fprintf(stderr, "%*s%s: token=%s, next=\"%.20s\"\n", \		(level), " ", (production), tokenStrings[infoPtr->token], \		infoPtr->next); \    }#else#define HERE(production, level)#endif /* TCL_COMPILE_DEBUG *//* *---------------------------------------------------------------------- * * TclCompileExpr -- * *	This procedure compiles a string containing a Tcl expression into *	Tcl bytecodes. This procedure is the top-level interface to the *	the expression compilation module, and is used by such public *	procedures as Tcl_ExprString, Tcl_ExprStringObj, Tcl_ExprLong, *	Tcl_ExprDouble, Tcl_ExprBoolean, and Tcl_ExprBooleanObj. * *	Note that the topmost recursive-descent parsing routine used by *	TclCompileExpr to compile expressions is called "CompileCondExpr" *	and not, e.g., "CompileExpr". This is done to avoid an extra *	procedure call since such a procedure would only return the result *	of calling CompileCondExpr. Other recursive-descent procedures *	that need to parse expressions also call CompileCondExpr. * * Results: *	The return value is TCL_OK on a successful compilation and TCL_ERROR *	on failure. If TCL_ERROR is returned, then the interpreter's result *	contains an error message. * *	envPtr->termOffset is filled in with the offset of the character in *	"string" just after the last one successfully processed; this might *	be the offset of the ']' (if flags & TCL_BRACKET_TERM), or the *	offset of the '\0' at the end of the string. * *	envPtr->maxStackDepth is updated with the maximum number of stack *	elements needed to execute the expression. * *	envPtr->exprIsJustVarRef is set 1 if the expression consisted of *	a single variable reference as in the expression of "if $b then...". *	Otherwise it is set 0. This is used to implement Tcl's two level *	expression substitution semantics properly. * *	envPtr->exprIsComparison is set 1 if the top-level operator in the *	expr is a comparison. Otherwise it is set 0. If 1, because the *	operands might be strings, the expr is compiled out-of-line in order *	to implement expr's 2 level substitution semantics properly. * * Side effects: *	Adds instructions to envPtr to evaluate the expression at runtime. * *---------------------------------------------------------------------- */intTclCompileExpr(interp, string, lastChar, flags, envPtr)    Tcl_Interp *interp;		/* Used for error reporting. */    char *string;		/* The source string to compile. */    char *lastChar;		/* Pointer to terminating character of				 * string. */    int flags;			/* Flags to control compilation (same as				 * passed to Tcl_Eval). */    CompileEnv *envPtr;		/* Holds resulting instructions. */{    Interp *iPtr = (Interp *) interp;    ExprInfo info;    int maxDepth = 0;		/* Maximum number of stack elements needed				 * to execute the expression. */    int result;#ifdef TCL_COMPILE_DEBUG    if (traceCompileExpr) {	fprintf(stderr, "expr: string=\"%.30s\"\n", string);    }#endif /* TCL_COMPILE_DEBUG */    /*     * Register the builtin math functions the first time an expression is     * compiled.     */    if (!(iPtr->flags & EXPR_INITIALIZED)) {	BuiltinFunc *funcPtr;	Tcl_HashEntry *hPtr;	MathFunc *mathFuncPtr;	int i;	iPtr->flags |= EXPR_INITIALIZED;	i = 0;	for (funcPtr = builtinFuncTable; funcPtr->name != NULL; funcPtr++) {	    Tcl_CreateMathFunc(interp, funcPtr->name,		    funcPtr->numArgs, funcPtr->argTypes,		    (Tcl_MathProc *) NULL, (ClientData) 0);	    	    hPtr = Tcl_FindHashEntry(&iPtr->mathFuncTable, funcPtr->name);	    if (hPtr == NULL) {		panic("TclCompileExpr: Tcl_CreateMathFunc incorrectly registered '%s'", funcPtr->name);		return TCL_ERROR;	    }	    mathFuncPtr = (MathFunc *) Tcl_GetHashValue(hPtr);	    mathFuncPtr->builtinFuncIndex = i;	    i++;	}    }    info.token = UNKNOWN;    info.objIndex = -1;    info.funcName = NULL;    info.next = string;    info.originalExpr = string;    info.lastChar = lastChar;    info.hasOperators = 0;    info.exprIsJustVarRef = 1;	/* will be set 0 if anything else is seen */    info.exprIsComparison = 0;	/* set 1 if topmost operator is <,==,etc. */    /*     * Get the first token then compile an expression.     */    result = GetToken(interp, &info, envPtr);    if (result != TCL_OK) {	goto done;    }        result = CompileCondExpr(interp, &info, flags, envPtr);    if (result != TCL_OK) {	goto done;    }    if (info.token != END) {	Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),		"syntax error in expression \"", string, "\"", (char *) NULL);	result = TCL_ERROR;	goto done;    }    if (!info.hasOperators) {	/*	 * Attempt to convert the primary's object to an int or double.	 * This is done in order to support Tcl's policy of interpreting	 * operands if at all possible as first integers, else	 * floating-point numbers.	 */		TclEmitOpcode(INST_TRY_CVT_TO_NUMERIC, envPtr);    }    maxDepth = envPtr->maxStackDepth;    done:    envPtr->termOffset = (info.next - string);    envPtr->maxStackDepth = maxDepth;    envPtr->exprIsJustVarRef = info.exprIsJustVarRef;    envPtr->exprIsComparison = info.exprIsComparison;    return result;}/* *---------------------------------------------------------------------- * * CompileCondExpr -- * *	This procedure compiles a Tcl conditional expression: *	condExpr ::= lorExpr ['?' condExpr ':' condExpr] * *	Note that this is the topmost recursive-descent parsing routine used *	by TclCompileExpr to compile expressions. It does not call an *	separate, higher-level "CompileExpr" procedure. This avoids an extra *	procedure call since such a procedure would only return the result *	of calling CompileCondExpr. Other recursive-descent procedures that *	need to parse expressions also call CompileCondExpr. * * Results: *	The return value is TCL_OK on a successful compilation and TCL_ERROR *	on failure. If TCL_ERROR is returned, then the interpreter's result *	contains an error message. * *	envPtr->maxStackDepth is updated with the maximum number of stack *	elements needed to execute the expression. * * Side effects: *	Adds instructions to envPtr to evaluate the expression at runtime. * *---------------------------------------------------------------------- */static intCompileCondExpr(interp, infoPtr, flags, envPtr)    Tcl_Interp *interp;		/* Used for error reporting. */    ExprInfo *infoPtr;		/* Describes the compilation state for the				 * expression being compiled. */    int flags;			/* Flags to control compilation (same as				 * passed to Tcl_Eval). */    CompileEnv *envPtr;		/* Holds resulting instructions. */{    int maxDepth = 0;		/* Maximum number of stack elements needed				 * to execute the expression. */    JumpFixup jumpAroundThenFixup, jumpAroundElseFixup;				/* Used to update or replace one-byte jumps				 * around the then and else expressions when				 * their target PCs are determined. */    int elseCodeOffset, currCodeOffset, jumpDist, result;        HERE("condExpr", 1);    result = CompileLorExpr(interp, infoPtr, flags, envPtr);    if (result != TCL_OK) {	goto done;    }    maxDepth = envPtr->maxStackDepth;        if (infoPtr->token == QUESTY) {	result = GetToken(interp, infoPtr, envPtr); /* skip over the '?' */	if (result != TCL_OK) {	    goto done;	}	/*	 * Emit the jump around the "then" clause to the "else" condExpr if	 * the test was false. We emit a one byte (relative) jump here, and	 * replace it later with a four byte jump if the jump target is more	 * than 127 bytes away.	 */	TclEmitForwardJump(envPtr, TCL_FALSE_JUMP, &jumpAroundThenFixup);	/*	 * Compile the "then" expression. Note that if a subexpression	 * is only a primary, we need to try to convert it to numeric.	 * This is done in order to support Tcl's policy of interpreting	 * operands if at all possible as first integers, else	 * floating-point numbers.	 */	infoPtr->hasOperators = 0;	infoPtr->exprIsJustVarRef = 0;	infoPtr->exprIsComparison = 0;	result = CompileCondExpr(interp, infoPtr, flags, envPtr);	if (result != TCL_OK) {	    goto done;	}	maxDepth = TclMax(envPtr->maxStackDepth, maxDepth);	if (infoPtr->token != COLON) {	    Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),

⌨️ 快捷键说明

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