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

📄 tclexpr.c

📁 tcl源码详细资料
💻 C
📖 第 1 页 / 共 3 页
字号:
	    return TCL_OK;	case '<':	    switch (p[1]) {		case '<':		    infoPtr->expr = p+2;		    infoPtr->token = LEFT_SHIFT;		    break;		case '=':		    infoPtr->expr = p+2;		    infoPtr->token = LEQ;		    break;		default:		    infoPtr->token = LESS;		    break;	    }	    return TCL_OK;	case '>':	    switch (p[1]) {		case '>':		    infoPtr->expr = p+2;		    infoPtr->token = RIGHT_SHIFT;		    break;		case '=':		    infoPtr->expr = p+2;		    infoPtr->token = GEQ;		    break;		default:		    infoPtr->token = GREATER;		    break;	    }	    return TCL_OK;	case '=':	    if (p[1] == '=') {		infoPtr->expr = p+2;		infoPtr->token = EQUAL;	    } else {		infoPtr->token = UNKNOWN;	    }	    return TCL_OK;	case '!':	    if (p[1] == '=') {		infoPtr->expr = p+2;		infoPtr->token = NEQ;	    } else {		infoPtr->token = NOT;	    }	    return TCL_OK;	case '&':	    if (p[1] == '&') {		infoPtr->expr = p+2;		infoPtr->token = AND;	    } else {		infoPtr->token = BIT_AND;	    }	    return TCL_OK;	case '^':	    infoPtr->token = BIT_XOR;	    return TCL_OK;	case '|':	    if (p[1] == '|') {		infoPtr->expr = p+2;		infoPtr->token = OR;	    } else {		infoPtr->token = BIT_OR;	    }	    return TCL_OK;	case '~':	    infoPtr->token = BIT_NOT;	    return TCL_OK;	case 0:	    infoPtr->token = END;	    infoPtr->expr = p;	    return TCL_OK;	default:	    infoPtr->expr = p+1;	    infoPtr->token = UNKNOWN;	    return TCL_OK;    }}/* *---------------------------------------------------------------------- * * ExprGetValue -- * *	Parse a "value" from the remainder of the expression in infoPtr. * * Results: *	Normally TCL_OK is returned.  The value of the expression is *	returned in *valuePtr.  If an error occurred, then interp->result *	contains an error message and TCL_ERROR is returned. *	InfoPtr->token will be left pointing to the token AFTER the *	expression, and infoPtr->expr will point to the character just *	after the terminating token. * * Side effects: *	None. * *---------------------------------------------------------------------- */static intExprGetValue(interp, infoPtr, prec, valuePtr)    Tcl_Interp *interp;			/* Interpreter to use for error					 * reporting. */    register ExprInfo *infoPtr;		/* Describes the state of the parse					 * just before the value (i.e. ExprLex					 * will be called to get first token					 * of value). */    int prec;				/* Treat any un-parenthesized operator					 * with precedence <= this as the end					 * of the expression. */    Value *valuePtr;			/* Where to store the value of the					 * expression.   Caller must have					 * initialized pv field. */{    Interp *iPtr = (Interp *) interp;    Value value2;			/* Second operand for current					 * operator.  */    int operator;			/* Current operator (either unary					 * or binary). */    int badType;			/* Type of offending argument;  used					 * for error messages. */    int gotOp;				/* Non-zero means already lexed the					 * operator (while picking up value					 * for unary operator).  Don't lex					 * again. */    int result;    /*     * There are two phases to this procedure.  First, pick off an initial     * value.  Then, parse (binary operator, value) pairs until done.     */    gotOp = 0;    value2.pv.buffer = value2.pv.next = value2.staticSpace;    value2.pv.end = value2.pv.buffer + STATIC_STRING_SPACE - 1;    value2.pv.expandProc = TclExpandParseValue;    value2.pv.clientData = (ClientData) NULL;    result = ExprLex(interp, infoPtr, valuePtr);    if (result != TCL_OK) {	goto done;    }    if (infoPtr->token == OPEN_PAREN) {	/*	 * Parenthesized sub-expression.	 */	result = ExprGetValue(interp, infoPtr, -1, valuePtr);	if (result != TCL_OK) {	    goto done;	}	if (infoPtr->token != CLOSE_PAREN) {	    Tcl_ResetResult(interp);	    Tcl_AppendResult(interp,		    "unmatched parentheses in expression \"",		    infoPtr->originalExpr, "\"", (char *) NULL);	    result = TCL_ERROR;	    goto done;	}    } else {	if (infoPtr->token == MINUS) {	    infoPtr->token = UNARY_MINUS;	}	if (infoPtr->token >= UNARY_MINUS) {	    /*	     * Process unary operators.	     */	    operator = infoPtr->token;	    result = ExprGetValue(interp, infoPtr, precTable[infoPtr->token],		    valuePtr);	    if (result != TCL_OK) {		goto done;	    }	    switch (operator) {		case UNARY_MINUS:		    if (valuePtr->type == TYPE_INT) {			valuePtr->intValue = -valuePtr->intValue;		    } else if (valuePtr->type == TYPE_DOUBLE){			valuePtr->doubleValue = -valuePtr->doubleValue;		    } else {			badType = valuePtr->type;			goto illegalType;		    } 		    break;		case NOT:		    if (valuePtr->type == TYPE_INT) {			valuePtr->intValue = !valuePtr->intValue;		    } else if (valuePtr->type == TYPE_DOUBLE) {			/*			 * Theoretically, should be able to use			 * "!valuePtr->intValue", but apparently some			 * compilers can't handle it.			 */			if (valuePtr->doubleValue == 0.0) {			    valuePtr->intValue = 1;			} else {			    valuePtr->intValue = 0;			}			valuePtr->type = TYPE_INT;		    } else {			badType = valuePtr->type;			goto illegalType;		    }		    break;		case BIT_NOT:		    if (valuePtr->type == TYPE_INT) {			valuePtr->intValue = ~valuePtr->intValue;		    } else {			badType  = valuePtr->type;			goto illegalType;		    }		    break;	    }	    gotOp = 1;	} else if (infoPtr->token != VALUE) {	    goto syntaxError;	}    }    /*     * Got the first operand.  Now fetch (operator, operand) pairs.     */    if (!gotOp) {	result = ExprLex(interp, infoPtr, &value2);	if (result != TCL_OK) {	    goto done;	}    }    while (1) {	operator = infoPtr->token;	value2.pv.next = value2.pv.buffer;	if ((operator < MULT) || (operator >= UNARY_MINUS)) {	    if ((operator == END) || (operator == CLOSE_PAREN)) {		result = TCL_OK;		goto done;	    } else {		goto syntaxError;	    }	}	if (precTable[operator] <= prec) {	    result = TCL_OK;	    goto done;	}	/*	 * If we're doing an AND or OR and the first operand already	 * determines the result, don't execute anything in the	 * second operand:  just parse.  Same style for ?: pairs.	 */	if ((operator == AND) || (operator == OR) || (operator == QUESTY)) {	    if (valuePtr->type == TYPE_DOUBLE) {		valuePtr->intValue = valuePtr->doubleValue != 0;		valuePtr->type = TYPE_INT;	    } else if (valuePtr->type == TYPE_STRING) {		badType = TYPE_STRING;		goto illegalType;	    }	    if (((operator == AND) && !valuePtr->intValue)		    || ((operator == OR) && valuePtr->intValue)) {		iPtr->noEval++;		result = ExprGetValue(interp, infoPtr, precTable[operator],			&value2);		iPtr->noEval--;	    } else if (operator == QUESTY) {		if (valuePtr->intValue != 0) {		    valuePtr->pv.next = valuePtr->pv.buffer;		    result = ExprGetValue(interp, infoPtr, precTable[operator],			    valuePtr);		    if (result != TCL_OK) {			goto done;		    }		    if (infoPtr->token != COLON) {			goto syntaxError;		    }		    value2.pv.next = value2.pv.buffer;		    iPtr->noEval++;		    result = ExprGetValue(interp, infoPtr, precTable[operator],			    &value2);		    iPtr->noEval--;		} else {		    iPtr->noEval++;		    result = ExprGetValue(interp, infoPtr, precTable[operator],			    &value2);		    iPtr->noEval--;		    if (result != TCL_OK) {			goto done;		    }		    if (infoPtr->token != COLON) {			goto syntaxError;		    }		    valuePtr->pv.next = valuePtr->pv.buffer;		    result = ExprGetValue(interp, infoPtr, precTable[operator],			    valuePtr);		}	    } else {		result = ExprGetValue(interp, infoPtr, precTable[operator],			&value2);	    }	} else {	    result = ExprGetValue(interp, infoPtr, precTable[operator],		    &value2);	}	if (result != TCL_OK) {	    goto done;	}	if ((infoPtr->token < MULT) && (infoPtr->token != VALUE)		&& (infoPtr->token != END)		&& (infoPtr->token != CLOSE_PAREN)) {	    goto syntaxError;	}	/*	 * At this point we've got two values and an operator.  Check	 * to make sure that the particular data types are appropriate	 * for the particular operator, and perform type conversion	 * if necessary.	 */	switch (operator) {	    /*	     * For the operators below, no strings are allowed and	     * ints get converted to floats if necessary.	     */	    case MULT: case DIVIDE: case PLUS: case MINUS:		if ((valuePtr->type == TYPE_STRING)			|| (value2.type == TYPE_STRING)) {		    badType = TYPE_STRING;		    goto illegalType;		}		if (valuePtr->type == TYPE_DOUBLE) {		    if (value2.type == TYPE_INT) {			value2.doubleValue = value2.intValue;			value2.type = TYPE_DOUBLE;		    }		} else if (value2.type == TYPE_DOUBLE) {		    if (valuePtr->type == TYPE_INT) {			valuePtr->doubleValue = valuePtr->intValue;			valuePtr->type = TYPE_DOUBLE;		    }		}		break;	    /*	     * For the operators below, only integers are allowed.	     */	    case MOD: case LEFT_SHIFT: case RIGHT_SHIFT:	    case BIT_AND: case BIT_XOR: case BIT_OR:		 if (valuePtr->type != TYPE_INT) {		     badType = valuePtr->type;		     goto illegalType;		 } else if (value2.type != TYPE_INT) {		     badType = value2.type;		     goto illegalType;		 }		 break;	    /*	     * For the operators below, any type is allowed but the	     * two operands must have the same type.  Convert integers	     * to floats and either to strings, if necessary.	     */	    case LESS: case GREATER: case LEQ: case GEQ:	    case EQUAL: case NEQ:		if (valuePtr->type == TYPE_STRING) {		    if (value2.type != TYPE_STRING) {			ExprMakeString(&value2);		    }		} else if (value2.type == TYPE_STRING) {		    if (valuePtr->type != TYPE_STRING) {			ExprMakeString(valuePtr);		    }		} else if (valuePtr->type == TYPE_DOUBLE) {		    if (value2.type == TYPE_INT) {			value2.doubleValue = value2.intValue;			value2.type = TYPE_DOUBLE;		    }		} else if (value2.type == TYPE_DOUBLE) {		     if (valuePtr->type == TYPE_INT) {			valuePtr->doubleValue = valuePtr->intValue;			valuePtr->type = TYPE_DOUBLE;		    }		}		break;	    /*	     * For the operators below, no strings are allowed, but	     * no int->double conversions are performed.	     */	    case AND: case OR:		if (valuePtr->type == TYPE_STRING) {		    badType = valuePtr->type;		    goto illegalType;		}		if (value2.type == TYPE_STRING) {		    badType = value2.type;		    goto illegalType;		}		break;	    /*	     * For the operators below, type and conversions are	     * irrelevant:  they're handled elsewhere.	     */	    case QUESTY: case COLON:		break;	    /*	     * Any other operator is an error.	     */	    default:		interp->result = "unknown operator in expression";		result = TCL_ERROR;		goto done;	}	/*	 * If necessary, convert one of the operands to the type	 * of the other.  If the operands are incompatible with	 * the operator (e.g. "+" on strings) then return an	 * error.	 */	switch (operator) {

⌨️ 快捷键说明

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