diff options
author | nijtmans <nijtmans> | 2010-02-21 20:09:37 (GMT) |
---|---|---|
committer | nijtmans <nijtmans> | 2010-02-21 20:09:37 (GMT) |
commit | c0efda860028550fa1392602cb9d479a67c7cf55 (patch) | |
tree | 107091c0a01f164224f02d295ebb0a866b39c5d4 /generic/tclBasic.c | |
parent | 3fb3008b2698db7d2a9f46adeac8c91565ba890b (diff) | |
download | tcl-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.c | 53 |
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; |