summaryrefslogtreecommitdiffstats
path: root/generic/tclBasic.c
diff options
context:
space:
mode:
authornijtmans <nijtmans>2010-02-21 20:09:37 (GMT)
committernijtmans <nijtmans>2010-02-21 20:09:37 (GMT)
commitc0efda860028550fa1392602cb9d479a67c7cf55 (patch)
tree107091c0a01f164224f02d295ebb0a866b39c5d4 /generic/tclBasic.c
parent3fb3008b2698db7d2a9f46adeac8c91565ba890b (diff)
downloadtcl-c0efda860028550fa1392602cb9d479a67c7cf55.zip
tcl-c0efda860028550fa1392602cb9d479a67c7cf55.tar.gz
tcl-c0efda860028550fa1392602cb9d479a67c7cf55.tar.bz2
Follow-up to Fix [Bug 2954959] expr abs(0.0) is -0.0
Some more tests, showing that the LONG implementation was not quite correct too, and a fix for that. Some more internal "const" additions
Diffstat (limited to 'generic/tclBasic.c')
-rw-r--r--generic/tclBasic.c53
1 files changed, 34 insertions, 19 deletions
diff --git a/generic/tclBasic.c b/generic/tclBasic.c
index 527ed81..4001407 100644
--- a/generic/tclBasic.c
+++ b/generic/tclBasic.c
@@ -16,7 +16,7 @@
* See the file "license.terms" for information on usage and redistribution of
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tclBasic.c,v 1.445 2010/02/21 08:56:19 nijtmans Exp $
+ * RCS: @(#) $Id: tclBasic.c,v 1.446 2010/02/21 20:09:38 nijtmans Exp $
*/
#include "tclInt.h"
@@ -7419,15 +7419,25 @@ ExprAbsFunc(
if (type == TCL_NUMBER_LONG) {
long l = *((const long *) ptr);
- if (l <= (long)0) {
- if (l == LONG_MIN) {
- TclBNInitBignumFromLong(&big, l);
- goto tooLarge;
+ if (l > (long)0) {
+ goto unChanged;
+ } else if (l == (long)0) {
+ const char *string = objv[1]->bytes;
+ if (!string) {
+ /* There is no string representation, so internal one is correct */
+ goto unChanged;
}
- Tcl_SetObjResult(interp, Tcl_NewLongObj(-l));
- } else {
- Tcl_SetObjResult(interp, objv[1]);
+ while (isspace(UCHAR(*string))) {
+ ++string;
+ }
+ if (*string != '-') {
+ goto unChanged;
+ }
+ } else if (l == LONG_MIN) {
+ TclBNInitBignumFromLong(&big, l);
+ goto tooLarge;
}
+ Tcl_SetObjResult(interp, Tcl_NewLongObj(-l));
return TCL_OK;
}
@@ -7438,11 +7448,16 @@ ExprAbsFunc(
/* We need to distinguish here between positive 0.0 and
* negative -0.0, see Bug ID #2954959.
*/
- if ((d <= -0.0) && memcmp(&d, &poszero, sizeof(double))) {
- Tcl_SetObjResult(interp, Tcl_NewDoubleObj(-d));
+ if (d == -0.0) {
+ if (!memcmp(&d, &poszero, sizeof(double))) {
+ goto unChanged;
+ }
} else {
- Tcl_SetObjResult(interp, objv[1]);
+ if (d > -0.0) {
+ goto unChanged;
+ }
}
+ Tcl_SetObjResult(interp, Tcl_NewDoubleObj(-d));
return TCL_OK;
}
@@ -7450,15 +7465,14 @@ ExprAbsFunc(
if (type == TCL_NUMBER_WIDE) {
Tcl_WideInt w = *((const Tcl_WideInt *) ptr);
- if (w < (Tcl_WideInt)0) {
- if (w == LLONG_MIN) {
- TclBNInitBignumFromWideInt(&big, w);
- goto tooLarge;
- }
- Tcl_SetObjResult(interp, Tcl_NewWideIntObj(-w));
- } else {
- Tcl_SetObjResult(interp, objv[1]);
+ if (w >= (Tcl_WideInt)0) {
+ goto unChanged;
+ }
+ if (w == LLONG_MIN) {
+ TclBNInitBignumFromWideInt(&big, w);
+ goto tooLarge;
}
+ Tcl_SetObjResult(interp, Tcl_NewWideIntObj(-w));
return TCL_OK;
}
#endif
@@ -7471,6 +7485,7 @@ ExprAbsFunc(
mp_neg(&big, &big);
Tcl_SetObjResult(interp, Tcl_NewBignumObj(&big));
} else {
+ unChanged:
Tcl_SetObjResult(interp, objv[1]);
}
return TCL_OK;