📄 tclexpr.c
字号:
case MULT: if (valuePtr->type == TYPE_INT) { valuePtr->intValue *= value2.intValue; } else { valuePtr->doubleValue *= value2.doubleValue; } break; case DIVIDE: if (valuePtr->type == TYPE_INT) { if (value2.intValue == 0) { divideByZero: interp->result = "divide by zero"; result = TCL_ERROR; goto done; } valuePtr->intValue /= value2.intValue; } else { if (value2.doubleValue == 0.0) { goto divideByZero; } valuePtr->doubleValue /= value2.doubleValue; } break; case MOD: if (value2.intValue == 0) { goto divideByZero; } valuePtr->intValue %= value2.intValue; break; case PLUS: if (valuePtr->type == TYPE_INT) { valuePtr->intValue += value2.intValue; } else { valuePtr->doubleValue += value2.doubleValue; } break; case MINUS: if (valuePtr->type == TYPE_INT) { valuePtr->intValue -= value2.intValue; } else { valuePtr->doubleValue -= value2.doubleValue; } break; case LEFT_SHIFT: valuePtr->intValue <<= value2.intValue; break; case RIGHT_SHIFT: /* * The following code is a bit tricky: it ensures that * right shifts propagate the sign bit even on machines * where ">>" won't do it by default. */ if (valuePtr->intValue < 0) { valuePtr->intValue = ~((~valuePtr->intValue) >> value2.intValue); } else { valuePtr->intValue >>= value2.intValue; } break; case LESS: if (valuePtr->type == TYPE_INT) { valuePtr->intValue = valuePtr->intValue < value2.intValue; } else if (valuePtr->type == TYPE_DOUBLE) { valuePtr->intValue = valuePtr->doubleValue < value2.doubleValue; } else { valuePtr->intValue = strcmp(valuePtr->pv.buffer, value2.pv.buffer) < 0; } valuePtr->type = TYPE_INT; break; case GREATER: if (valuePtr->type == TYPE_INT) { valuePtr->intValue = valuePtr->intValue > value2.intValue; } else if (valuePtr->type == TYPE_DOUBLE) { valuePtr->intValue = valuePtr->doubleValue > value2.doubleValue; } else { valuePtr->intValue = strcmp(valuePtr->pv.buffer, value2.pv.buffer) > 0; } valuePtr->type = TYPE_INT; break; case LEQ: if (valuePtr->type == TYPE_INT) { valuePtr->intValue = valuePtr->intValue <= value2.intValue; } else if (valuePtr->type == TYPE_DOUBLE) { valuePtr->intValue = valuePtr->doubleValue <= value2.doubleValue; } else { valuePtr->intValue = strcmp(valuePtr->pv.buffer, value2.pv.buffer) <= 0; } valuePtr->type = TYPE_INT; break; case GEQ: if (valuePtr->type == TYPE_INT) { valuePtr->intValue = valuePtr->intValue >= value2.intValue; } else if (valuePtr->type == TYPE_DOUBLE) { valuePtr->intValue = valuePtr->doubleValue >= value2.doubleValue; } else { valuePtr->intValue = strcmp(valuePtr->pv.buffer, value2.pv.buffer) >= 0; } valuePtr->type = TYPE_INT; break; case EQUAL: if (valuePtr->type == TYPE_INT) { valuePtr->intValue = valuePtr->intValue == value2.intValue; } else if (valuePtr->type == TYPE_DOUBLE) { valuePtr->intValue = valuePtr->doubleValue == value2.doubleValue; } else { valuePtr->intValue = strcmp(valuePtr->pv.buffer, value2.pv.buffer) == 0; } valuePtr->type = TYPE_INT; break; case NEQ: if (valuePtr->type == TYPE_INT) { valuePtr->intValue = valuePtr->intValue != value2.intValue; } else if (valuePtr->type == TYPE_DOUBLE) { valuePtr->intValue = valuePtr->doubleValue != value2.doubleValue; } else { valuePtr->intValue = strcmp(valuePtr->pv.buffer, value2.pv.buffer) != 0; } valuePtr->type = TYPE_INT; break; case BIT_AND: valuePtr->intValue &= value2.intValue; break; case BIT_XOR: valuePtr->intValue ^= value2.intValue; break; case BIT_OR: valuePtr->intValue |= value2.intValue; break; /* * For AND and OR, we know that the first value has already * been converted to an integer. Thus we need only consider * the possibility of int vs. double for the second value. */ case AND: if (value2.type == TYPE_DOUBLE) { value2.intValue = value2.doubleValue != 0; value2.type = TYPE_INT; } valuePtr->intValue = valuePtr->intValue && value2.intValue; break; case OR: if (value2.type == TYPE_DOUBLE) { value2.intValue = value2.doubleValue != 0; value2.type = TYPE_INT; } valuePtr->intValue = valuePtr->intValue || value2.intValue; break; case COLON: interp->result = "can't have : operator without ? first"; result = TCL_ERROR; goto done; } } done: if (value2.pv.buffer != value2.staticSpace) { ckfree(value2.pv.buffer); } return result; syntaxError: Tcl_ResetResult(interp); Tcl_AppendResult(interp, "syntax error in expression \"", infoPtr->originalExpr, "\"", (char *) NULL); result = TCL_ERROR; goto done; illegalType: Tcl_AppendResult(interp, "can't use ", (badType == TYPE_DOUBLE) ? "floating-point value" : "non-numeric string", " as operand of \"", operatorStrings[operator], "\"", (char *) NULL); result = TCL_ERROR; goto done;}/* *-------------------------------------------------------------- * * ExprMakeString -- * * Convert a value from int or double representation to * a string. * * Results: * The information at *valuePtr gets converted to string * format, if it wasn't that way already. * * Side effects: * None. * *-------------------------------------------------------------- */static voidExprMakeString(valuePtr) register Value *valuePtr; /* Value to be converted. */{ int shortfall; shortfall = 150 - (valuePtr->pv.end - valuePtr->pv.buffer); if (shortfall > 0) { (*valuePtr->pv.expandProc)(&valuePtr->pv, shortfall); } if (valuePtr->type == TYPE_INT) { sprintf(valuePtr->pv.buffer, "%ld", valuePtr->intValue); } else if (valuePtr->type == TYPE_DOUBLE) { sprintf(valuePtr->pv.buffer, "%g", valuePtr->doubleValue); } valuePtr->type = TYPE_STRING;}/* *-------------------------------------------------------------- * * ExprTopLevel -- * * This procedure provides top-level functionality shared by * procedures like Tcl_ExprInt, Tcl_ExprDouble, etc. * * Results: * The result is a standard Tcl return value. If an error * occurs then an error message is left in interp->result. * The value of the expression is returned in *valuePtr, in * whatever form it ends up in (could be string or integer * or double). Caller may need to convert result. Caller * is also responsible for freeing string memory in *valuePtr, * if any was allocated. * * Side effects: * None. * *-------------------------------------------------------------- */static intExprTopLevel(interp, string, valuePtr) Tcl_Interp *interp; /* Context in which to evaluate the * expression. */ char *string; /* Expression to evaluate. */ Value *valuePtr; /* Where to store result. Should * not be initialized by caller. */{ ExprInfo info; int result; info.originalExpr = string; info.expr = string; valuePtr->pv.buffer = valuePtr->pv.next = valuePtr->staticSpace; valuePtr->pv.end = valuePtr->pv.buffer + STATIC_STRING_SPACE - 1; valuePtr->pv.expandProc = TclExpandParseValue; valuePtr->pv.clientData = (ClientData) NULL; result = ExprGetValue(interp, &info, -1, valuePtr); if (result != TCL_OK) { return result; } if (info.token != END) { Tcl_AppendResult(interp, "syntax error in expression \"", string, "\"", (char *) NULL); return TCL_ERROR; } return TCL_OK;}/* *-------------------------------------------------------------- * * Tcl_ExprLong, Tcl_ExprDouble, Tcl_ExprBoolean -- * * Procedures to evaluate an expression and return its value * in a particular form. * * Results: * Each of the procedures below returns a standard Tcl result. * If an error occurs then an error message is left in * interp->result. Otherwise the value of the expression, * in the appropriate form, is stored at *resultPtr. If * the expression had a result that was incompatible with the * desired form then an error is returned. * * Side effects: * None. * *-------------------------------------------------------------- */intTcl_ExprLong(interp, string, ptr) Tcl_Interp *interp; /* Context in which to evaluate the * expression. */ char *string; /* Expression to evaluate. */ long *ptr; /* Where to store result. */{ Value value; int result; result = ExprTopLevel(interp, string, &value); if (result == TCL_OK) { if (value.type == TYPE_INT) { *ptr = value.intValue; } else if (value.type == TYPE_DOUBLE) { *ptr = value.doubleValue; } else { interp->result = "expression didn't have numeric value"; result = TCL_ERROR; } } if (value.pv.buffer != value.staticSpace) { ckfree(value.pv.buffer); } return result;}intTcl_ExprDouble(interp, string, ptr) Tcl_Interp *interp; /* Context in which to evaluate the * expression. */ char *string; /* Expression to evaluate. */ double *ptr; /* Where to store result. */{ Value value; int result; result = ExprTopLevel(interp, string, &value); if (result == TCL_OK) { if (value.type == TYPE_INT) { *ptr = value.intValue; } else if (value.type == TYPE_DOUBLE) { *ptr = value.doubleValue; } else { interp->result = "expression didn't have numeric value"; result = TCL_ERROR; } } if (value.pv.buffer != value.staticSpace) { ckfree(value.pv.buffer); } return result;}intTcl_ExprBoolean(interp, string, ptr) Tcl_Interp *interp; /* Context in which to evaluate the * expression. */ char *string; /* Expression to evaluate. */ int *ptr; /* Where to store 0/1 result. */{ Value value; int result; result = ExprTopLevel(interp, string, &value); if (result == TCL_OK) { if (value.type == TYPE_INT) { *ptr = value.intValue != 0; } else if (value.type == TYPE_DOUBLE) { *ptr = value.doubleValue != 0.0; } else { interp->result = "expression didn't have numeric value"; result = TCL_ERROR; } } if (value.pv.buffer != value.staticSpace) { ckfree(value.pv.buffer); } return result;}/* *-------------------------------------------------------------- * * Tcl_ExprString -- * * Evaluate an expression and return its value in string form. * * Results: * A standard Tcl result. If the result is TCL_OK, then the * interpreter's result is set to the string value of the * expression. If the result is TCL_OK, then interp->result * contains an error message. * * Side effects: * None. * *-------------------------------------------------------------- */intTcl_ExprString(interp, string) Tcl_Interp *interp; /* Context in which to evaluate the * expression. */ char *string; /* Expression to evaluate. */{ Value value; int result; result = ExprTopLevel(interp, string, &value); if (result == TCL_OK) { if (value.type == TYPE_INT) { sprintf(interp->result, "%ld", value.intValue); } else if (value.type == TYPE_DOUBLE) { sprintf(interp->result, "%g", value.doubleValue); } else { if (value.pv.buffer != value.staticSpace) { interp->result = value.pv.buffer; interp->freeProc = (Tcl_FreeProc *) free; value.pv.buffer = value.staticSpace; } else { Tcl_SetResult(interp, value.pv.buffer, TCL_VOLATILE); } } } if (value.pv.buffer != value.staticSpace) { ckfree(value.pv.buffer); } return result;}#elsestatic const char file_name[] = "tclExpr.c";#endif /* EXCLUDE_TCL */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -