summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordgp <dgp@users.sourceforge.net>2005-04-21 15:23:00 (GMT)
committerdgp <dgp@users.sourceforge.net>2005-04-21 15:23:00 (GMT)
commitbcb74eb9c3f377874729c7a81aee5568afd2f0bb (patch)
tree40530074e93fe7b57008a72d8d4e4cad207c8307
parenta87519a28334dacc716da9f583c54ddf3a804131 (diff)
downloadtcl-bcb74eb9c3f377874729c7a81aee5568afd2f0bb.zip
tcl-bcb74eb9c3f377874729c7a81aee5568afd2f0bb.tar.gz
tcl-bcb74eb9c3f377874729c7a81aee5568afd2f0bb.tar.bz2
* generic/tclObj.c: Re-ordered error detection code so all values
with trailing garbage receive a "not an integer" message instead of an "integer too large" message. Removed inactive code meant to deal with strtoul* routines that fail to parse leading signs. All of them do, and if any are detected that do not, the correct fix is replacement with compat/strtoul*.c, not a lot of special care by the callers.
-rw-r--r--ChangeLog8
-rw-r--r--generic/tclObj.c93
2 files changed, 47 insertions, 54 deletions
diff --git a/ChangeLog b/ChangeLog
index a88a761..5de769c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -6,6 +6,14 @@
Tcl_GetFoo() routines into wrappers around Tcl_GetFooFromObj().
Reduces code duplication, and the resulting potential for inconsistency.
+ * generic/tclObj.c: Re-ordered error detection code so all values
+ with trailing garbage receive a "not an integer" message instead of
+ an "integer too large" message.
+ Removed inactive code meant to deal with strtoul* routines that fail
+ to parse leading signs. All of them do, and if any are detected
+ that do not, the correct fix is replacement with compat/strtoul*.c,
+ not a lot of special care by the callers.
+
2005-04-20 Don Porter <dgp@users.sourceforge.net>
* generic/tclGet.c (Tcl_GetInt): Corrected error that did not
diff --git a/generic/tclObj.c b/generic/tclObj.c
index aa30598..625e70a 100644
--- a/generic/tclObj.c
+++ b/generic/tclObj.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: tclObj.c,v 1.76 2005/04/20 16:04:20 dgp Exp $
+ * RCS: @(#) $Id: tclObj.c,v 1.77 2005/04/21 15:23:10 dgp Exp $
*/
#include "tclInt.h"
@@ -1774,12 +1774,6 @@ SetDoubleFromAny(interp, objPtr)
}
return TCL_ERROR;
}
- if (errno != 0) {
- if (interp != NULL) {
- TclExprFloatError(interp, newDouble);
- }
- return TCL_ERROR;
- }
/*
* Make sure that the string has no garbage after the end of the double.
@@ -1793,6 +1787,13 @@ SetDoubleFromAny(interp, objPtr)
goto badDouble;
}
+ if (errno != 0) {
+ if (interp != NULL) {
+ TclExprFloatError(interp, newDouble);
+ }
+ return TCL_ERROR;
+ }
+
/*
* The conversion to double succeeded. Free the old internalRep before
* setting the new one. We do this as late as possible to allow the
@@ -2064,7 +2065,6 @@ SetIntOrWideFromAny(interp, objPtr)
register char *p;
unsigned long newLong;
int isNegative = 0;
- int isWide = 0;
/*
* Get the string representation. Make it up-to-date if necessary.
@@ -2076,8 +2076,9 @@ SetIntOrWideFromAny(interp, objPtr)
* Now parse "objPtr"s string as an int. We use an implementation here
* that doesn't report errors in interp if interp is NULL. Note: use
* strtoul instead of strtol for integer conversions to allow full-size
- * unsigned numbers, but don't depend on strtoul to handle sign
- * characters; it won't in some implementations.
+ * unsigned numbers. We parse the leading space and sign ourselves so
+ * we can tell the difference between apparently positive and negative
+ * values.
*/
errno = 0;
@@ -2106,14 +2107,6 @@ SetIntOrWideFromAny(interp, objPtr)
if (end == p) {
goto badInteger;
}
- if (errno == ERANGE) {
- if (interp != NULL) {
- CONST char *s = "integer value too large to represent";
- Tcl_SetObjResult(interp, Tcl_NewStringObj(s, -1));
- Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW", s, (char *) NULL);
- }
- return TCL_ERROR;
- }
/*
* Make sure that the string has no garbage after the end of the int.
@@ -2127,17 +2120,14 @@ SetIntOrWideFromAny(interp, objPtr)
goto badInteger;
}
- /*
- * If the resulting integer will exceed the range of a long,
- * put it into a wide instead. (Tcl Bug #868489)
- */
-
-#ifndef TCL_WIDE_INT_IS_LONG
- if ((isNegative && newLong > (unsigned long) (LONG_MAX) + 1)
- || (!isNegative && newLong > LONG_MAX)) {
- isWide = 1;
+ if (errno == ERANGE) {
+ if (interp != NULL) {
+ CONST char *s = "integer value too large to represent";
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(s, -1));
+ Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW", s, (char *) NULL);
+ }
+ return TCL_ERROR;
}
-#endif
/*
* The conversion to int succeeded. Free the old internalRep before
@@ -2147,11 +2137,20 @@ SetIntOrWideFromAny(interp, objPtr)
*/
TclFreeIntRep(objPtr);
- if (isWide) {
+#ifndef TCL_WIDE_INT_IS_LONG
+ /*
+ * If the resulting integer will exceed the range of a long,
+ * put it into a wide instead. (Tcl Bug #868489)
+ */
+
+ if ((isNegative && newLong > (unsigned long) (LONG_MAX) + 1)
+ || (!isNegative && newLong > LONG_MAX)) {
objPtr->internalRep.wideValue =
(isNegative ? -(Tcl_WideInt)newLong : (Tcl_WideInt)newLong);
objPtr->typePtr = &tclWideIntType;
- } else {
+ } else
+#endif
+ {
objPtr->internalRep.longValue =
(isNegative ? -(long)newLong : (long)newLong);
objPtr->typePtr = &tclIntType;
@@ -2454,25 +2453,11 @@ SetWideIntFromAny(interp, objPtr)
* Now parse "objPtr"s string as an int. We use an implementation here
* that doesn't report errors in interp if interp is NULL. Note: use
* strtoull instead of strtoll for integer conversions to allow full-size
- * unsigned numbers, but don't depend on strtoull to handle sign
- * characters; it won't in some implementations.
+ * unsigned numbers.
*/
errno = 0;
-#ifdef TCL_STRTOUL_SIGN_CHECK
- for (; isspace(UCHAR(*p)) ; p++) { /* INTL: ISO space. */
- /* Empty loop body. */
- }
- if (*p == '-') {
- p++;
- newWide = -((Tcl_WideInt)strtoull(p, &end, 0));
- } else if (*p == '+') {
- p++;
- newWide = strtoull(p, &end, 0);
- } else
-#else
- newWide = strtoull(p, &end, 0);
-#endif
+ newWide = strtoull(p, &end, 0);
if (end == p) {
badInteger:
if (interp != NULL) {
@@ -2485,14 +2470,6 @@ SetWideIntFromAny(interp, objPtr)
}
return TCL_ERROR;
}
- if (errno == ERANGE) {
- if (interp != NULL) {
- CONST char *s = "integer value too large to represent";
- Tcl_SetObjResult(interp, Tcl_NewStringObj(s, -1));
- Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW", s, (char *) NULL);
- }
- return TCL_ERROR;
- }
/*
* Make sure that the string has no garbage after the end of the int.
@@ -2506,6 +2483,14 @@ SetWideIntFromAny(interp, objPtr)
goto badInteger;
}
+ if (errno == ERANGE) {
+ if (interp != NULL) {
+ CONST char *s = "integer value too large to represent";
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(s, -1));
+ Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW", s, (char *) NULL);
+ }
+ return TCL_ERROR;
+ }
/*
* The conversion to int succeeded. Free the old internalRep before
* setting the new one. We do this as late as possible to allow the