summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjan.nijtmans <nijtmans@users.sourceforge.net>2022-11-21 23:54:42 (GMT)
committerjan.nijtmans <nijtmans@users.sourceforge.net>2022-11-21 23:54:42 (GMT)
commitef78b1558f3f0feb6b934f68dba8c84d402511db (patch)
treecefc2509704bf47aa223bf56d01d2bb3a4a719cf
parent948fd24ddb34fc06ec3c6a8bc76133b5f1daafd6 (diff)
parentc1e4942181ef1b8b60b89bfe5983b410080cd477 (diff)
downloadtcl-ef78b1558f3f0feb6b934f68dba8c84d402511db.zip
tcl-ef78b1558f3f0feb6b934f68dba8c84d402511db.tar.gz
tcl-ef78b1558f3f0feb6b934f68dba8c84d402511db.tar.bz2
Merge 8.7
-rw-r--r--doc/IntObj.37
-rw-r--r--doc/LinkVar.33
-rw-r--r--generic/tcl.decls10
-rw-r--r--generic/tclDecls.h9
-rw-r--r--generic/tclLink.c54
-rw-r--r--generic/tclObj.c84
-rw-r--r--generic/tclStubInit.c2
-rw-r--r--tests/unixInit.test2
8 files changed, 110 insertions, 61 deletions
diff --git a/doc/IntObj.3 b/doc/IntObj.3
index 703f2ce..d2954c8 100644
--- a/doc/IntObj.3
+++ b/doc/IntObj.3
@@ -8,7 +8,7 @@
.so man.macros
.BS
.SH NAME
-Tcl_NewIntObj, Tcl_NewLongObj, Tcl_NewWideIntObj, Tcl_SetIntObj, Tcl_SetLongObj, Tcl_SetWideIntObj, Tcl_GetIntFromObj, Tcl_GetIntForIndex, Tcl_GetLongFromObj, Tcl_GetWideIntFromObj, Tcl_NewBignumObj, Tcl_SetBignumObj, Tcl_GetBignumFromObj, Tcl_TakeBignumFromObj \- manipulate Tcl values as integers
+Tcl_NewIntObj, Tcl_NewLongObj, Tcl_NewWideIntObj, Tcl_SetIntObj, Tcl_SetLongObj, Tcl_SetWideIntObj, Tcl_GetIntFromObj, Tcl_GetIntForIndex, Tcl_GetLongFromObj, Tcl_GetWideIntFromObj, Tcl_GetWideUIntFromObj, Tcl_NewBignumObj, Tcl_SetBignumObj, Tcl_GetBignumFromObj, Tcl_TakeBignumFromObj \- manipulate Tcl values as integers
.SH SYNOPSIS
.nf
\fB#include <tcl.h>\fR
@@ -40,6 +40,9 @@ int
int
\fBTcl_GetWideIntFromObj\fR(\fIinterp, objPtr, widePtr\fR)
.sp
+int
+\fBTcl_GetWideUIntFromObj\fR(\fIinterp, objPtr, uwidePtr\fR)
+.sp
.sp
\fB#include <tclTomMath.h>\fR
.sp
@@ -84,6 +87,8 @@ Points to place to store the long integer value retrieved from \fIobjPtr\fR.
Points to place to store the size_t value retrieved from \fIobjPtr\fR.
.AP Tcl_WideInt *widePtr out
Points to place to store the wide integer value retrieved from \fIobjPtr\fR.
+.AP Tcl_WideUInt *uwidePtr out
+Points to place to store the unsigned wide integer value retrieved from \fIobjPtr\fR.
.AP mp_int *bigValue in/out
Points to a multi-precision integer structure declared by the LibTomMath
library.
diff --git a/doc/LinkVar.3 b/doc/LinkVar.3
index db5a90b..f7ce3a3 100644
--- a/doc/LinkVar.3
+++ b/doc/LinkVar.3
@@ -239,8 +239,7 @@ The C variable, or each element of the C array, is of type \fBTcl_WideUInt\fR
(which is an unsigned integer type at least 64-bits wide on all platforms that
can support it.)
Any value written into the Tcl variable must have a proper unsigned
-wideinteger form acceptable to \fBTcl_GetBignumFromObj\fR and in the
-platform's defined range for the \fBTcl_WideUInt\fR type;
+wideinteger form acceptable to \fBTcl_GetWideUIntFromObj\fR;
attempts to write non-integer values into \fIvarName\fR will be
rejected with Tcl errors. Incomplete integer representations (like
the empty string, '+', '-' or the hex/octal/decimal/binary prefix) are accepted
diff --git a/generic/tcl.decls b/generic/tcl.decls
index 8e77e49..d07b269 100644
--- a/generic/tcl.decls
+++ b/generic/tcl.decls
@@ -2619,11 +2619,11 @@ declare 683 {
# void Tcl_SetWideUIntObj(Tcl_Obj *objPtr, Tcl_WideUInt uwideValue)
#}
-# TIP #650 (reserved)
-#declare 686 {
-# int Tcl_GetWideUIntFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr,
-# Tcl_WideUInt *uwidePtr)
-#}
+# TIP #650
+declare 686 {
+ int Tcl_GetWideUIntFromObj(Tcl_Interp *interp, Tcl_Obj *objPtr,
+ Tcl_WideUInt *uwidePtr)
+}
# TIP 651
declare 687 {
diff --git a/generic/tclDecls.h b/generic/tclDecls.h
index faada2a..0bbf665 100644
--- a/generic/tclDecls.h
+++ b/generic/tclDecls.h
@@ -1854,7 +1854,9 @@ EXTERN int Tcl_RemoveChannelMode(Tcl_Interp *interp,
EXTERN int Tcl_GetEncodingNulLength(Tcl_Encoding encoding);
/* Slot 684 is reserved */
/* Slot 685 is reserved */
-/* Slot 686 is reserved */
+/* 686 */
+EXTERN int Tcl_GetWideUIntFromObj(Tcl_Interp *interp,
+ Tcl_Obj *objPtr, Tcl_WideUInt *uwidePtr);
/* 687 */
EXTERN Tcl_Obj * Tcl_DStringToObj(Tcl_DString *dsPtr);
@@ -2554,7 +2556,7 @@ typedef struct TclStubs {
int (*tcl_GetEncodingNulLength) (Tcl_Encoding encoding); /* 683 */
void (*reserved684)(void);
void (*reserved685)(void);
- void (*reserved686)(void);
+ int (*tcl_GetWideUIntFromObj) (Tcl_Interp *interp, Tcl_Obj *objPtr, Tcl_WideUInt *uwidePtr); /* 686 */
Tcl_Obj * (*tcl_DStringToObj) (Tcl_DString *dsPtr); /* 687 */
} TclStubs;
@@ -3878,7 +3880,8 @@ extern const TclStubs *tclStubsPtr;
(tclStubsPtr->tcl_GetEncodingNulLength) /* 683 */
/* Slot 684 is reserved */
/* Slot 685 is reserved */
-/* Slot 686 is reserved */
+#define Tcl_GetWideUIntFromObj \
+ (tclStubsPtr->tcl_GetWideUIntFromObj) /* 686 */
#define Tcl_DStringToObj \
(tclStubsPtr->tcl_DStringToObj) /* 687 */
diff --git a/generic/tclLink.c b/generic/tclLink.c
index 4df2a33..a0212ee 100644
--- a/generic/tclLink.c
+++ b/generic/tclLink.c
@@ -527,56 +527,14 @@ GetUWide(
Tcl_Obj *objPtr,
Tcl_WideUInt *uwidePtr)
{
- Tcl_WideInt *widePtr = (Tcl_WideInt *) uwidePtr;
- void *clientData;
- int type, intValue;
-
- if (Tcl_GetNumberFromObj(NULL, objPtr, &clientData, &type) == TCL_OK) {
- if (type == TCL_NUMBER_INT) {
- *widePtr = *((const Tcl_WideInt *) clientData);
- return (*widePtr < 0);
- } else if (type == TCL_NUMBER_BIG) {
- mp_int *numPtr = (mp_int *)clientData;
- Tcl_WideUInt value = 0;
- union {
- Tcl_WideUInt value;
- unsigned char bytes[sizeof(Tcl_WideUInt)];
- } scratch;
- size_t numBytes;
- unsigned char *bytes = scratch.bytes;
-
- if (numPtr->sign || (MP_OKAY != mp_to_ubin(numPtr,
- bytes, sizeof(Tcl_WideUInt), &numBytes))) {
- /*
- * If the sign bit is set (a negative value) or if the value
- * can't possibly fit in the bits of an unsigned wide, there's
- * no point in doing further conversion.
- */
- return 1;
- }
-#ifndef WORDS_BIGENDIAN
- while (numBytes-- > 0) {
- value = (value << CHAR_BIT) | *bytes++;
- }
-#else /* WORDS_BIGENDIAN */
- /*
- * Big-endian can read the value directly.
- */
- value = scratch.value;
-#endif /* WORDS_BIGENDIAN */
- *uwidePtr = value;
- return 0;
- }
- }
-
- /*
- * Evil edge case fallback.
- */
+ if (Tcl_GetWideUIntFromObj(NULL, objPtr, uwidePtr) != TCL_OK) {
+ int intValue;
- if (GetInvalidIntFromObj(objPtr, &intValue) != TCL_OK) {
- return 1;
+ if (GetInvalidIntFromObj(objPtr, &intValue) != TCL_OK) {
+ return 1;
+ }
+ *uwidePtr = intValue;
}
- *uwidePtr = intValue;
return 0;
}
diff --git a/generic/tclObj.c b/generic/tclObj.c
index df2ed6d..76f1627 100644
--- a/generic/tclObj.c
+++ b/generic/tclObj.c
@@ -2960,6 +2960,90 @@ Tcl_GetWideIntFromObj(
/*
*----------------------------------------------------------------------
*
+ * Tcl_GetWideUIntFromObj --
+ *
+ * Attempt to return a unsigned wide integer from the Tcl object "objPtr". If the
+ * object is not already a wide int object or a bignum object, an attempt will
+ * be made to convert it to one.
+ *
+ * Results:
+ * The return value is a standard Tcl object result. If an error occurs
+ * during conversion, an error message is left in the interpreter's
+ * result unless "interp" is NULL.
+ *
+ * Side effects:
+ * If the object is not already an int object, the conversion will free
+ * any old internal representation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+int
+Tcl_GetWideUIntFromObj(
+ Tcl_Interp *interp, /* Used for error reporting if not NULL. */
+ Tcl_Obj *objPtr, /* Object from which to get a wide int. */
+ Tcl_WideUInt *wideUIntPtr)
+ /* Place to store resulting long. */
+{
+ do {
+ if (objPtr->typePtr == &tclIntType) {
+ if (objPtr->internalRep.wideValue < 0) {
+ wideUIntOutOfRange:
+ if (interp != NULL) {
+ Tcl_SetObjResult(interp, Tcl_ObjPrintf(
+ "expected unsigned integer but got \"%s\"",
+ TclGetString(objPtr)));
+ Tcl_SetErrorCode(interp, "TCL", "VALUE", "INTEGER", NULL);
+ }
+ return TCL_ERROR;
+ }
+ *wideUIntPtr = (Tcl_WideUInt)objPtr->internalRep.wideValue;
+ return TCL_OK;
+ }
+ if (objPtr->typePtr == &tclDoubleType) {
+ goto wideUIntOutOfRange;
+ }
+ if (objPtr->typePtr == &tclBignumType) {
+ /*
+ * Must check for those bignum values that can fit in a
+ * Tcl_WideUInt, even when auto-narrowing is enabled.
+ */
+
+ mp_int big;
+ Tcl_WideUInt value = 0;
+ size_t numBytes;
+ Tcl_WideUInt scratch;
+ unsigned char *bytes = (unsigned char *) &scratch;
+
+ TclUnpackBignum(objPtr, big);
+ if (big.sign == MP_NEG) {
+ goto wideUIntOutOfRange;
+ }
+ if (mp_to_ubin(&big, bytes, sizeof(Tcl_WideUInt), &numBytes) == MP_OKAY) {
+ while (numBytes-- > 0) {
+ value = (value << CHAR_BIT) | *bytes++;
+ }
+ *wideUIntPtr = (Tcl_WideUInt)value;
+ return TCL_OK;
+ }
+
+ if (interp != NULL) {
+ const char *s = "integer value too large to represent";
+ Tcl_Obj *msg = Tcl_NewStringObj(s, -1);
+
+ Tcl_SetObjResult(interp, msg);
+ Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW", s, NULL);
+ }
+ return TCL_ERROR;
+ }
+ } while (TclParseNumber(interp, objPtr, "integer", NULL, -1, NULL,
+ TCL_PARSE_INTEGER_ONLY)==TCL_OK);
+ return TCL_ERROR;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
* TclGetWideBitsFromObj --
*
* Attempt to return a wide integer from the Tcl object "objPtr". If the
diff --git a/generic/tclStubInit.c b/generic/tclStubInit.c
index 623407b..8481998 100644
--- a/generic/tclStubInit.c
+++ b/generic/tclStubInit.c
@@ -1491,7 +1491,7 @@ const TclStubs tclStubs = {
Tcl_GetEncodingNulLength, /* 683 */
0, /* 684 */
0, /* 685 */
- 0, /* 686 */
+ Tcl_GetWideUIntFromObj, /* 686 */
Tcl_DStringToObj, /* 687 */
};
diff --git a/tests/unixInit.test b/tests/unixInit.test
index 69c3eac..8e64c7a 100644
--- a/tests/unixInit.test
+++ b/tests/unixInit.test
@@ -348,7 +348,7 @@ test unixInit-3.2 {TclpSetInitialEncodings} -setup {
catch {set oldlc_all $env(LC_ALL)}
catch {set oldtcl_library $env(TCL_LIBRARY)}
unset -nocomplain env(TCL_LIBRARY)
-} -constraints {unix stdio} -body {
+} -constraints {unix stdio knownBug} -body {
set env(LANG) japanese
set env(LC_ALL) japanese
set f [open "|[list [interpreter]]" w+]