summaryrefslogtreecommitdiffstats
path: root/generic/tclExecute.c
diff options
context:
space:
mode:
authormdejong <mdejong>2005-06-29 03:28:56 (GMT)
committermdejong <mdejong>2005-06-29 03:28:56 (GMT)
commit74e4d540d750139af207b77b2f32347ec287b2c9 (patch)
treecf0a37d4826a647109c653b9a68ab5d930e8e0b1 /generic/tclExecute.c
parent1e5b3a5233998d25d4ba019c04551d95f3100d7b (diff)
downloadtcl-74e4d540d750139af207b77b2f32347ec287b2c9.zip
tcl-74e4d540d750139af207b77b2f32347ec287b2c9.tar.gz
tcl-74e4d540d750139af207b77b2f32347ec287b2c9.tar.bz2
* generic/tclExecute.c (TclExecuteByteCode):
When parsing an integer operand for a unary minus expression operator, check for a wide integer that is actually LONG_MIN. If found, convert it back to a long int type. * tests/expr.test: Add constraint for 32bit long int type and 64bit wide int type. Add tests that parse the smallest/largest long int and wide int values.
Diffstat (limited to 'generic/tclExecute.c')
-rw-r--r--generic/tclExecute.c34
1 files changed, 29 insertions, 5 deletions
diff --git a/generic/tclExecute.c b/generic/tclExecute.c
index ad06d99..06456d3 100644
--- a/generic/tclExecute.c
+++ b/generic/tclExecute.c
@@ -11,7 +11,7 @@
* 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.192 2005/06/20 23:10:24 dkf Exp $
+ * RCS: @(#) $Id: tclExecute.c,v 1.193 2005/06/29 03:29:00 mdejong Exp $
*/
#include "tclInt.h"
@@ -4224,10 +4224,11 @@ TclExecuteByteCode(interp, codePtr)
double d;
int boolvar;
long i;
+ int negate_value = 1;
Tcl_WideInt w;
Tcl_ObjType *tPtr;
Tcl_Obj *valuePtr;
-
+
valuePtr = *tosPtr;
tPtr = valuePtr->typePtr;
if (IS_INTEGER_TYPE(tPtr)
@@ -4247,6 +4248,23 @@ TclExecuteByteCode(interp, codePtr)
char *s = Tcl_GetStringFromObj(valuePtr, &length);
if (TclLooksLikeInt(s, length)) {
GET_WIDE_OR_INT(result, valuePtr, i, w);
+
+ /*
+ * An integer was parsed. If parsing a literal that
+ * is the smallest long value, then it would have
+ * been promoted to a wide since it would not fit in
+ * a long type without the leading '-'. Convert
+ * back to the smallest possible long.
+ */
+
+ if ((result == TCL_OK) &&
+ (*pc == INST_UMINUS) &&
+ (valuePtr->typePtr == &tclWideIntType) &&
+ (w == -Tcl_LongAsWide(LONG_MIN))) {
+ valuePtr->typePtr = &tclIntType;
+ valuePtr->internalRep.longValue = LONG_MIN;
+ negate_value = 0;
+ }
} else {
result = Tcl_GetDoubleFromObj(NULL, valuePtr, &d);
}
@@ -4270,11 +4288,14 @@ TclExecuteByteCode(interp, codePtr)
*/
if (tPtr == &tclIntType) {
i = valuePtr->internalRep.longValue;
- TclNewLongObj(objResultPtr, -i);
+ if (negate_value) {
+ i = -i;
+ }
+ TclNewLongObj(objResultPtr, i);
TRACE_WITH_OBJ(("%ld => ", i), objResultPtr);
} else if (tPtr == &tclWideIntType) {
TclGetWide(w,valuePtr);
- TclNewWideIntObj(objResultPtr, -w);
+ TclNewWideIntObj(objResultPtr, -w);
TRACE_WITH_OBJ((LLD" => ", w), objResultPtr);
} else {
d = valuePtr->internalRep.doubleValue;
@@ -4288,7 +4309,10 @@ TclExecuteByteCode(interp, codePtr)
*/
if (tPtr == &tclIntType) {
i = valuePtr->internalRep.longValue;
- TclSetLongObj(valuePtr, -i);
+ if (negate_value) {
+ i = -i;
+ }
+ TclSetLongObj(valuePtr, i);
TRACE_WITH_OBJ(("%ld => ", i), valuePtr);
} else if (tPtr == &tclWideIntType) {
TclGetWide(w,valuePtr);