summaryrefslogtreecommitdiffstats
path: root/generic/tclObj.c
diff options
context:
space:
mode:
Diffstat (limited to 'generic/tclObj.c')
-rw-r--r--generic/tclObj.c2482
1 files changed, 959 insertions, 1523 deletions
diff --git a/generic/tclObj.c b/generic/tclObj.c
index f321399..230842a 100644
--- a/generic/tclObj.c
+++ b/generic/tclObj.c
@@ -4,20 +4,20 @@
* This file contains Tcl object-related functions that are used by many
* Tcl commands.
*
- * Copyright © 1995-1997 Sun Microsystems, Inc.
- * Copyright © 1999 Scriptics Corporation.
- * Copyright © 2001 ActiveState Corporation.
- * Copyright © 2005 Kevin B. Kenny. All rights reserved.
- * Copyright © 2007 Daniel A. Steffen <das@users.sourceforge.net>
+ * Copyright (c) 1995-1997 Sun Microsystems, Inc.
+ * Copyright (c) 1999 by Scriptics Corporation.
+ * Copyright (c) 2001 by ActiveState Corporation.
+ * Copyright (c) 2005 by Kevin B. Kenny. All rights reserved.
+ * Copyright (c) 2007 Daniel A. Steffen <das@users.sourceforge.net>
*
* See the file "license.terms" for information on usage and redistribution of
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
*/
#include "tclInt.h"
-#include "tclTomMath.h"
+#include "tommath.h"
+#include <float.h>
#include <math.h>
-#include <assert.h>
/*
* Table of all object types.
@@ -38,7 +38,7 @@ Tcl_Obj *tclFreeObjList = NULL;
* TclNewObj macro, however, so must be visible.
*/
-#if TCL_THREADS
+#ifdef TCL_THREADS
MODULE_SCOPE Tcl_Mutex tclObjMutex;
Tcl_Mutex tclObjMutex;
#endif
@@ -50,17 +50,18 @@ Tcl_Mutex tclObjMutex;
*/
char tclEmptyString = '\0';
-
-#if TCL_THREADS && defined(TCL_MEM_DEBUG)
+char *tclEmptyStringRep = &tclEmptyString;
+
+#if defined(TCL_MEM_DEBUG) && defined(TCL_THREADS)
/*
- * Structure for tracking the source file and line number where a given
- * Tcl_Obj was allocated. We also track the pointer to the Tcl_Obj itself,
- * for sanity checking purposes.
+ * Structure for tracking the source file and line number where a given Tcl_Obj
+ * was allocated. We also track the pointer to the Tcl_Obj itself, for sanity
+ * checking purposes.
*/
-typedef struct {
+typedef struct ObjData {
Tcl_Obj *objPtr; /* The pointer to the allocated Tcl_Obj. */
- const char *file; /* The name of the source file calling this
+ CONST char *file; /* The name of the source file calling this
* function; used for debugging. */
int line; /* Line number in the source file; used for
* debugging. */
@@ -76,29 +77,34 @@ typedef struct {
* The structure defined below is used in this file only.
*/
-typedef struct {
- Tcl_HashTable *lineCLPtr; /* This table remembers for each Tcl_Obj
- * generated by a call to the function
- * TclSubstTokens() from a literal text
- * where bs+nl sequences occurred in it, if
- * any. I.e. this table keeps track of
- * invisible and stripped continuation lines.
- * Its keys are Tcl_Obj pointers, the values
- * are ContLineLoc pointers. See the file
- * tclCompile.h for the definition of this
- * structure, and for references to all
- * related places in the core. */
-#if TCL_THREADS && defined(TCL_MEM_DEBUG)
- Tcl_HashTable *objThreadMap;/* Thread local table that is used to check
- * that a Tcl_Obj was not allocated by some
- * other thread. */
+typedef struct ThreadSpecificData {
+ Tcl_HashTable* lineCLPtr; /* This table remembers for each Tcl_Obj
+ * generated by a call to the function
+ * TclSubstTokens() from a literal text
+ * where bs+nl sequences occured in it, if
+ * any. I.e. this table keeps track of
+ * invisible/stripped continuation lines. Its
+ * keys are Tcl_Obj pointers, the values are
+ * ContLineLoc pointers. See the file
+ * tclCompile.h for the definition of this
+ * structure, and for references to all related
+ * places in the core.
+ */
+#if defined(TCL_MEM_DEBUG) && defined(TCL_THREADS)
+ /*
+ * Thread local table that is used to check that a Tcl_Obj was not
+ * allocated by some other thread.
+ */
+
+ Tcl_HashTable *objThreadMap;
#endif /* TCL_MEM_DEBUG && TCL_THREADS */
} ThreadSpecificData;
static Tcl_ThreadDataKey dataKey;
-static void TclThreadFinalizeContLines(void *clientData);
-static ThreadSpecificData *TclGetContLineTable(void);
+static void ContLineLocFree (char* clientData);
+static void TclThreadFinalizeContLines (ClientData clientData);
+static ThreadSpecificData* TclGetContLineTable (void);
/*
* Nested Tcl_Obj deletion management support
@@ -111,14 +117,14 @@ static ThreadSpecificData *TclGetContLineTable(void);
*/
typedef struct PendingObjData {
- int deletionCount; /* Count of the number of invocations of
+ int deletionCount; /* Count of the number of invokations of
* TclFreeObj() are on the stack (at least
* conceptually; many are actually expanded
* macros). */
Tcl_Obj *deletionStack; /* Stack of objects that have had TclFreeObj()
* invoked upon them but which can't be
* deleted yet because they are in a nested
- * invocation of TclFreeObj(). By postponing
+ * invokation of TclFreeObj(). By postponing
* this way, we limit the maximum overall C
* stack depth when deleting a complex object.
* The down-side is that we alter the overall
@@ -145,31 +151,27 @@ typedef struct PendingObjData {
#define ObjDeletionUnlock(contextPtr) ((contextPtr)->deletionCount--)
#define ObjDeletePending(contextPtr) ((contextPtr)->deletionCount > 0)
#define ObjOnStack(contextPtr) ((contextPtr)->deletionStack != NULL)
-#define PushObjToDelete(contextPtr,objPtr) \
+#define PushObjToDelete(contextPtr,objPtr) \
/* The string rep is already invalidated so we can use the bytes value \
- * for our pointer chain: push onto the head of the stack. */ \
- (objPtr)->bytes = (char *) ((contextPtr)->deletionStack); \
+ * for our pointer chain: push onto the head of the stack. */ \
+ (objPtr)->bytes = (char *) ((contextPtr)->deletionStack); \
(contextPtr)->deletionStack = (objPtr)
-#define PopObjToDelete(contextPtr,objPtrVar) \
- (objPtrVar) = (contextPtr)->deletionStack; \
+#define PopObjToDelete(contextPtr,objPtrVar) \
+ (objPtrVar) = (contextPtr)->deletionStack; \
(contextPtr)->deletionStack = (Tcl_Obj *) (objPtrVar)->bytes
/*
* Macro to set up the local reference to the deletion context.
*/
-#if !TCL_THREADS
+#ifndef TCL_THREADS
static PendingObjData pendingObjData;
#define ObjInitDeletionContext(contextPtr) \
- PendingObjData *const contextPtr = &pendingObjData
-#elif defined(HAVE_FAST_TSD)
-static __thread PendingObjData pendingObjData;
-#define ObjInitDeletionContext(contextPtr) \
- PendingObjData *const contextPtr = &pendingObjData
+ PendingObjData *CONST contextPtr = &pendingObjData
#else
static Tcl_ThreadDataKey pendingObjDataKey;
#define ObjInitDeletionContext(contextPtr) \
- PendingObjData *const contextPtr = \
- (PendingObjData *)Tcl_GetThreadData(&pendingObjDataKey, sizeof(PendingObjData))
+ PendingObjData *CONST contextPtr = (PendingObjData *) \
+ Tcl_GetThreadData(&pendingObjDataKey, sizeof(PendingObjData))
#endif
/*
@@ -177,15 +179,29 @@ static Tcl_ThreadDataKey pendingObjDataKey;
*/
#define PACK_BIGNUM(bignum, objPtr) \
- if ((bignum).used > 0x7FFF) { \
- mp_int *temp = (mp_int *)ckalloc(sizeof(mp_int)); \
- *temp = bignum; \
- (objPtr)->internalRep.twoPtrValue.ptr1 = temp; \
- (objPtr)->internalRep.twoPtrValue.ptr2 = INT2PTR(-1); \
- } else if (((bignum).alloc <= 0x7FFF) || (mp_shrink(&(bignum))) == MP_OKAY) { \
- (objPtr)->internalRep.twoPtrValue.ptr1 = (void *)(bignum).dp; \
- (objPtr)->internalRep.twoPtrValue.ptr2 = INT2PTR(((bignum).sign << 30) \
- | ((bignum).alloc << 15) | ((bignum).used)); \
+ if ((bignum).used > 0x7fff) { \
+ mp_int *temp = (void *) ckalloc((unsigned) sizeof(mp_int)); \
+ *temp = bignum; \
+ (objPtr)->internalRep.ptrAndLongRep.ptr = (void*) temp; \
+ (objPtr)->internalRep.ptrAndLongRep.value = (unsigned long)(-1); \
+ } else { \
+ if ((bignum).alloc > 0x7fff) { \
+ mp_shrink(&(bignum)); \
+ } \
+ (objPtr)->internalRep.ptrAndLongRep.ptr = (void*) (bignum).dp; \
+ (objPtr)->internalRep.ptrAndLongRep.value = ( ((bignum).sign << 30) \
+ | ((bignum).alloc << 15) | ((bignum).used)); \
+ }
+
+#define UNPACK_BIGNUM(objPtr, bignum) \
+ if ((objPtr)->internalRep.ptrAndLongRep.value == (unsigned long)(-1)) { \
+ (bignum) = *((mp_int *) ((objPtr)->internalRep.ptrAndLongRep.ptr)); \
+ } else { \
+ (bignum).dp = (mp_digit*) (objPtr)->internalRep.ptrAndLongRep.ptr; \
+ (bignum).sign = (objPtr)->internalRep.ptrAndLongRep.value >> 30; \
+ (bignum).alloc = \
+ ((objPtr)->internalRep.ptrAndLongRep.value >> 15) & 0x7fff; \
+ (bignum).used = (objPtr)->internalRep.ptrAndLongRep.value & 0x7fff; \
}
/*
@@ -193,12 +209,14 @@ static Tcl_ThreadDataKey pendingObjDataKey;
*/
static int ParseBoolean(Tcl_Obj *objPtr);
+static int SetBooleanFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr);
static int SetDoubleFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr);
static int SetIntFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr);
static void UpdateStringOfDouble(Tcl_Obj *objPtr);
static void UpdateStringOfInt(Tcl_Obj *objPtr);
-#if !defined(TCL_NO_DEPRECATED) && TCL_MAJOR_VERSION < 9 && !defined(TCL_WIDE_INT_IS_LONG)
-static void UpdateStringOfOldInt(Tcl_Obj *objPtr);
+#ifndef NO_WIDE_TYPE
+static void UpdateStringOfWideInt(Tcl_Obj *objPtr);
+static int SetWideIntFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr);
#endif
static void FreeBignum(Tcl_Obj *objPtr);
static void DupBignum(Tcl_Obj *objPtr, Tcl_Obj *copyPtr);
@@ -228,62 +246,56 @@ static int SetCmdNameFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr);
* implementations.
*/
-#if !defined(TCL_NO_DEPRECATED) && TCL_MAJOR_VERSION < 9
-static const Tcl_ObjType oldBooleanType = {
- "boolean", /* name */
- NULL, /* freeIntRepProc */
- NULL, /* dupIntRepProc */
- NULL, /* updateStringProc */
- TclSetBooleanFromAny /* setFromAnyProc */
+static Tcl_ObjType oldBooleanType = {
+ "boolean", /* name */
+ NULL, /* freeIntRepProc */
+ NULL, /* dupIntRepProc */
+ NULL, /* updateStringProc */
+ SetBooleanFromAny /* setFromAnyProc */
};
-#endif
-const Tcl_ObjType tclBooleanType = {
- "booleanString", /* name */
- NULL, /* freeIntRepProc */
- NULL, /* dupIntRepProc */
- NULL, /* updateStringProc */
- TclSetBooleanFromAny /* setFromAnyProc */
+Tcl_ObjType tclBooleanType = {
+ "booleanString", /* name */
+ NULL, /* freeIntRepProc */
+ NULL, /* dupIntRepProc */
+ NULL, /* updateStringProc */
+ SetBooleanFromAny /* setFromAnyProc */
};
-const Tcl_ObjType tclDoubleType = {
- "double", /* name */
- NULL, /* freeIntRepProc */
- NULL, /* dupIntRepProc */
- UpdateStringOfDouble, /* updateStringProc */
- SetDoubleFromAny /* setFromAnyProc */
+Tcl_ObjType tclDoubleType = {
+ "double", /* name */
+ NULL, /* freeIntRepProc */
+ NULL, /* dupIntRepProc */
+ UpdateStringOfDouble, /* updateStringProc */
+ SetDoubleFromAny /* setFromAnyProc */
};
-const Tcl_ObjType tclIntType = {
-#if defined(TCL_NO_DEPRECATED) || TCL_MAJOR_VERSION > 8 || defined(TCL_WIDE_INT_IS_LONG)
- "int", /* name */
-#else
- "wideInt", /* name, keeping maximum compatibility with Tcl 8.6 on 32-bit platforms*/
-#endif
- NULL, /* freeIntRepProc */
- NULL, /* dupIntRepProc */
- UpdateStringOfInt, /* updateStringProc */
- SetIntFromAny /* setFromAnyProc */
+Tcl_ObjType tclIntType = {
+ "int", /* name */
+ NULL, /* freeIntRepProc */
+ NULL, /* dupIntRepProc */
+ UpdateStringOfInt, /* updateStringProc */
+ SetIntFromAny /* setFromAnyProc */
};
-#if !defined(TCL_NO_DEPRECATED) && TCL_MAJOR_VERSION < 9 && !defined(TCL_WIDE_INT_IS_LONG)
-static const Tcl_ObjType oldIntType = {
- "int", /* name */
- NULL, /* freeIntRepProc */
- NULL, /* dupIntRepProc */
- UpdateStringOfOldInt, /* updateStringProc */
- SetIntFromAny /* setFromAnyProc */
+#ifndef NO_WIDE_TYPE
+Tcl_ObjType tclWideIntType = {
+ "wideInt", /* name */
+ NULL, /* freeIntRepProc */
+ NULL, /* dupIntRepProc */
+ UpdateStringOfWideInt, /* updateStringProc */
+ SetWideIntFromAny /* setFromAnyProc */
};
#endif
-const Tcl_ObjType tclBignumType = {
- "bignum", /* name */
- FreeBignum, /* freeIntRepProc */
- DupBignum, /* dupIntRepProc */
- UpdateStringOfBignum, /* updateStringProc */
- NULL /* setFromAnyProc */
+Tcl_ObjType tclBignumType = {
+ "bignum", /* name */
+ FreeBignum, /* freeIntRepProc */
+ DupBignum, /* dupIntRepProc */
+ UpdateStringOfBignum, /* updateStringProc */
+ NULL /* setFromAnyProc */
};
/*
* The structure below defines the Tcl obj hash key type.
*/
-const Tcl_HashKeyType tclObjHashKeyType = {
+Tcl_HashKeyType tclObjHashKeyType = {
TCL_HASH_KEY_TYPE_VERSION, /* version */
0, /* flags */
TclHashObjKey, /* hashKeyProc */
@@ -305,22 +317,14 @@ const Tcl_HashKeyType tclObjHashKeyType = {
* ResolvedCmdName pointer, but DO NOT DO THIS. It seems that some extensions
* use the second internal pointer field of the twoPtrValue field for their
* own purposes.
- *
- * TRICKY POINT! Some extensions update this structure! (Notably, these
- * include TclBlend and TCom). This is highly ill-advised on their part, but
- * does allow them to delete a command when references to it are gone, which
- * is fragile but useful given their somewhat-OO style. Because of this, this
- * structure MUST NOT be const so that the C compiler puts the data in
- * writable memory. [Bug 2558422] [Bug 07d13d99b0a9]
- * TODO: Provide a better API for those extensions so that they can coexist...
*/
-Tcl_ObjType tclCmdNameType = {
- "cmdName", /* name */
- FreeCmdNameInternalRep, /* freeIntRepProc */
- DupCmdNameInternalRep, /* dupIntRepProc */
- NULL, /* updateStringProc */
- SetCmdNameFromAny /* setFromAnyProc */
+static Tcl_ObjType tclCmdNameType = {
+ "cmdName", /* name */
+ FreeCmdNameInternalRep, /* freeIntRepProc */
+ DupCmdNameInternalRep, /* dupIntRepProc */
+ NULL, /* updateStringProc */
+ SetCmdNameFromAny /* setFromAnyProc */
};
/*
@@ -336,23 +340,23 @@ typedef struct ResolvedCmdName {
* reference (not the namespace that contains
* the referenced command). NULL if the name
* is fully qualified.*/
- unsigned long refNsId; /* refNsPtr's unique namespace id. Used to
+ long refNsId; /* refNsPtr's unique namespace id. Used to
* verify that refNsPtr is still valid (e.g.,
* it's possible that the cmd's containing
* namespace was deleted and a new one created
* at the same address). */
- Tcl_Size refNsCmdEpoch; /* Value of the referencing namespace's
+ int refNsCmdEpoch; /* Value of the referencing namespace's
* cmdRefEpoch when the pointer was cached.
* Before using the cached pointer, we check
* if the namespace's epoch was incremented;
* if so, this cached pointer is invalid. */
- Tcl_Size cmdEpoch; /* Value of the command's cmdEpoch when this
+ int cmdEpoch; /* Value of the command's cmdEpoch when this
* pointer was cached. Before using the cached
* pointer, we check if the cmd's epoch was
* incremented; if so, the cmd was renamed,
* deleted, hidden, or exposed, and so the
* pointer is invalid. */
- size_t refCount; /* Reference count: 1 for each cmdName object
+ int refCount; /* Reference count: 1 for each cmdName object
* that has a pointer to this ResolvedCmdName
* structure as its internal rep. This
* structure can be freed when refCount
@@ -387,26 +391,21 @@ TclInitObjSubsystem(void)
Tcl_RegisterObjType(&tclByteArrayType);
Tcl_RegisterObjType(&tclDoubleType);
-#if !defined(TCL_NO_DEPRECATED)
+ Tcl_RegisterObjType(&tclEndOffsetType);
+ Tcl_RegisterObjType(&tclIntType);
Tcl_RegisterObjType(&tclStringType);
- /* Only registered for 8.7, not for 9.0 any more.
- * See [https://core.tcl-lang.org/tk/tktview/6b49149b4e] */
- Tcl_RegisterObjType(&tclUniCharStringType);
-#endif
Tcl_RegisterObjType(&tclListType);
Tcl_RegisterObjType(&tclDictType);
Tcl_RegisterObjType(&tclByteCodeType);
+ Tcl_RegisterObjType(&tclArraySearchType);
Tcl_RegisterObjType(&tclCmdNameType);
Tcl_RegisterObjType(&tclRegexpType);
Tcl_RegisterObjType(&tclProcBodyType);
/* For backward compatibility only ... */
-#if !defined(TCL_NO_DEPRECATED) && TCL_MAJOR_VERSION < 9
- Tcl_RegisterObjType(&tclIntType);
-#if !defined(TCL_WIDE_INT_IS_LONG)
- Tcl_RegisterObjType(&oldIntType);
-#endif
Tcl_RegisterObjType(&oldBooleanType);
+#ifndef NO_WIDE_TYPE
+ Tcl_RegisterObjType(&tclWideIntType);
#endif
#ifdef TCL_COMPILE_STATS
@@ -415,7 +414,6 @@ TclInitObjSubsystem(void)
tclObjsFreed = 0;
{
int i;
-
for (i=0 ; i<TCL_MAX_SHARED_OBJ_STATS ; i++) {
tclObjsShared[i] = 0;
}
@@ -444,7 +442,7 @@ TclInitObjSubsystem(void)
void
TclFinalizeThreadObjects(void)
{
-#if TCL_THREADS && defined(TCL_MEM_DEBUG)
+#if defined(TCL_MEM_DEBUG) && defined(TCL_THREADS)
Tcl_HashEntry *hPtr;
Tcl_HashSearch hSearch;
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
@@ -453,15 +451,15 @@ TclFinalizeThreadObjects(void)
if (tablePtr != NULL) {
for (hPtr = Tcl_FirstHashEntry(tablePtr, &hSearch);
hPtr != NULL; hPtr = Tcl_NextHashEntry(&hSearch)) {
- ObjData *objData = (ObjData *)Tcl_GetHashValue(hPtr);
+ ObjData *objData = Tcl_GetHashValue(hPtr);
if (objData != NULL) {
- ckfree(objData);
+ ckfree((char *) objData);
}
}
Tcl_DeleteHashTable(tablePtr);
- ckfree(tablePtr);
+ ckfree((char *) tablePtr);
tsdPtr->objThreadMap = NULL;
}
#endif
@@ -523,8 +521,8 @@ TclFinalizeObjects(void)
*----------------------------------------------------------------------
*/
-static ThreadSpecificData *
-TclGetContLineTable(void)
+static ThreadSpecificData*
+TclGetContLineTable()
{
/*
* Initialize the hashtable tracking invisible continuation lines. For
@@ -535,11 +533,10 @@ TclGetContLineTable(void)
*/
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
-
if (!tsdPtr->lineCLPtr) {
- tsdPtr->lineCLPtr = (Tcl_HashTable *)ckalloc(sizeof(Tcl_HashTable));
+ tsdPtr->lineCLPtr = (Tcl_HashTable*) ckalloc (sizeof (Tcl_HashTable));
Tcl_InitHashTable(tsdPtr->lineCLPtr, TCL_ONE_WORD_KEYS);
- Tcl_CreateThreadExitHandler(TclThreadFinalizeContLines,NULL);
+ Tcl_CreateThreadExitHandler (TclThreadFinalizeContLines,NULL);
}
return tsdPtr;
}
@@ -562,17 +559,18 @@ TclGetContLineTable(void)
*----------------------------------------------------------------------
*/
-ContLineLoc *
-TclContinuationsEnter(
- Tcl_Obj *objPtr,
- Tcl_Size num,
- Tcl_Size *loc)
+ContLineLoc*
+TclContinuationsEnter(Tcl_Obj* objPtr,
+ int num,
+ int* loc)
{
int newEntry;
ThreadSpecificData *tsdPtr = TclGetContLineTable();
- Tcl_HashEntry *hPtr =
- Tcl_CreateHashEntry(tsdPtr->lineCLPtr, objPtr, &newEntry);
- ContLineLoc *clLocPtr = (ContLineLoc *)ckalloc(offsetof(ContLineLoc, loc) + (num + 1U) *sizeof(Tcl_Size));
+ Tcl_HashEntry* hPtr =
+ Tcl_CreateHashEntry (tsdPtr->lineCLPtr, (char*) objPtr, &newEntry);
+
+ ContLineLoc* clLocPtr =
+ (ContLineLoc*) ckalloc (sizeof(ContLineLoc) + num*sizeof(int));
if (!newEntry) {
/*
@@ -584,25 +582,25 @@ TclContinuationsEnter(
* the switch command is identical, mapping them all to the same
* literal. An interesting result of this is that the number and
* locations (offset) of invisible continuation lines in the literal
- * are the same for all occurrences.
+ * are the same for all occurences.
*
* Note that while reusing the existing entry is possible it requires
* the same actions as for a new entry because we have to copy the
* incoming num/loc data even so. Because we are called from
* TclContinuationsEnterDerived for this case, which modified the
* stored locations (Rebased to the proper relative offset). Just
- * returning the stored entry would rebase them a second time, or
- * more, hosing the data. It is easier to simply replace, as we are
- * doing.
+ * returning the stored entry and data would rebase them a second
+ * time, or more, hosing the data. It is easier to simply replace, as
+ * we are doing.
*/
- ckfree(Tcl_GetHashValue(hPtr));
+ ckfree((char *) Tcl_GetHashValue(hPtr));
}
clLocPtr->num = num;
- memcpy(&clLocPtr->loc, loc, num*sizeof(Tcl_Size));
- clLocPtr->loc[num] = CLL_END; /* Sentinel */
- Tcl_SetHashValue(hPtr, clLocPtr);
+ memcpy (&clLocPtr->loc, loc, num*sizeof(int));
+ clLocPtr->loc[num] = CLL_END; /* Sentinel */
+ Tcl_SetHashValue (hPtr, clLocPtr);
return clLocPtr;
}
@@ -627,15 +625,8 @@ TclContinuationsEnter(
*/
void
-TclContinuationsEnterDerived(
- Tcl_Obj *objPtr,
- Tcl_Size start,
- Tcl_Size *clNext)
+TclContinuationsEnterDerived(Tcl_Obj* objPtr, int start, int* clNext)
{
- Tcl_Size length;
- Tcl_Size end, num;
- Tcl_Size *wordCLLast = clNext;
-
/*
* We have to handle invisible continuations lines here as well, despite
* the code we have in TclSubstTokens (TST) for that. Why ? Nesting. If
@@ -656,15 +647,20 @@ TclContinuationsEnterDerived(
*/
/*
- * First compute the range of the word within the script. (Is there a
- * better way which doesn't shimmer?)
+ * First compute the range of the word within the script.
*/
- TclGetStringFromObj(objPtr, &length);
- end = start + length; /* First char after the word */
+ int length, end, num;
+ int* wordCLLast = clNext;
+
+ Tcl_GetStringFromObj(objPtr, &length);
+ /* Is there a better way which doesn't shimmer ? */
+
+ end = start + length; /* first char after the word */
/*
- * Then compute the table slice covering the range of the word.
+ * Then compute the table slice covering the range of
+ * the word.
*/
while (*wordCLLast >= 0 && *wordCLLast < end) {
@@ -672,19 +668,21 @@ TclContinuationsEnterDerived(
}
/*
- * And generate the table from the slice, if it was not empty.
+ * And generate the table from the slice, if it was
+ * not empty.
*/
num = wordCLLast - clNext;
if (num) {
- Tcl_Size i;
- ContLineLoc *clLocPtr = TclContinuationsEnter(objPtr, num, clNext);
+ int i;
+ ContLineLoc* clLocPtr =
+ TclContinuationsEnter(objPtr, num, clNext);
/*
* Re-base the locations.
*/
- for (i=0 ; i<num ; i++) {
+ for (i=0;i<num;i++) {
clLocPtr->loc[i] -= start;
/*
@@ -706,9 +704,9 @@ TclContinuationsEnterDerived(
* TclContinuationsCopy --
*
* This procedure is a helper which copies the continuation line
- * information associated with a Tcl_Obj* to another Tcl_Obj*. It is
- * assumed that both contain the same string/script. Use this when a
- * script is duplicated because it was shared.
+ * information associated with a Tcl_Obj* to another Tcl_Obj*.
+ * It is assumed that both contain the same string/script. Use
+ * this when a script is duplicated because it was shared.
*
* Results:
* None.
@@ -721,16 +719,13 @@ TclContinuationsEnterDerived(
*/
void
-TclContinuationsCopy(
- Tcl_Obj *objPtr,
- Tcl_Obj *originObjPtr)
+TclContinuationsCopy(Tcl_Obj* objPtr, Tcl_Obj* originObjPtr)
{
ThreadSpecificData *tsdPtr = TclGetContLineTable();
- Tcl_HashEntry *hPtr =
- Tcl_FindHashEntry(tsdPtr->lineCLPtr, originObjPtr);
+ Tcl_HashEntry* hPtr = Tcl_FindHashEntry (tsdPtr->lineCLPtr, (char*) originObjPtr);
if (hPtr) {
- ContLineLoc *clLocPtr = (ContLineLoc *)Tcl_GetHashValue(hPtr);
+ ContLineLoc* clLocPtr = (ContLineLoc*) Tcl_GetHashValue (hPtr);
TclContinuationsEnter(objPtr, clLocPtr->num, clLocPtr->loc);
}
@@ -745,8 +740,8 @@ TclContinuationsCopy(
* information associated with a Tcl_Obj*, if it has any.
*
* Results:
- * A reference to the continuation line location table, or NULL if the
- * Tcl_Obj* has no such information associated with it.
+ * A reference to the continuation line location table, or NULL
+ * if the Tcl_Obj* has no such information associated with it.
*
* Side effects:
* None.
@@ -755,18 +750,17 @@ TclContinuationsCopy(
*----------------------------------------------------------------------
*/
-ContLineLoc *
-TclContinuationsGet(
- Tcl_Obj *objPtr)
+ContLineLoc*
+TclContinuationsGet(Tcl_Obj* objPtr)
{
ThreadSpecificData *tsdPtr = TclGetContLineTable();
- Tcl_HashEntry *hPtr =
- Tcl_FindHashEntry(tsdPtr->lineCLPtr, objPtr);
+ Tcl_HashEntry* hPtr = Tcl_FindHashEntry (tsdPtr->lineCLPtr, (char*) objPtr);
- if (!hPtr) {
- return NULL;
+ if (hPtr) {
+ return (ContLineLoc*) Tcl_GetHashValue (hPtr);
+ } else {
+ return NULL;
}
- return (ContLineLoc *)Tcl_GetHashValue(hPtr);
}
/*
@@ -788,8 +782,7 @@ TclContinuationsGet(
*/
static void
-TclThreadFinalizeContLines(
- TCL_UNUSED(void *))
+TclThreadFinalizeContLines (ClientData clientData)
{
/*
* Release the hashtable tracking invisible continuation lines.
@@ -800,16 +793,46 @@ TclThreadFinalizeContLines(
Tcl_HashSearch hSearch;
for (hPtr = Tcl_FirstHashEntry(tsdPtr->lineCLPtr, &hSearch);
- hPtr != NULL; hPtr = Tcl_NextHashEntry(&hSearch)) {
- ckfree(Tcl_GetHashValue(hPtr));
- Tcl_DeleteHashEntry(hPtr);
+ hPtr != NULL;
+ hPtr = Tcl_NextHashEntry(&hSearch)) {
+ /*
+ * We are not using Tcl_EventuallyFree (as in TclFreeObj()) because
+ * here we can be sure that the compiler will not hold references to
+ * the data in the hashtable, and using TEF might bork the
+ * finalization sequence.
+ */
+ ContLineLocFree (Tcl_GetHashValue (hPtr));
+ Tcl_DeleteHashEntry (hPtr);
}
- Tcl_DeleteHashTable(tsdPtr->lineCLPtr);
- ckfree(tsdPtr->lineCLPtr);
+ Tcl_DeleteHashTable (tsdPtr->lineCLPtr);
+ ckfree((char *) tsdPtr->lineCLPtr);
tsdPtr->lineCLPtr = NULL;
}
/*
+ *----------------------------------------------------------------------
+ *
+ * ContLineLocFree --
+ *
+ * The freProc for continuation line location tables.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * Releases memory.
+ *
+ * TIP #280
+ *----------------------------------------------------------------------
+ */
+
+static void
+ContLineLocFree (char* clientData)
+{
+ ckfree (clientData);
+}
+
+/*
*--------------------------------------------------------------
*
* Tcl_RegisterObjType --
@@ -830,7 +853,7 @@ TclThreadFinalizeContLines(
void
Tcl_RegisterObjType(
- const Tcl_ObjType *typePtr) /* Information about object type; storage must
+ Tcl_ObjType *typePtr) /* Information about object type; storage must
* be statically allocated (must live
* forever). */
{
@@ -873,9 +896,9 @@ Tcl_AppendAllObjTypes(
* name of each registered type is appended as
* a list element. */
{
- Tcl_HashEntry *hPtr;
+ register Tcl_HashEntry *hPtr;
Tcl_HashSearch search;
- Tcl_Size numElems;
+ int numElems;
/*
* Get the test for a valid list out of the way first.
@@ -894,7 +917,7 @@ Tcl_AppendAllObjTypes(
for (hPtr = Tcl_FirstHashEntry(&typeTable, &search);
hPtr != NULL; hPtr = Tcl_NextHashEntry(&search)) {
Tcl_ListObjAppendElement(NULL, objPtr,
- Tcl_NewStringObj((char *)Tcl_GetHashKey(&typeTable, hPtr), -1));
+ Tcl_NewStringObj(Tcl_GetHashKey(&typeTable, hPtr), -1));
}
Tcl_MutexUnlock(&tableMutex);
return TCL_OK;
@@ -917,17 +940,17 @@ Tcl_AppendAllObjTypes(
*----------------------------------------------------------------------
*/
-const Tcl_ObjType *
+Tcl_ObjType *
Tcl_GetObjType(
- const char *typeName) /* Name of Tcl object type to look up. */
+ CONST char *typeName) /* Name of Tcl object type to look up. */
{
- Tcl_HashEntry *hPtr;
- const Tcl_ObjType *typePtr = NULL;
+ register Tcl_HashEntry *hPtr;
+ Tcl_ObjType *typePtr = NULL;
Tcl_MutexLock(&tableMutex);
hPtr = Tcl_FindHashEntry(&typeTable, typeName);
if (hPtr != NULL) {
- typePtr = (const Tcl_ObjType *)Tcl_GetHashValue(hPtr);
+ typePtr = (Tcl_ObjType *) Tcl_GetHashValue(hPtr);
}
Tcl_MutexUnlock(&tableMutex);
return typePtr;
@@ -957,7 +980,7 @@ int
Tcl_ConvertToType(
Tcl_Interp *interp, /* Used for error reporting if not NULL. */
Tcl_Obj *objPtr, /* The object to convert. */
- const Tcl_ObjType *typePtr) /* The target type. */
+ Tcl_ObjType *typePtr) /* The target type. */
{
if (objPtr->typePtr == typePtr) {
return TCL_OK;
@@ -973,7 +996,7 @@ Tcl_ConvertToType(
if (interp) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"can't convert value to type %s", typePtr->name));
- Tcl_SetErrorCode(interp, "TCL", "API_ABUSE", (void *)NULL);
+ Tcl_SetErrorCode(interp, "TCL", "API_ABUSE", NULL);
}
return TCL_ERROR;
}
@@ -998,11 +1021,11 @@ Tcl_ConvertToType(
*--------------------------------------------------------------
*/
-#if TCL_THREADS && defined(TCL_MEM_DEBUG)
void
TclDbDumpActiveObjects(
FILE *outFile)
{
+#if defined(TCL_MEM_DEBUG) && defined(TCL_THREADS)
Tcl_HashSearch hSearch;
Tcl_HashEntry *hPtr;
Tcl_HashTable *tablePtr;
@@ -1011,10 +1034,10 @@ TclDbDumpActiveObjects(
tablePtr = tsdPtr->objThreadMap;
if (tablePtr != NULL) {
- fprintf(outFile, "total objects: %" TCL_SIZE_MODIFIER "d\n", tablePtr->numEntries);
+ fprintf(outFile, "total objects: %d\n", tablePtr->numEntries);
for (hPtr = Tcl_FirstHashEntry(tablePtr, &hSearch); hPtr != NULL;
hPtr = Tcl_NextHashEntry(&hSearch)) {
- ObjData *objData = (ObjData *)Tcl_GetHashValue(hPtr);
+ ObjData *objData = Tcl_GetHashValue(hPtr);
if (objData != NULL) {
fprintf(outFile,
@@ -1027,14 +1050,8 @@ TclDbDumpActiveObjects(
}
}
}
-}
-#else
-void
-TclDbDumpActiveObjects(
- TCL_UNUSED(FILE *))
-{
-}
#endif
+}
/*
*----------------------------------------------------------------------
@@ -1043,7 +1060,7 @@ TclDbDumpActiveObjects(
*
* Called via the TclNewObj or TclDbNewObj macros when TCL_MEM_DEBUG is
* enabled. This function will initialize the members of a Tcl_Obj
- * struct. Initialization would be done inline via the TclNewObj macro
+ * struct. Initilization would be done inline via the TclNewObj macro
* when compiling without TCL_MEM_DEBUG.
*
* Results:
@@ -1057,17 +1074,18 @@ TclDbDumpActiveObjects(
#ifdef TCL_MEM_DEBUG
void
TclDbInitNewObj(
- Tcl_Obj *objPtr,
- const char *file, /* The name of the source file calling this
+ register Tcl_Obj *objPtr,
+ register CONST char *file, /* The name of the source file calling this
* function; used for debugging. */
- int line) /* Line number in the source file; used for
+ register int line) /* Line number in the source file; used for
* debugging. */
{
objPtr->refCount = 0;
+ objPtr->bytes = tclEmptyStringRep;
+ objPtr->length = 0;
objPtr->typePtr = NULL;
- TclInitEmptyStringRep(objPtr);
-#if TCL_THREADS
+#ifdef TCL_THREADS
/*
* Add entry to a thread local map used to check if a Tcl_Obj was
* allocated by the currently executing thread.
@@ -1081,11 +1099,12 @@ TclDbInitNewObj(
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
if (tsdPtr->objThreadMap == NULL) {
- tsdPtr->objThreadMap = (Tcl_HashTable *)ckalloc(sizeof(Tcl_HashTable));
+ tsdPtr->objThreadMap = (Tcl_HashTable *)
+ ckalloc(sizeof(Tcl_HashTable));
Tcl_InitHashTable(tsdPtr->objThreadMap, TCL_ONE_WORD_KEYS);
}
tablePtr = tsdPtr->objThreadMap;
- hPtr = Tcl_CreateHashEntry(tablePtr, objPtr, &isNew);
+ hPtr = Tcl_CreateHashEntry(tablePtr, (char *) objPtr, &isNew);
if (!isNew) {
Tcl_Panic("expected to create new entry for object map");
}
@@ -1094,7 +1113,7 @@ TclDbInitNewObj(
* Record the debugging information.
*/
- objData = (ObjData *)ckalloc(sizeof(ObjData));
+ objData = (ObjData *) ckalloc(sizeof(ObjData));
objData->objPtr = objPtr;
objData->file = file;
objData->line = line;
@@ -1144,7 +1163,7 @@ Tcl_NewObj(void)
Tcl_Obj *
Tcl_NewObj(void)
{
- Tcl_Obj *objPtr;
+ register Tcl_Obj *objPtr;
/*
* Use the macro defined in tclInt.h - it will use the correct allocator.
@@ -1186,12 +1205,12 @@ Tcl_NewObj(void)
Tcl_Obj *
Tcl_DbNewObj(
- const char *file, /* The name of the source file calling this
+ register CONST char *file, /* The name of the source file calling this
* function; used for debugging. */
- int line) /* Line number in the source file; used for
+ register int line) /* Line number in the source file; used for
* debugging. */
{
- Tcl_Obj *objPtr;
+ register Tcl_Obj *objPtr;
/*
* Use the macro defined in tclInt.h - it will use the correct allocator.
@@ -1204,12 +1223,12 @@ Tcl_DbNewObj(
Tcl_Obj *
Tcl_DbNewObj(
- TCL_UNUSED(const char *) /*file*/,
- TCL_UNUSED(int) /*line*/)
+ CONST char *file, /* The name of the source file calling this
+ * function; used for debugging. */
+ int line) /* Line number in the source file; used for
+ * debugging. */
{
- Tcl_Obj *objPtr;
- TclNewObj(objPtr);
- return objPtr;
+ return Tcl_NewObj();
}
#endif /* TCL_MEM_DEBUG */
@@ -1241,8 +1260,8 @@ TclAllocateFreeObjects(void)
{
size_t bytesToAlloc = (OBJS_TO_ALLOC_EACH_TIME * sizeof(Tcl_Obj));
char *basePtr;
- Tcl_Obj *prevPtr, *objPtr;
- int i;
+ register Tcl_Obj *prevPtr, *objPtr;
+ register int i;
/*
* This has been noted by Purify to be a potential leak. The problem is
@@ -1253,12 +1272,12 @@ TclAllocateFreeObjects(void)
* Purify apparently can't figure that out, and fires a false alarm.
*/
- basePtr = (char *)ckalloc(bytesToAlloc);
+ basePtr = (char *) ckalloc(bytesToAlloc);
prevPtr = NULL;
objPtr = (Tcl_Obj *) basePtr;
for (i = 0; i < OBJS_TO_ALLOC_EACH_TIME; i++) {
- objPtr->internalRep.twoPtrValue.ptr1 = prevPtr;
+ objPtr->internalRep.twoPtrValue.ptr1 = (void *) prevPtr;
prevPtr = objPtr;
objPtr++;
}
@@ -1293,9 +1312,9 @@ TclAllocateFreeObjects(void)
#ifdef TCL_MEM_DEBUG
void
TclFreeObj(
- Tcl_Obj *objPtr) /* The object to be freed. */
+ register Tcl_Obj *objPtr) /* The object to be freed. */
{
- const Tcl_ObjType *typePtr = objPtr->typePtr;
+ register Tcl_ObjType *typePtr = objPtr->typePtr;
/*
* This macro declares a variable, so must come here...
@@ -1303,7 +1322,7 @@ TclFreeObj(
ObjInitDeletionContext(context);
-#if TCL_THREADS
+# ifdef TCL_THREADS
/*
* Check to make sure that the Tcl_Obj was allocated by the current
* thread. Don't do this check when shutting down since thread local
@@ -1325,10 +1344,10 @@ TclFreeObj(
* As the Tcl_Obj is going to be deleted we remove the entry.
*/
- ObjData *objData = (ObjData *)Tcl_GetHashValue(hPtr);
+ ObjData *objData = Tcl_GetHashValue(hPtr);
if (objData != NULL) {
- ckfree(objData);
+ ckfree((char *) objData);
}
Tcl_DeleteHashEntry(hPtr);
@@ -1343,23 +1362,21 @@ TclFreeObj(
* and so on, is always a sign of a botch in the caller.
*/
if (objPtr->refCount < -1) {
- Tcl_Panic("Reference count for %p was negative", objPtr);
+ Tcl_Panic("Reference count for %lx was negative", objPtr);
}
/*
* Now, in case we just approved drop from 1 to 0 as acceptable, make
* sure we do not accept a second free when falling from 0 to -1.
* Skip that possibility so any double free will trigger the panic.
*/
- objPtr->refCount = TCL_INDEX_NONE;
+ objPtr->refCount = -1;
- /*
- * Invalidate the string rep first so we can use the bytes value for our
- * pointer chain, and signal an obj deletion (as opposed to shimmering)
- * with 'length == TCL_INDEX_NONE'.
- */
+ /* Invalidate the string rep first so we can use the bytes value
+ * for our pointer chain, and signal an obj deletion (as opposed
+ * to shimmering) with 'length == -1' */
TclInvalidateStringRep(objPtr);
- objPtr->length = TCL_INDEX_NONE;
+ objPtr->length = -1;
if (ObjDeletePending(context)) {
PushObjToDelete(context, objPtr);
@@ -1372,19 +1389,19 @@ TclFreeObj(
}
Tcl_MutexLock(&tclObjMutex);
- ckfree(objPtr);
+ ckfree((char *) objPtr);
Tcl_MutexUnlock(&tclObjMutex);
TclIncrObjsFreed();
ObjDeletionLock(context);
while (ObjOnStack(context)) {
Tcl_Obj *objToFree;
- PopObjToDelete(context, objToFree);
+ PopObjToDelete(context,objToFree);
TCL_DTRACE_OBJ_FREE(objToFree);
- TclFreeInternalRep(objToFree);
+ TclFreeIntRep(objToFree);
Tcl_MutexLock(&tclObjMutex);
- ckfree(objToFree);
+ ckfree((char *) objToFree);
Tcl_MutexUnlock(&tclObjMutex);
TclIncrObjsFreed();
}
@@ -1393,23 +1410,22 @@ TclFreeObj(
/*
* We cannot use TclGetContinuationTable() here, because that may
- * re-initialize the thread-data for calls coming after the finalization.
- * We have to access it using the low-level call and then check for
- * validity. This function can be called after TclFinalizeThreadData() has
- * already killed the thread-global data structures. Performing
- * TCL_TSD_INIT will leave us with an uninitialized memory block upon
- * which we crash (if we where to access the uninitialized hashtable).
+ * re-initialize the thread-data for calls coming after the
+ * finalization. We have to access it using the low-level call and then
+ * check for validity. This function can be called after
+ * TclFinalizeThreadData() has already killed the thread-global data
+ * structures. Performing TCL_TSD_INIT will leave us with an
+ * un-initialized memory block upon which we crash (if we where to access
+ * the uninitialized hashtable).
*/
{
- ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
- Tcl_HashEntry *hPtr;
-
+ ThreadSpecificData* tsdPtr = TCL_TSD_INIT(&dataKey);
if (tsdPtr->lineCLPtr) {
- hPtr = Tcl_FindHashEntry(tsdPtr->lineCLPtr, objPtr);
+ Tcl_HashEntry* hPtr = Tcl_FindHashEntry (tsdPtr->lineCLPtr, (char *) objPtr);
if (hPtr) {
- ckfree(Tcl_GetHashValue(hPtr));
- Tcl_DeleteHashEntry(hPtr);
+ Tcl_EventuallyFree (Tcl_GetHashValue (hPtr), ContLineLocFree);
+ Tcl_DeleteHashEntry (hPtr);
}
}
}
@@ -1418,16 +1434,14 @@ TclFreeObj(
void
TclFreeObj(
- Tcl_Obj *objPtr) /* The object to be freed. */
+ register Tcl_Obj *objPtr) /* The object to be freed. */
{
- /*
- * Invalidate the string rep first so we can use the bytes value for our
- * pointer chain, and signal an obj deletion (as opposed to shimmering)
- * with 'length == -1'.
- */
+ /* Invalidate the string rep first so we can use the bytes value
+ * for our pointer chain, and signal an obj deletion (as opposed
+ * to shimmering) with 'length == -1' */
TclInvalidateStringRep(objPtr);
- objPtr->length = TCL_INDEX_NONE;
+ objPtr->length = -1;
if (!objPtr->typePtr || !objPtr->typePtr->freeIntRepProc) {
/*
@@ -1468,8 +1482,7 @@ TclFreeObj(
ObjDeletionLock(context);
while (ObjOnStack(context)) {
Tcl_Obj *objToFree;
-
- PopObjToDelete(context, objToFree);
+ PopObjToDelete(context,objToFree);
TCL_DTRACE_OBJ_FREE(objToFree);
if ((objToFree->typePtr != NULL)
&& (objToFree->typePtr->freeIntRepProc != NULL)) {
@@ -1484,28 +1497,27 @@ TclFreeObj(
/*
* We cannot use TclGetContinuationTable() here, because that may
- * re-initialize the thread-data for calls coming after the finalization.
- * We have to access it using the low-level call and then check for
- * validity. This function can be called after TclFinalizeThreadData() has
- * already killed the thread-global data structures. Performing
- * TCL_TSD_INIT will leave us with an uninitialized memory block upon
- * which we crash (if we where to access the uninitialized hashtable).
+ * re-initialize the thread-data for calls coming after the
+ * finalization. We have to access it using the low-level call and then
+ * check for validity. This function can be called after
+ * TclFinalizeThreadData() has already killed the thread-global data
+ * structures. Performing TCL_TSD_INIT will leave us with an
+ * un-initialized memory block upon which we crash (if we where to access
+ * the uninitialized hashtable).
*/
{
- ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
- Tcl_HashEntry *hPtr;
-
+ ThreadSpecificData* tsdPtr = TCL_TSD_INIT(&dataKey);
if (tsdPtr->lineCLPtr) {
- hPtr = Tcl_FindHashEntry(tsdPtr->lineCLPtr, objPtr);
+ Tcl_HashEntry* hPtr = Tcl_FindHashEntry (tsdPtr->lineCLPtr, (char *) objPtr);
if (hPtr) {
- ckfree(Tcl_GetHashValue(hPtr));
- Tcl_DeleteHashEntry(hPtr);
+ Tcl_EventuallyFree (Tcl_GetHashValue (hPtr), ContLineLocFree);
+ Tcl_DeleteHashEntry (hPtr);
}
}
}
}
-#endif /* TCL_MEM_DEBUG */
+#endif
/*
*----------------------------------------------------------------------
@@ -1529,8 +1541,9 @@ int
TclObjBeingDeleted(
Tcl_Obj *objPtr)
{
- return (objPtr->length == TCL_INDEX_NONE);
+ return (objPtr->length == -1);
}
+
/*
*----------------------------------------------------------------------
@@ -1561,47 +1574,30 @@ TclObjBeingDeleted(
*----------------------------------------------------------------------
*/
-#define SetDuplicateObj(dupPtr, objPtr) \
- { \
- const Tcl_ObjType *typePtr = (objPtr)->typePtr; \
- const char *bytes = (objPtr)->bytes; \
- if (bytes) { \
- (void)TclAttemptInitStringRep((dupPtr), bytes, (objPtr)->length); \
- } else { \
- (dupPtr)->bytes = NULL; \
- } \
- if (typePtr) { \
- if (typePtr->dupIntRepProc) { \
- typePtr->dupIntRepProc((objPtr), (dupPtr)); \
- } else { \
- (dupPtr)->internalRep = (objPtr)->internalRep; \
- (dupPtr)->typePtr = typePtr; \
- } \
- } \
- }
-
Tcl_Obj *
Tcl_DuplicateObj(
- Tcl_Obj *objPtr) /* The object to duplicate. */
+ register Tcl_Obj *objPtr) /* The object to duplicate. */
{
- Tcl_Obj *dupPtr;
+ register Tcl_ObjType *typePtr = objPtr->typePtr;
+ register Tcl_Obj *dupPtr;
TclNewObj(dupPtr);
- SetDuplicateObj(dupPtr, objPtr);
- return dupPtr;
-}
-void
-TclSetDuplicateObj(
- Tcl_Obj *dupPtr,
- Tcl_Obj *objPtr)
-{
- if (Tcl_IsShared(dupPtr)) {
- Tcl_Panic("%s called with shared object", "TclSetDuplicateObj");
+ if (objPtr->bytes == NULL) {
+ dupPtr->bytes = NULL;
+ } else if (objPtr->bytes != tclEmptyStringRep) {
+ TclInitStringRep(dupPtr, objPtr->bytes, objPtr->length);
+ }
+
+ if (typePtr != NULL) {
+ if (typePtr->dupIntRepProc == NULL) {
+ dupPtr->internalRep = objPtr->internalRep;
+ dupPtr->typePtr = typePtr;
+ } else {
+ (*typePtr->dupIntRepProc)(objPtr, dupPtr);
+ }
}
- TclInvalidateStringRep(dupPtr);
- TclFreeInternalRep(dupPtr);
- SetDuplicateObj(dupPtr, objPtr);
+ return dupPtr;
}
/*
@@ -1625,37 +1621,20 @@ TclSetDuplicateObj(
*----------------------------------------------------------------------
*/
-#undef Tcl_GetString
char *
Tcl_GetString(
- Tcl_Obj *objPtr) /* Object whose string rep byte pointer should
+ register Tcl_Obj *objPtr) /* Object whose string rep byte pointer should
* be returned. */
{
- if (objPtr->bytes == NULL) {
- /*
- * Note we do not check for objPtr->typePtr == NULL. An invariant
- * of a properly maintained Tcl_Obj is that at least one of
- * objPtr->bytes and objPtr->typePtr must not be NULL. If broken
- * extensions fail to maintain that invariant, we can crash here.
- */
+ if (objPtr->bytes != NULL) {
+ return objPtr->bytes;
+ }
- if (objPtr->typePtr->updateStringProc == NULL) {
- /*
- * Those Tcl_ObjTypes which choose not to define an
- * updateStringProc must be written in such a way that
- * (objPtr->bytes) never becomes NULL.
- */
- Tcl_Panic("UpdateStringProc should not be invoked for type %s",
- objPtr->typePtr->name);
- }
- objPtr->typePtr->updateStringProc(objPtr);
- if (objPtr->bytes == NULL || objPtr->length < 0
- || objPtr->bytes[objPtr->length] != '\0') {
- Tcl_Panic("UpdateStringProc for type '%s' "
- "failed to create a valid string rep",
- objPtr->typePtr->name);
- }
+ if (objPtr->typePtr->updateStringProc == NULL) {
+ Tcl_Panic("UpdateStringProc should not be invoked for type %s",
+ objPtr->typePtr->name);
}
+ (*objPtr->typePtr->updateStringProc)(objPtr);
return objPtr->bytes;
}
@@ -1684,37 +1663,20 @@ Tcl_GetString(
char *
Tcl_GetStringFromObj(
- Tcl_Obj *objPtr, /* Object whose string rep byte pointer should
+ register Tcl_Obj *objPtr, /* Object whose string rep byte pointer should
* be returned. */
- int *lengthPtr) /* If non-NULL, the location where the string
+ register int *lengthPtr) /* If non-NULL, the location where the string
* rep's byte array length should * be stored.
* If NULL, no length is stored. */
{
if (objPtr->bytes == NULL) {
- /*
- * Note we do not check for objPtr->typePtr == NULL. An invariant
- * of a properly maintained Tcl_Obj is that at least one of
- * objPtr->bytes and objPtr->typePtr must not be NULL. If broken
- * extensions fail to maintain that invariant, we can crash here.
- */
-
if (objPtr->typePtr->updateStringProc == NULL) {
- /*
- * Those Tcl_ObjTypes which choose not to define an
- * updateStringProc must be written in such a way that
- * (objPtr->bytes) never becomes NULL.
- */
Tcl_Panic("UpdateStringProc should not be invoked for type %s",
objPtr->typePtr->name);
}
- objPtr->typePtr->updateStringProc(objPtr);
- if (objPtr->bytes == NULL || objPtr->length < 0
- || objPtr->bytes[objPtr->length] != '\0') {
- Tcl_Panic("UpdateStringProc for type '%s' "
- "failed to create a valid string rep",
- objPtr->typePtr->name);
- }
+ (*objPtr->typePtr->updateStringProc)(objPtr);
}
+
if (lengthPtr != NULL) {
*lengthPtr = objPtr->length;
}
@@ -1724,107 +1686,6 @@ Tcl_GetStringFromObj(
/*
*----------------------------------------------------------------------
*
- * Tcl_InitStringRep --
- *
- * This function is called in several configurations to provide all
- * the tools needed to set an object's string representation. The
- * function is determined by the arguments.
- *
- * (objPtr->bytes != NULL && bytes != NULL) || (numBytes < 0)
- * Invalid call -- panic!
- *
- * objPtr->bytes == NULL && bytes == NULL && numBytes >= 0
- * Allocation only - allocate space for (numBytes+1) chars.
- * store in objPtr->bytes and return. Also sets
- * objPtr->length to 0 and objPtr->bytes[0] to NUL.
- *
- * objPtr->bytes == NULL && bytes != NULL && numBytes >= 0
- * Allocate and copy. bytes is assumed to point to chars to
- * copy into the string rep. objPtr->length = numBytes. Allocate
- * array of (numBytes + 1) chars. store in objPtr->bytes. Copy
- * numBytes chars from bytes to objPtr->bytes; Set
- * objPtr->bytes[numBytes] to NUL and return objPtr->bytes.
- * Caller must guarantee there are numBytes chars at bytes to
- * be copied.
- *
- * objPtr->bytes != NULL && bytes == NULL && numBytes >= 0
- * Truncate. Set objPtr->length to numBytes and
- * objPr->bytes[numBytes] to NUL. Caller has to guarantee
- * that a prior allocating call allocated enough bytes for
- * this to be valid. Return objPtr->bytes.
- *
- * Caller is expected to ascertain that the bytes copied into
- * the string rep make up complete valid UTF-8 characters.
- *
- * Results:
- * A pointer to the string rep of objPtr.
- *
- * Side effects:
- * As described above.
- *
- *----------------------------------------------------------------------
- */
-
-char *
-Tcl_InitStringRep(
- Tcl_Obj *objPtr, /* Object whose string rep is to be set */
- const char *bytes,
- unsigned int numBytes)
-{
- assert(objPtr->bytes == NULL || bytes == NULL);
-
- if (numBytes > INT_MAX) {
- Tcl_Panic("max size for a Tcl value (%d bytes) exceeded", INT_MAX);
- }
-
- if (objPtr->bytes == NULL) {
- /* Start with no string rep */
- if (numBytes == 0) {
- TclInitEmptyStringRep(objPtr);
- return objPtr->bytes;
- } else {
- objPtr->bytes = (char *)attemptckalloc(numBytes + 1);
- if (objPtr->bytes) {
- objPtr->length = (int) numBytes;
- if (bytes) {
- memcpy(objPtr->bytes, bytes, numBytes);
- }
- objPtr->bytes[objPtr->length] = '\0';
- }
- }
- } else if (objPtr->bytes == &tclEmptyString) {
- /* Start with empty string rep (not allocated) */
- if (numBytes == 0) {
- return objPtr->bytes;
- } else {
- objPtr->bytes = (char *)attemptckalloc(numBytes + 1);
- if (objPtr->bytes) {
- objPtr->length = (int) numBytes;
- objPtr->bytes[objPtr->length] = '\0';
- }
- }
- } else {
- /* Start with non-empty string rep (allocated) */
- if (numBytes == 0) {
- ckfree(objPtr->bytes);
- TclInitEmptyStringRep(objPtr);
- return objPtr->bytes;
- } else {
- objPtr->bytes = (char *)attemptckrealloc(objPtr->bytes,
- numBytes + 1);
- if (objPtr->bytes) {
- objPtr->length = (int) numBytes;
- objPtr->bytes[objPtr->length] = '\0';
- }
- }
- }
-
- return objPtr->bytes;
-}
-
-/*
- *----------------------------------------------------------------------
- *
* Tcl_InvalidateStringRep --
*
* This function is called to invalidate an object's string
@@ -1842,122 +1703,12 @@ Tcl_InitStringRep(
void
Tcl_InvalidateStringRep(
- Tcl_Obj *objPtr) /* Object whose string rep byte pointer should
+ register Tcl_Obj *objPtr) /* Object whose string rep byte pointer should
* be freed. */
{
TclInvalidateStringRep(objPtr);
}
-
-/*
- *----------------------------------------------------------------------
- *
- * Tcl_HasStringRep --
- *
- * This function reports whether object has a string representation.
- *
- * Results:
- * Boolean.
- *----------------------------------------------------------------------
- */
-int
-Tcl_HasStringRep(
- Tcl_Obj *objPtr) /* Object to test */
-{
- return TclHasStringRep(objPtr);
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * Tcl_StoreInternalRep --
- *
- * Called to set the object's internal representation to match a
- * particular type.
- *
- * It is the caller's responsibility to guarantee that
- * the value of the submitted internalrep is in agreement with
- * the value of any existing string rep.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Calls the freeIntRepProc of the current Tcl_ObjType, if any.
- * Sets the internalRep and typePtr fields to the submitted values.
- *
- *----------------------------------------------------------------------
- */
-
-void
-Tcl_StoreInternalRep(
- Tcl_Obj *objPtr, /* Object whose internal rep should be set. */
- const Tcl_ObjType *typePtr, /* New type for the object */
- const Tcl_ObjInternalRep *irPtr) /* New internalrep for the object */
-{
- /* Clear out any existing internalrep ( "shimmer" ) */
- TclFreeInternalRep(objPtr);
-
- /* When irPtr == NULL, just leave objPtr with no internalrep for typePtr */
- if (irPtr) {
- /* Copy the new internalrep into place */
- objPtr->internalRep = *irPtr;
-
- /* Set the type to match */
- objPtr->typePtr = typePtr;
- }
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * Tcl_FetchInternalRep --
- *
- * This function is called to retrieve the object's internal
- * representation matching a requested type, if any.
- *
- * Results:
- * A read-only pointer to the associated Tcl_ObjInternalRep, or
- * NULL if no such internal representation exists.
- *
- * Side effects:
- * Calls the freeIntRepProc of the current Tcl_ObjType, if any.
- * Sets the internalRep and typePtr fields to the submitted values.
- *
- *----------------------------------------------------------------------
- */
-
-Tcl_ObjInternalRep *
-Tcl_FetchInternalRep(
- Tcl_Obj *objPtr, /* Object to fetch from. */
- const Tcl_ObjType *typePtr) /* Requested type */
-{
- return TclFetchInternalRep(objPtr, typePtr);
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * Tcl_FreeInternalRep --
- *
- * This function is called to free an object's internal representation.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Calls the freeIntRepProc of the current Tcl_ObjType, if any.
- * Sets typePtr field to NULL.
- *
- *----------------------------------------------------------------------
- */
-
-void
-Tcl_FreeInternalRep(
- Tcl_Obj *objPtr) /* Object whose internal rep should be freed. */
-{
- TclFreeInternalRep(objPtr);
-}
/*
*----------------------------------------------------------------------
@@ -1966,11 +1717,11 @@ Tcl_FreeInternalRep(
*
* This function is normally called when not debugging: i.e., when
* TCL_MEM_DEBUG is not defined. It creates a new Tcl_Obj and
- * initializes it from the argument boolean value. A nonzero "intValue"
+ * initializes it from the argument boolean value. A nonzero "boolValue"
* is coerced to 1.
*
* When TCL_MEM_DEBUG is defined, this function just returns the result
- * of calling the debugging version Tcl_DbNewLongObj.
+ * of calling the debugging version Tcl_DbNewBooleanObj.
*
* Results:
* The newly created object is returned. This object will have an invalid
@@ -1987,20 +1738,20 @@ Tcl_FreeInternalRep(
Tcl_Obj *
Tcl_NewBooleanObj(
- int intValue) /* Boolean used to initialize new object. */
+ register int boolValue) /* Boolean used to initialize new object. */
{
- return Tcl_DbNewWideIntObj(intValue!=0, "unknown", 0);
+ return Tcl_DbNewLongObj(boolValue!=0, "unknown", 0);
}
#else /* if not TCL_MEM_DEBUG */
Tcl_Obj *
Tcl_NewBooleanObj(
- int intValue) /* Boolean used to initialize new object. */
+ register int boolValue) /* Boolean used to initialize new object. */
{
- Tcl_Obj *objPtr;
+ register Tcl_Obj *objPtr;
- TclNewIntObj(objPtr, intValue!=0);
+ TclNewIntObj(objPtr, boolValue!=0);
return objPtr;
}
#endif /* TCL_MEM_DEBUG */
@@ -2031,25 +1782,23 @@ Tcl_NewBooleanObj(
*----------------------------------------------------------------------
*/
-#ifndef TCL_NO_DEPRECATED
#undef Tcl_DbNewBooleanObj
#ifdef TCL_MEM_DEBUG
Tcl_Obj *
Tcl_DbNewBooleanObj(
- int intValue, /* Boolean used to initialize new object. */
- const char *file, /* The name of the source file calling this
+ register int boolValue, /* Boolean used to initialize new object. */
+ CONST char *file, /* The name of the source file calling this
* function; used for debugging. */
int line) /* Line number in the source file; used for
* debugging. */
{
- Tcl_Obj *objPtr;
+ register Tcl_Obj *objPtr;
TclDbNewObj(objPtr, file, line);
- /* Optimized TclInvalidateStringRep() */
objPtr->bytes = NULL;
- objPtr->internalRep.wideValue = (intValue != 0);
+ objPtr->internalRep.longValue = (boolValue? 1 : 0);
objPtr->typePtr = &tclIntType;
return objPtr;
}
@@ -2058,11 +1807,13 @@ Tcl_DbNewBooleanObj(
Tcl_Obj *
Tcl_DbNewBooleanObj(
- int intValue, /* Boolean used to initialize new object. */
- TCL_UNUSED(const char *) /*file*/,
- TCL_UNUSED(int) /*line*/)
+ register int boolValue, /* Boolean used to initialize new object. */
+ CONST char *file, /* The name of the source file calling this
+ * function; used for debugging. */
+ int line) /* Line number in the source file; used for
+ * debugging. */
{
- return Tcl_NewBooleanObj(intValue);
+ return Tcl_NewBooleanObj(boolValue);
}
#endif /* TCL_MEM_DEBUG */
@@ -2072,7 +1823,7 @@ Tcl_DbNewBooleanObj(
* Tcl_SetBooleanObj --
*
* Modify an object to be a boolean object and to have the specified
- * boolean value. A nonzero "intValue" is coerced to 1.
+ * boolean value. A nonzero "boolValue" is coerced to 1.
*
* Results:
* None.
@@ -2087,21 +1838,20 @@ Tcl_DbNewBooleanObj(
#undef Tcl_SetBooleanObj
void
Tcl_SetBooleanObj(
- Tcl_Obj *objPtr, /* Object whose internal rep to init. */
- int intValue) /* Boolean used to set object's value. */
+ register Tcl_Obj *objPtr, /* Object whose internal rep to init. */
+ register int boolValue) /* Boolean used to set object's value. */
{
if (Tcl_IsShared(objPtr)) {
Tcl_Panic("%s called with shared object", "Tcl_SetBooleanObj");
}
- TclSetIntObj(objPtr, intValue!=0);
+ TclSetIntObj(objPtr, boolValue!=0);
}
-#endif /* TCL_NO_DEPRECATED */
/*
*----------------------------------------------------------------------
*
- * Tcl_GetBoolFromObj, Tcl_GetBooleanFromObj --
+ * Tcl_GetBooleanFromObj --
*
* Attempt to return a boolean from the Tcl object "objPtr". This
* includes conversion from any of Tcl's numeric types.
@@ -2112,99 +1862,62 @@ Tcl_SetBooleanObj(
* result unless "interp" is NULL.
*
* Side effects:
- * The internalrep of *objPtr may be changed.
+ * The intrep of *objPtr may be changed.
*
*----------------------------------------------------------------------
*/
-#undef Tcl_GetBoolFromObj
int
-Tcl_GetBoolFromObj(
- Tcl_Interp *interp, /* Used for error reporting if not NULL. */
- Tcl_Obj *objPtr, /* The object from which to get boolean. */
- int flags,
- char *charPtr) /* Place to store resulting boolean. */
+Tcl_GetBooleanFromObj(
+ Tcl_Interp *interp, /* Used for error reporting if not NULL. */
+ register Tcl_Obj *objPtr, /* The object from which to get boolean. */
+ register int *boolPtr) /* Place to store resulting boolean. */
{
- int result;
-
- if ((flags & TCL_NULL_OK) && (objPtr == NULL || Tcl_GetString(objPtr)[0] == '\0')) {
- result = -1;
- goto boolEnd;
- } else if (objPtr == NULL) {
- if (interp) {
- TclNewObj(objPtr);
- TclParseNumber(interp, objPtr, (flags & TCL_NULL_OK)
- ? "boolean value or \"\"" : "boolean value", NULL, TCL_INDEX_NONE, NULL, 0);
- Tcl_DecrRefCount(objPtr);
- }
- return TCL_ERROR;
- }
do {
if (objPtr->typePtr == &tclIntType) {
- result = (objPtr->internalRep.wideValue != 0);
- goto boolEnd;
+ *boolPtr = (objPtr->internalRep.longValue != 0);
+ return TCL_OK;
}
if (objPtr->typePtr == &tclBooleanType) {
- result = objPtr->internalRep.longValue != 0;
- goto boolEnd;
+ *boolPtr = (int) objPtr->internalRep.longValue;
+ return TCL_OK;
}
if (objPtr->typePtr == &tclDoubleType) {
/*
* Caution: Don't be tempted to check directly for the "double"
- * Tcl_ObjType and then compare the internalrep to 0.0. This isn't
+ * Tcl_ObjType and then compare the intrep to 0.0. This isn't
* reliable because a "double" Tcl_ObjType can hold the NaN value.
* Use the API Tcl_GetDoubleFromObj, which does the checking and
* sets the proper error message for us.
*/
- double d;
+ double d;
if (Tcl_GetDoubleFromObj(interp, objPtr, &d) != TCL_OK) {
return TCL_ERROR;
}
- result = (d != 0.0);
- goto boolEnd;
+ *boolPtr = (d != 0.0);
+ return TCL_OK;
}
if (objPtr->typePtr == &tclBignumType) {
- result = 1;
- boolEnd:
- if (charPtr != NULL) {
- flags &= (TCL_NULL_OK-2);
- if (flags) {
- if (flags == (int)sizeof(int)) {
- *(int *)charPtr = result;
- return TCL_OK;
- } else if (flags == (int)sizeof(short)) {
- *(short *)charPtr = result;
- return TCL_OK;
- } else {
- Tcl_Panic("Wrong bool var for %s", "Tcl_GetBoolFromObj");
- }
- }
- *charPtr = result;
- }
+ *boolPtr = 1;
+ return TCL_OK;
+ }
+#ifndef NO_WIDE_TYPE
+ if (objPtr->typePtr == &tclWideIntType) {
+ *boolPtr = (objPtr->internalRep.wideValue != 0);
return TCL_OK;
}
+#endif
} while ((ParseBoolean(objPtr) == TCL_OK) || (TCL_OK ==
- TclParseNumber(interp, objPtr, (flags & TCL_NULL_OK)
- ? "boolean value or \"\"" : "boolean value", NULL,-1,NULL,0)));
+ TclParseNumber(interp, objPtr, "boolean value", NULL,-1,NULL,0)));
return TCL_ERROR;
}
-#undef Tcl_GetBooleanFromObj
-int
-Tcl_GetBooleanFromObj(
- Tcl_Interp *interp, /* Used for error reporting if not NULL. */
- Tcl_Obj *objPtr, /* The object from which to get boolean. */
- int *intPtr) /* Place to store resulting boolean. */
-{
- return Tcl_GetBoolFromObj(interp, objPtr, (TCL_NULL_OK-2)&(int)sizeof(int), (char *)(void *)intPtr);
-}
-
/*
*----------------------------------------------------------------------
*
- * TclSetBooleanFromAny --
+ * SetBooleanFromAny --
*
* Attempt to generate a boolean internal form for the Tcl object
* "objPtr".
@@ -2216,20 +1929,15 @@ Tcl_GetBooleanFromObj(
*
* Side effects:
* If no error occurs, an integer 1 or 0 is stored as "objPtr"s internal
- * representation and the type of "objPtr" is set to boolean or int/wideInt.
- *
- * Warning: If the returned type is "wideInt" (32-bit platforms) and your
- * platform is bigendian, you cannot use internalRep.longValue to distinguish
- * between false and true. On Windows and most other platforms this still will
- * work fine, but basically it is non-portable.
+ * representation and the type of "objPtr" is set to boolean.
*
*----------------------------------------------------------------------
*/
-int
-TclSetBooleanFromAny(
+static int
+SetBooleanFromAny(
Tcl_Interp *interp, /* Used for error reporting if not NULL. */
- Tcl_Obj *objPtr) /* The object to convert. */
+ register Tcl_Obj *objPtr) /* The object to convert. */
{
/*
* For some "pure" numeric Tcl_ObjTypes (no string rep), we can determine
@@ -2239,7 +1947,8 @@ TclSetBooleanFromAny(
if (objPtr->bytes == NULL) {
if (objPtr->typePtr == &tclIntType) {
- if ((Tcl_WideUInt)objPtr->internalRep.wideValue < 2) {
+ switch (objPtr->internalRep.longValue) {
+ case 0L: case 1L:
return TCL_OK;
}
goto badBoolean;
@@ -2249,6 +1958,12 @@ TclSetBooleanFromAny(
goto badBoolean;
}
+#ifndef NO_WIDE_TYPE
+ if (objPtr->typePtr == &tclWideIntType) {
+ goto badBoolean;
+ }
+#endif
+
if (objPtr->typePtr == &tclDoubleType) {
goto badBoolean;
}
@@ -2260,33 +1975,27 @@ TclSetBooleanFromAny(
badBoolean:
if (interp != NULL) {
- Tcl_Size length;
- const char *str = Tcl_GetStringFromObj(objPtr, &length);
+ int length;
+ char *str = Tcl_GetStringFromObj(objPtr, &length);
Tcl_Obj *msg;
TclNewLiteralStringObj(msg, "expected boolean value but got \"");
Tcl_AppendLimitedToObj(msg, str, length, 50, "");
Tcl_AppendToObj(msg, "\"", -1);
Tcl_SetObjResult(interp, msg);
- Tcl_SetErrorCode(interp, "TCL", "VALUE", "BOOLEAN", (void *)NULL);
}
return TCL_ERROR;
}
static int
ParseBoolean(
- Tcl_Obj *objPtr) /* The object to parse/convert. */
+ register Tcl_Obj *objPtr) /* The object to parse/convert. */
{
- int newBool;
- char lowerCase[6];
- Tcl_Size i, length;
- const char *str = Tcl_GetStringFromObj(objPtr, &length);
-
- if ((length < 1) || (length > 5)) {
- /*
- * Longest valid boolean string rep. is "false".
- */
+ int i, length, newBool;
+ char lowerCase[6], *str = TclGetStringFromObj(objPtr, &length);
+ if ((length == 0) || (length > 5)) {
+ /* longest valid boolean string rep. is "false" */
return TCL_ERROR;
}
@@ -2312,7 +2021,6 @@ ParseBoolean(
for (i=0; i < length; i++) {
char c = str[i];
-
switch (c) {
case 'A': case 'E': case 'F': case 'L': case 'N':
case 'O': case 'R': case 'S': case 'T': case 'U': case 'Y':
@@ -2332,25 +2040,25 @@ ParseBoolean(
/*
* Checking the 'y' is redundant, but makes the code clearer.
*/
- if (strncmp(lowerCase, "yes", length) == 0) {
+ if (strncmp(lowerCase, "yes", (size_t) length) == 0) {
newBool = 1;
goto goodBoolean;
}
return TCL_ERROR;
case 'n':
- if (strncmp(lowerCase, "no", length) == 0) {
+ if (strncmp(lowerCase, "no", (size_t) length) == 0) {
newBool = 0;
goto goodBoolean;
}
return TCL_ERROR;
case 't':
- if (strncmp(lowerCase, "true", length) == 0) {
+ if (strncmp(lowerCase, "true", (size_t) length) == 0) {
newBool = 1;
goto goodBoolean;
}
return TCL_ERROR;
case 'f':
- if (strncmp(lowerCase, "false", length) == 0) {
+ if (strncmp(lowerCase, "false", (size_t) length) == 0) {
newBool = 0;
goto goodBoolean;
}
@@ -2359,10 +2067,10 @@ ParseBoolean(
if (length < 2) {
return TCL_ERROR;
}
- if (strncmp(lowerCase, "on", length) == 0) {
+ if (strncmp(lowerCase, "on", (size_t) length) == 0) {
newBool = 1;
goto goodBoolean;
- } else if (strncmp(lowerCase, "off", length) == 0) {
+ } else if (strncmp(lowerCase, "off", (size_t) length) == 0) {
newBool = 0;
goto goodBoolean;
}
@@ -2378,14 +2086,14 @@ ParseBoolean(
*/
goodBoolean:
- TclFreeInternalRep(objPtr);
+ TclFreeIntRep(objPtr);
objPtr->internalRep.longValue = newBool;
objPtr->typePtr = &tclBooleanType;
return TCL_OK;
numericBoolean:
- TclFreeInternalRep(objPtr);
- objPtr->internalRep.wideValue = newBool;
+ TclFreeIntRep(objPtr);
+ objPtr->internalRep.longValue = newBool;
objPtr->typePtr = &tclIntType;
return TCL_OK;
}
@@ -2417,7 +2125,7 @@ ParseBoolean(
Tcl_Obj *
Tcl_NewDoubleObj(
- double dblValue) /* Double used to initialize the object. */
+ register double dblValue) /* Double used to initialize the object. */
{
return Tcl_DbNewDoubleObj(dblValue, "unknown", 0);
}
@@ -2426,9 +2134,9 @@ Tcl_NewDoubleObj(
Tcl_Obj *
Tcl_NewDoubleObj(
- double dblValue) /* Double used to initialize the object. */
+ register double dblValue) /* Double used to initialize the object. */
{
- Tcl_Obj *objPtr;
+ register Tcl_Obj *objPtr;
TclNewDoubleObj(objPtr, dblValue);
return objPtr;
@@ -2465,16 +2173,15 @@ Tcl_NewDoubleObj(
Tcl_Obj *
Tcl_DbNewDoubleObj(
- double dblValue, /* Double used to initialize the object. */
- const char *file, /* The name of the source file calling this
+ register double dblValue, /* Double used to initialize the object. */
+ CONST char *file, /* The name of the source file calling this
* function; used for debugging. */
int line) /* Line number in the source file; used for
* debugging. */
{
- Tcl_Obj *objPtr;
+ register Tcl_Obj *objPtr;
TclDbNewObj(objPtr, file, line);
- /* Optimized TclInvalidateStringRep() */
objPtr->bytes = NULL;
objPtr->internalRep.doubleValue = dblValue;
@@ -2486,9 +2193,11 @@ Tcl_DbNewDoubleObj(
Tcl_Obj *
Tcl_DbNewDoubleObj(
- double dblValue, /* Double used to initialize the object. */
- TCL_UNUSED(const char *) /*file*/,
- TCL_UNUSED(int) /*line*/)
+ register double dblValue, /* Double used to initialize the object. */
+ CONST char *file, /* The name of the source file calling this
+ * function; used for debugging. */
+ int line) /* Line number in the source file; used for
+ * debugging. */
{
return Tcl_NewDoubleObj(dblValue);
}
@@ -2514,8 +2223,8 @@ Tcl_DbNewDoubleObj(
void
Tcl_SetDoubleObj(
- Tcl_Obj *objPtr, /* Object whose internal rep to init. */
- double dblValue) /* Double used to set the object's value. */
+ register Tcl_Obj *objPtr, /* Object whose internal rep to init. */
+ register double dblValue) /* Double used to set the object's value. */
{
if (Tcl_IsShared(objPtr)) {
Tcl_Panic("%s called with shared object", "Tcl_SetDoubleObj");
@@ -2546,18 +2255,16 @@ Tcl_SetDoubleObj(
int
Tcl_GetDoubleFromObj(
- Tcl_Interp *interp, /* Used for error reporting if not NULL. */
- Tcl_Obj *objPtr, /* The object from which to get a double. */
- double *dblPtr) /* Place to store resulting double. */
+ Tcl_Interp *interp, /* Used for error reporting if not NULL. */
+ register Tcl_Obj *objPtr, /* The object from which to get a double. */
+ register double *dblPtr) /* Place to store resulting double. */
{
do {
if (objPtr->typePtr == &tclDoubleType) {
- if (isnan(objPtr->internalRep.doubleValue)) {
+ if (TclIsNaN(objPtr->internalRep.doubleValue)) {
if (interp != NULL) {
Tcl_SetObjResult(interp, Tcl_NewStringObj(
"floating point value is Not a Number", -1));
- Tcl_SetErrorCode(interp, "TCL", "VALUE", "DOUBLE", "NAN",
- (void *)NULL);
}
return TCL_ERROR;
}
@@ -2565,16 +2272,21 @@ Tcl_GetDoubleFromObj(
return TCL_OK;
}
if (objPtr->typePtr == &tclIntType) {
- *dblPtr = (double) objPtr->internalRep.wideValue;
+ *dblPtr = objPtr->internalRep.longValue;
return TCL_OK;
}
if (objPtr->typePtr == &tclBignumType) {
mp_int big;
-
- TclUnpackBignum(objPtr, big);
- *dblPtr = TclBignumToDouble(&big);
+ UNPACK_BIGNUM( objPtr, big );
+ *dblPtr = TclBignumToDouble( &big );
+ return TCL_OK;
+ }
+#ifndef NO_WIDE_TYPE
+ if (objPtr->typePtr == &tclWideIntType) {
+ *dblPtr = (double) objPtr->internalRep.wideValue;
return TCL_OK;
}
+#endif
} while (SetDoubleFromAny(interp, objPtr) == TCL_OK);
return TCL_ERROR;
}
@@ -2602,7 +2314,7 @@ Tcl_GetDoubleFromObj(
static int
SetDoubleFromAny(
Tcl_Interp *interp, /* Used for error reporting if not NULL. */
- Tcl_Obj *objPtr) /* The object to convert. */
+ register Tcl_Obj *objPtr) /* The object to convert. */
{
return TclParseNumber(interp, objPtr, "floating-point number", NULL, -1,
NULL, 0);
@@ -2631,14 +2343,17 @@ SetDoubleFromAny(
static void
UpdateStringOfDouble(
- Tcl_Obj *objPtr) /* Double obj with string rep to update. */
+ register Tcl_Obj *objPtr) /* Double obj with string rep to update. */
{
- char *dst = Tcl_InitStringRep(objPtr, NULL, TCL_DOUBLE_SPACE);
+ char buffer[TCL_DOUBLE_SPACE];
+ register int len;
- TclOOM(dst, TCL_DOUBLE_SPACE + 1);
+ Tcl_PrintDouble(NULL, objPtr->internalRep.doubleValue, buffer);
+ len = strlen(buffer);
- Tcl_PrintDouble(NULL, objPtr->internalRep.doubleValue, dst);
- (void) Tcl_InitStringRep(objPtr, NULL, strlen(dst));
+ objPtr->bytes = (char *) ckalloc((unsigned) len + 1);
+ strcpy(objPtr->bytes, buffer);
+ objPtr->length = len;
}
/*
@@ -2671,30 +2386,28 @@ UpdateStringOfDouble(
*----------------------------------------------------------------------
*/
-#ifndef TCL_NO_DEPRECATED
-#undef Tcl_NewIntObj
#ifdef TCL_MEM_DEBUG
+#undef Tcl_NewIntObj
Tcl_Obj *
Tcl_NewIntObj(
- int intValue) /* Int used to initialize the new object. */
+ register int intValue) /* Int used to initialize the new object. */
{
- return Tcl_DbNewWideIntObj(intValue, "unknown", 0);
+ return Tcl_DbNewLongObj((long)intValue, "unknown", 0);
}
#else /* if not TCL_MEM_DEBUG */
Tcl_Obj *
Tcl_NewIntObj(
- int intValue) /* Int used to initialize the new object. */
+ register int intValue) /* Int used to initialize the new object. */
{
- Tcl_Obj *objPtr;
+ register Tcl_Obj *objPtr;
TclNewIntObj(objPtr, intValue);
return objPtr;
}
#endif /* if TCL_MEM_DEBUG */
-#endif /* TCL_NO_DEPRECATED */
/*
*----------------------------------------------------------------------
@@ -2713,12 +2426,11 @@ Tcl_NewIntObj(
*
*----------------------------------------------------------------------
*/
-#ifndef TCL_NO_DEPRECATED
-#undef Tcl_SetIntObj
+
void
Tcl_SetIntObj(
- Tcl_Obj *objPtr, /* Object whose internal rep to init. */
- int intValue) /* Integer used to set object's value. */
+ register Tcl_Obj *objPtr, /* Object whose internal rep to init. */
+ register int intValue) /* Integer used to set object's value. */
{
if (Tcl_IsShared(objPtr)) {
Tcl_Panic("%s called with shared object", "Tcl_SetIntObj");
@@ -2726,7 +2438,6 @@ Tcl_SetIntObj(
TclSetIntObj(objPtr, intValue);
}
-#endif /* TCL_NO_DEPRECATED */
/*
*----------------------------------------------------------------------
@@ -2756,9 +2467,9 @@ Tcl_SetIntObj(
int
Tcl_GetIntFromObj(
- Tcl_Interp *interp, /* Used for error reporting if not NULL. */
- Tcl_Obj *objPtr, /* The object from which to get a int. */
- int *intPtr) /* Place to store resulting int. */
+ Tcl_Interp *interp, /* Used for error reporting if not NULL. */
+ register Tcl_Obj *objPtr, /* The object from which to get a int. */
+ register int *intPtr) /* Place to store resulting int. */
{
#if (LONG_MAX == INT_MAX)
return TclGetLongFromObj(interp, objPtr, (long *) intPtr);
@@ -2768,12 +2479,12 @@ Tcl_GetIntFromObj(
if (TclGetLongFromObj(interp, objPtr, &l) != TCL_OK) {
return TCL_ERROR;
}
- if ((ULONG_MAX > UINT_MAX) && ((l > UINT_MAX) || (l < INT_MIN))) {
+ if ((ULONG_MAX > UINT_MAX) && ((l > UINT_MAX) || (l < -(long)UINT_MAX))) {
if (interp != NULL) {
- const char *s =
- "integer value too large to represent";
+ CONST char *s =
+ "integer value too large to represent as non-long integer";
Tcl_SetObjResult(interp, Tcl_NewStringObj(s, -1));
- Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW", s, (void *)NULL);
+ Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW", s, NULL);
}
return TCL_ERROR;
}
@@ -2781,7 +2492,6 @@ Tcl_GetIntFromObj(
return TCL_OK;
#endif
}
-
/*
*----------------------------------------------------------------------
@@ -2804,8 +2514,8 @@ SetIntFromAny(
Tcl_Interp *interp, /* Tcl interpreter */
Tcl_Obj *objPtr) /* Pointer to the object to convert */
{
- Tcl_WideInt w;
- return Tcl_GetWideIntFromObj(interp, objPtr, &w);
+ long l;
+ return TclGetLongFromObj(interp, objPtr, &l);
}
/*
@@ -2829,27 +2539,17 @@ SetIntFromAny(
static void
UpdateStringOfInt(
- Tcl_Obj *objPtr) /* Int object whose string rep to update. */
+ register Tcl_Obj *objPtr) /* Int object whose string rep to update. */
{
- char *dst = Tcl_InitStringRep( objPtr, NULL, TCL_INTEGER_SPACE);
+ char buffer[TCL_INTEGER_SPACE];
+ register int len;
- TclOOM(dst, TCL_INTEGER_SPACE + 1);
- (void) Tcl_InitStringRep(objPtr, NULL,
- TclFormatInt(dst, objPtr->internalRep.wideValue));
-}
+ len = TclFormatInt(buffer, objPtr->internalRep.longValue);
-#if !defined(TCL_NO_DEPRECATED) && TCL_MAJOR_VERSION < 9 && !defined(TCL_WIDE_INT_IS_LONG)
-static void
-UpdateStringOfOldInt(
- Tcl_Obj *objPtr) /* Int object whose string rep to update. */
-{
- char *dst = Tcl_InitStringRep( objPtr, NULL, TCL_INTEGER_SPACE);
-
- TclOOM(dst, TCL_INTEGER_SPACE + 1);
- (void) Tcl_InitStringRep(objPtr, NULL,
- TclFormatInt(dst, objPtr->internalRep.longValue));
+ objPtr->bytes = ckalloc((unsigned) len + 1);
+ strcpy(objPtr->bytes, buffer);
+ objPtr->length = len;
}
-#endif
/*
*----------------------------------------------------------------------
@@ -2881,32 +2581,30 @@ UpdateStringOfOldInt(
*----------------------------------------------------------------------
*/
-#ifndef TCL_NO_DEPRECATED
-#undef Tcl_NewLongObj
#ifdef TCL_MEM_DEBUG
+#undef Tcl_NewLongObj
Tcl_Obj *
Tcl_NewLongObj(
- long longValue) /* Long integer used to initialize the
+ register long longValue) /* Long integer used to initialize the
* new object. */
{
- return Tcl_DbNewWideIntObj(longValue, "unknown", 0);
+ return Tcl_DbNewLongObj(longValue, "unknown", 0);
}
#else /* if not TCL_MEM_DEBUG */
Tcl_Obj *
Tcl_NewLongObj(
- long longValue) /* Long integer used to initialize the
+ register long longValue) /* Long integer used to initialize the
* new object. */
{
- Tcl_Obj *objPtr;
+ register Tcl_Obj *objPtr;
- TclNewIntObj(objPtr, longValue);
+ TclNewLongObj(objPtr, longValue);
return objPtr;
}
#endif /* if TCL_MEM_DEBUG */
-#endif /* TCL_NO_DEPRECATED */
/*
*----------------------------------------------------------------------
@@ -2940,26 +2638,23 @@ Tcl_NewLongObj(
*----------------------------------------------------------------------
*/
-#ifndef TCL_NO_DEPRECATED
-#undef Tcl_DbNewLongObj
#ifdef TCL_MEM_DEBUG
Tcl_Obj *
Tcl_DbNewLongObj(
- long longValue, /* Long integer used to initialize the new
+ register long longValue, /* Long integer used to initialize the new
* object. */
- const char *file, /* The name of the source file calling this
+ CONST char *file, /* The name of the source file calling this
* function; used for debugging. */
int line) /* Line number in the source file; used for
* debugging. */
{
- Tcl_Obj *objPtr;
+ register Tcl_Obj *objPtr;
TclDbNewObj(objPtr, file, line);
- /* Optimized TclInvalidateStringRep */
objPtr->bytes = NULL;
- objPtr->internalRep.wideValue = longValue;
+ objPtr->internalRep.longValue = longValue;
objPtr->typePtr = &tclIntType;
return objPtr;
}
@@ -2968,15 +2663,16 @@ Tcl_DbNewLongObj(
Tcl_Obj *
Tcl_DbNewLongObj(
- long longValue, /* Long integer used to initialize the new
+ register long longValue, /* Long integer used to initialize the new
* object. */
- TCL_UNUSED(const char *) /*file*/,
- TCL_UNUSED(int) /*line*/)
+ CONST char *file, /* The name of the source file calling this
+ * function; used for debugging. */
+ int line) /* Line number in the source file; used for
+ * debugging. */
{
- return Tcl_NewWideIntObj(longValue);
+ return Tcl_NewLongObj(longValue);
}
#endif /* TCL_MEM_DEBUG */
-#endif /* TCL_NO_DEPRECATED */
/*
*----------------------------------------------------------------------
@@ -2996,21 +2692,18 @@ Tcl_DbNewLongObj(
*----------------------------------------------------------------------
*/
-#ifndef TCL_NO_DEPRECATED
-#undef Tcl_SetLongObj
void
Tcl_SetLongObj(
- Tcl_Obj *objPtr, /* Object whose internal rep to init. */
- long longValue) /* Long integer used to initialize the
+ register Tcl_Obj *objPtr, /* Object whose internal rep to init. */
+ register long longValue) /* Long integer used to initialize the
* object's value. */
{
if (Tcl_IsShared(objPtr)) {
Tcl_Panic("%s called with shared object", "Tcl_SetLongObj");
}
- TclSetIntObj(objPtr, longValue);
+ TclSetLongObj(objPtr, longValue);
}
-#endif /* TCL_NO_DEPRECATED */
/*
*----------------------------------------------------------------------
@@ -3035,20 +2728,19 @@ Tcl_SetLongObj(
int
Tcl_GetLongFromObj(
- Tcl_Interp *interp, /* Used for error reporting if not NULL. */
- Tcl_Obj *objPtr, /* The object from which to get a long. */
- long *longPtr) /* Place to store resulting long. */
+ Tcl_Interp *interp, /* Used for error reporting if not NULL. */
+ register Tcl_Obj *objPtr, /* The object from which to get a long. */
+ register long *longPtr) /* Place to store resulting long. */
{
do {
-#ifdef TCL_WIDE_INT_IS_LONG
if (objPtr->typePtr == &tclIntType) {
- *longPtr = objPtr->internalRep.wideValue;
+ *longPtr = objPtr->internalRep.longValue;
return TCL_OK;
}
-#else
- if (objPtr->typePtr == &tclIntType) {
+#ifndef NO_WIDE_TYPE
+ if (objPtr->typePtr == &tclWideIntType) {
/*
- * We return any integer in the range LONG_MIN to ULONG_MAX
+ * We return any integer in the range -ULONG_MAX to ULONG_MAX
* converted to a long, ignoring overflow. The rule preserves
* existing semantics for conversion of integers on input, but
* avoids inadvertent demotion of wide integers to 32-bit ones in
@@ -3056,25 +2748,26 @@ Tcl_GetLongFromObj(
*/
Tcl_WideInt w = objPtr->internalRep.wideValue;
-
- if (w >= (Tcl_WideInt)(LONG_MIN)
+ if (w >= -(Tcl_WideInt)(ULONG_MAX)
&& w <= (Tcl_WideInt)(ULONG_MAX)) {
- *longPtr = (long)w;
+ *longPtr = Tcl_WideAsLong(w);
return TCL_OK;
}
goto tooLarge;
}
#endif
- if (objPtr->typePtr == &tclDoubleType) {
- if (interp != NULL) {
- Tcl_SetObjResult(interp, Tcl_ObjPrintf(
- "expected integer but got \"%s\"",
- TclGetString(objPtr)));
- Tcl_SetErrorCode(interp, "TCL", "VALUE", "INTEGER", (void *)NULL);
+ if (objPtr->typePtr == &tclDoubleType) {
+ if (interp != NULL) {
+ Tcl_Obj *msg;
+
+ TclNewLiteralStringObj(msg, "expected integer but got \"");
+ Tcl_AppendObjToObj(msg, objPtr);
+ Tcl_AppendToObj(msg, "\"", -1);
+ Tcl_SetObjResult(interp, msg);
}
return TCL_ERROR;
}
- if (objPtr->typePtr == &tclBignumType) {
+ if (objPtr->typePtr == &tclBignumType) {
/*
* Must check for those bignum values that can fit in a long, even
* when auto-narrowing is enabled. Only those values in the signed
@@ -3082,31 +2775,27 @@ Tcl_GetLongFromObj(
* values in the unsigned long range will fit in a long.
*/
- {
mp_int big;
- unsigned long scratch, value = 0;
- unsigned char *bytes = (unsigned char *) &scratch;
- size_t numBytes;
- TclUnpackBignum(objPtr, big);
- if (mp_to_ubin(&big, bytes, sizeof(long), &numBytes) == MP_OKAY) {
- while (numBytes-- > 0) {
+ UNPACK_BIGNUM(objPtr, big);
+ if ((size_t)(big.used) <= (CHAR_BIT * sizeof(long) + DIGIT_BIT - 1)
+ / DIGIT_BIT) {
+ unsigned long value = 0, numBytes = sizeof(long);
+ long scratch;
+ unsigned char *bytes = (unsigned char *)&scratch;
+ if (mp_to_unsigned_bin_n(&big, bytes, &numBytes) == MP_OKAY) {
+ while (numBytes-- > 0) {
value = (value << CHAR_BIT) | *bytes++;
- }
- if (big.sign) {
- if (value <= 1 + (unsigned long)LONG_MAX) {
- *longPtr = (long)(-value);
- return TCL_OK;
}
- } else {
- if (value <= (unsigned long)ULONG_MAX) {
- *longPtr = (long)value;
- return TCL_OK;
+ if (big.sign) {
+ *longPtr = - (long) value;
+ } else {
+ *longPtr = (long) value;
}
+ return TCL_OK;
}
}
- }
-#ifndef TCL_WIDE_INT_IS_LONG
+#ifndef NO_WIDE_TYPE
tooLarge:
#endif
if (interp != NULL) {
@@ -3114,7 +2803,7 @@ Tcl_GetLongFromObj(
Tcl_Obj *msg = Tcl_NewStringObj(s, -1);
Tcl_SetObjResult(interp, msg);
- Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW", s, (void *)NULL);
+ Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW", s, NULL);
}
return TCL_ERROR;
}
@@ -3122,6 +2811,49 @@ Tcl_GetLongFromObj(
TCL_PARSE_INTEGER_ONLY)==TCL_OK);
return TCL_ERROR;
}
+#ifndef NO_WIDE_TYPE
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * UpdateStringOfWideInt --
+ *
+ * Update the string representation for a wide integer object. Note: this
+ * function does not free an existing old string rep so storage will be
+ * lost if this has not already been done.
+ *
+ * Results:
+ * None.
+ *
+ * Side effects:
+ * The object's string is set to a valid string that results from the
+ * wideInt-to-string conversion.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static void
+UpdateStringOfWideInt(
+ register Tcl_Obj *objPtr) /* Int object whose string rep to update. */
+{
+ char buffer[TCL_INTEGER_SPACE+2];
+ register unsigned len;
+ register Tcl_WideInt wideVal = objPtr->internalRep.wideValue;
+
+ /*
+ * Note that sprintf will generate a compiler warning under Mingw claiming
+ * %I64 is an unknown format specifier. Just ignore this warning. We can't
+ * use %L as the format specifier since that gets printed as a 32 bit
+ * value.
+ */
+
+ sprintf(buffer, "%" TCL_LL_MODIFIER "d", wideVal);
+ len = strlen(buffer);
+ objPtr->bytes = ckalloc((unsigned) len + 1);
+ memcpy(objPtr->bytes, buffer, len + 1);
+ objPtr->length = len;
+}
+#endif /* !NO_WIDE_TYPE */
/*
*----------------------------------------------------------------------
@@ -3153,7 +2885,7 @@ Tcl_GetLongFromObj(
Tcl_Obj *
Tcl_NewWideIntObj(
- Tcl_WideInt wideValue)
+ register Tcl_WideInt wideValue)
/* Wide integer used to initialize the new
* object. */
{
@@ -3164,14 +2896,14 @@ Tcl_NewWideIntObj(
Tcl_Obj *
Tcl_NewWideIntObj(
- Tcl_WideInt wideValue)
+ register Tcl_WideInt wideValue)
/* Wide integer used to initialize the new
* object. */
{
- Tcl_Obj *objPtr;
+ register Tcl_Obj *objPtr;
TclNewObj(objPtr);
- TclSetIntObj(objPtr, wideValue);
+ Tcl_SetWideIntObj(objPtr, wideValue);
return objPtr;
}
#endif /* if TCL_MEM_DEBUG */
@@ -3212,18 +2944,18 @@ Tcl_NewWideIntObj(
Tcl_Obj *
Tcl_DbNewWideIntObj(
- Tcl_WideInt wideValue,
+ register Tcl_WideInt wideValue,
/* Wide integer used to initialize the new
* object. */
- const char *file, /* The name of the source file calling this
+ CONST char *file, /* The name of the source file calling this
* function; used for debugging. */
int line) /* Line number in the source file; used for
* debugging. */
{
- Tcl_Obj *objPtr;
+ register Tcl_Obj *objPtr;
TclDbNewObj(objPtr, file, line);
- TclSetIntObj(objPtr, wideValue);
+ Tcl_SetWideIntObj(objPtr, wideValue);
return objPtr;
}
@@ -3231,11 +2963,13 @@ Tcl_DbNewWideIntObj(
Tcl_Obj *
Tcl_DbNewWideIntObj(
- Tcl_WideInt wideValue,
+ register Tcl_WideInt wideValue,
/* Long integer used to initialize the new
* object. */
- TCL_UNUSED(const char *) /*file*/,
- TCL_UNUSED(int) /*line*/)
+ CONST char *file, /* The name of the source file calling this
+ * function; used for debugging. */
+ int line) /* Line number in the source file; used for
+ * debugging. */
{
return Tcl_NewWideIntObj(wideValue);
}
@@ -3261,8 +2995,8 @@ Tcl_DbNewWideIntObj(
void
Tcl_SetWideIntObj(
- Tcl_Obj *objPtr, /* Object w. internal rep to init. */
- Tcl_WideInt wideValue)
+ register Tcl_Obj *objPtr, /* Object w. internal rep to init. */
+ register Tcl_WideInt wideValue)
/* Wide integer used to initialize the
* object's value. */
{
@@ -3270,7 +3004,19 @@ Tcl_SetWideIntObj(
Tcl_Panic("%s called with shared object", "Tcl_SetWideIntObj");
}
- TclSetIntObj(objPtr, wideValue);
+ if ((wideValue >= (Tcl_WideInt) LONG_MIN)
+ && (wideValue <= (Tcl_WideInt) LONG_MAX)) {
+ TclSetLongObj(objPtr, (long) wideValue);
+ } else {
+#ifndef NO_WIDE_TYPE
+ TclSetWideIntObj(objPtr, wideValue);
+#else
+ mp_int big;
+
+ TclBNInitBignumFromWideInt(&big, wideValue);
+ Tcl_SetBignumObj(objPtr, &big);
+#endif
+ }
}
/*
@@ -3296,60 +3042,67 @@ Tcl_SetWideIntObj(
int
Tcl_GetWideIntFromObj(
- Tcl_Interp *interp, /* Used for error reporting if not NULL. */
- Tcl_Obj *objPtr, /* Object from which to get a wide int. */
- Tcl_WideInt *wideIntPtr)
+ Tcl_Interp *interp, /* Used for error reporting if not NULL. */
+ register Tcl_Obj *objPtr, /* Object from which to get a wide int. */
+ register Tcl_WideInt *wideIntPtr)
/* Place to store resulting long. */
{
do {
- if (objPtr->typePtr == &tclIntType) {
+#ifndef NO_WIDE_TYPE
+ if (objPtr->typePtr == &tclWideIntType) {
*wideIntPtr = objPtr->internalRep.wideValue;
return TCL_OK;
}
- if (objPtr->typePtr == &tclDoubleType) {
- if (interp != NULL) {
- Tcl_SetObjResult(interp, Tcl_ObjPrintf(
- "expected integer but got \"%s\"",
- TclGetString(objPtr)));
- Tcl_SetErrorCode(interp, "TCL", "VALUE", "INTEGER", (void *)NULL);
+#endif
+ if (objPtr->typePtr == &tclIntType) {
+ *wideIntPtr = (Tcl_WideInt) objPtr->internalRep.longValue;
+ return TCL_OK;
+ }
+ if (objPtr->typePtr == &tclDoubleType) {
+ if (interp != NULL) {
+ Tcl_Obj *msg;
+
+ TclNewLiteralStringObj(msg, "expected integer but got \"");
+ Tcl_AppendObjToObj(msg, objPtr);
+ Tcl_AppendToObj(msg, "\"", -1);
+ Tcl_SetObjResult(interp, msg);
}
return TCL_ERROR;
}
- if (objPtr->typePtr == &tclBignumType) {
+ if (objPtr->typePtr == &tclBignumType) {
/*
* Must check for those bignum values that can fit in a
* Tcl_WideInt, even when auto-narrowing is enabled.
*/
mp_int big;
- Tcl_WideUInt value = 0;
- size_t numBytes;
- Tcl_WideInt scratch;
- unsigned char *bytes = (unsigned char *) &scratch;
-
- TclUnpackBignum(objPtr, big);
- if (mp_to_ubin(&big, bytes, sizeof(Tcl_WideInt), &numBytes) == MP_OKAY) {
- while (numBytes-- > 0) {
- value = (value << CHAR_BIT) | *bytes++;
- }
- if (big.sign) {
- if (value <= 1 + ~(Tcl_WideUInt)WIDE_MIN) {
- *wideIntPtr = (Tcl_WideInt)(-value);
- return TCL_OK;
+
+ UNPACK_BIGNUM(objPtr, big);
+ if ((size_t)(big.used) <= (CHAR_BIT * sizeof(Tcl_WideInt)
+ + DIGIT_BIT - 1) / DIGIT_BIT) {
+ Tcl_WideUInt value = 0;
+ unsigned long numBytes = sizeof(Tcl_WideInt);
+ Tcl_WideInt scratch;
+ unsigned char *bytes = (unsigned char *) &scratch;
+
+ if (mp_to_unsigned_bin_n(&big, bytes, &numBytes) == MP_OKAY) {
+ while (numBytes-- > 0) {
+ value = (value << CHAR_BIT) | *bytes++;
}
- } else {
- if (value <= (Tcl_WideUInt)WIDE_MAX) {
- *wideIntPtr = (Tcl_WideInt)value;
- return TCL_OK;
+ if (big.sign) {
+ *wideIntPtr = - (Tcl_WideInt) value;
+ } else {
+ *wideIntPtr = (Tcl_WideInt) value;
}
+ return TCL_OK;
}
}
if (interp != NULL) {
const char *s = "integer value too large to represent";
- Tcl_Obj *msg = Tcl_NewStringObj(s, -1);
+ Tcl_Obj* msg = Tcl_NewStringObj(s, -1);
Tcl_SetObjResult(interp, msg);
- Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW", s, (void *)NULL);
+ Tcl_SetErrorCode(interp, "ARITH", "IOVERFLOW", s, NULL);
}
return TCL_ERROR;
}
@@ -3357,160 +3110,33 @@ Tcl_GetWideIntFromObj(
TCL_PARSE_INTEGER_ONLY)==TCL_OK);
return TCL_ERROR;
}
+#ifndef NO_WIDE_TYPE
/*
*----------------------------------------------------------------------
*
- * Tcl_GetWideUIntFromObj --
+ * SetWideIntFromAny --
*
- * 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", (void *)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, (void *)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
- * object is not already a int, double or bignum, an attempt will be made
- * to convert it to one of these. Out-of-range values don't result in an
- * error, but only the least significant 64 bits will be returned.
+ * Attempts to force the internal representation for a Tcl object to
+ * tclWideIntType, specifically.
*
* Results:
- * The return value is a standard Tcl object result. If an error occurs
+ * The return value is a standard object Tcl 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, double or bignum object, the
- * conversion will free any old internal representation.
- *
*----------------------------------------------------------------------
*/
-int
-TclGetWideBitsFromObj(
- Tcl_Interp *interp, /* Used for error reporting if not NULL. */
- Tcl_Obj *objPtr, /* Object from which to get a wide int. */
- Tcl_WideInt *wideIntPtr) /* Place to store resulting wide integer. */
+static int
+SetWideIntFromAny(
+ Tcl_Interp *interp, /* Tcl interpreter */
+ Tcl_Obj *objPtr) /* Pointer to the object to convert */
{
- do {
- if (objPtr->typePtr == &tclIntType) {
- *wideIntPtr = objPtr->internalRep.wideValue;
- return TCL_OK;
- }
- if (objPtr->typePtr == &tclDoubleType) {
- if (interp != NULL) {
- Tcl_SetObjResult(interp, Tcl_ObjPrintf(
- "expected integer but got \"%s\"",
- TclGetString(objPtr)));
- Tcl_SetErrorCode(interp, "TCL", "VALUE", "INTEGER", (void *)NULL);
- }
- return TCL_ERROR;
- }
- if (objPtr->typePtr == &tclBignumType) {
- mp_int big;
- mp_err err;
-
- Tcl_WideUInt value = 0, scratch;
- size_t numBytes;
- unsigned char *bytes = (unsigned char *) &scratch;
-
- Tcl_GetBignumFromObj(NULL, objPtr, &big);
- err = mp_mod_2d(&big, (int) (CHAR_BIT * sizeof(Tcl_WideInt)), &big);
- if (err == MP_OKAY) {
- err = mp_to_ubin(&big, bytes, sizeof(Tcl_WideInt), &numBytes);
- }
- if (err != MP_OKAY) {
- return TCL_ERROR;
- }
- while (numBytes-- > 0) {
- value = (value << CHAR_BIT) | *bytes++;
- }
- *wideIntPtr = !big.sign ? (Tcl_WideInt)value : -(Tcl_WideInt)value;
- mp_clear(&big);
- return TCL_OK;
- }
- } while (TclParseNumber(interp, objPtr, "integer", NULL, -1, NULL,
- TCL_PARSE_INTEGER_ONLY)==TCL_OK);
- return TCL_ERROR;
+ Tcl_WideInt w;
+ return Tcl_GetWideIntFromObj(interp, objPtr, &w);
}
+#endif /* !NO_WIDE_TYPE */
/*
*----------------------------------------------------------------------
@@ -3531,12 +3157,11 @@ FreeBignum(
{
mp_int toFree; /* Bignum to free */
- TclUnpackBignum(objPtr, toFree);
+ UNPACK_BIGNUM(objPtr, toFree);
mp_clear(&toFree);
- if (PTR2INT(objPtr->internalRep.twoPtrValue.ptr2) < 0) {
- ckfree(objPtr->internalRep.twoPtrValue.ptr1);
+ if ((long)(objPtr->internalRep.ptrAndLongRep.value) < 0) {
+ ckfree((char *)objPtr->internalRep.ptrAndLongRep.ptr);
}
- objPtr->typePtr = NULL;
}
/*
@@ -3550,7 +3175,7 @@ FreeBignum(
* None.
*
* Side effects:
- * The destination object receives a copy of the source object
+ * The destination object receies a copy of the source object
*
*----------------------------------------------------------------------
*/
@@ -3564,7 +3189,7 @@ DupBignum(
mp_int bignumCopy;
copyPtr->typePtr = &tclBignumType;
- TclUnpackBignum(srcPtr, bignumVal);
+ UNPACK_BIGNUM(srcPtr, bignumVal);
if (mp_init_copy(&bignumCopy, &bignumVal) != MP_OKAY) {
Tcl_Panic("initialization failure in DupBignum");
}
@@ -3597,17 +3222,21 @@ UpdateStringOfBignum(
{
mp_int bignumVal;
int size;
- char *stringVal;
+ int status;
+ char* stringVal;
- TclUnpackBignum(objPtr, bignumVal);
- if (MP_OKAY != mp_radix_size(&bignumVal, 10, &size)) {
+ UNPACK_BIGNUM(objPtr, bignumVal);
+ status = mp_radix_size(&bignumVal, 10, &size);
+ if (status != MP_OKAY) {
Tcl_Panic("radix size failure in UpdateStringOfBignum");
}
- if (size < 2) {
+ if (size == 3) {
/*
- * mp_radix_size() returns < 2 when more than INT_MAX bytes would be
+ * mp_radix_size() returns 3 when more than INT_MAX bytes would be
* needed to hold the string rep (because mp_radix_size ignores
- * integer overflow issues).
+ * integer overflow issues). When we know the string rep will be more
+ * than 3, we can conclude the string rep would overflow our string
+ * length limits.
*
* Note that so long as we enforce our bignums to the size that fits
* in a packed bignum, this branch will never be taken.
@@ -3615,13 +3244,13 @@ UpdateStringOfBignum(
Tcl_Panic("UpdateStringOfBignum: string length limit exceeded");
}
-
- stringVal = Tcl_InitStringRep(objPtr, NULL, size - 1);
-
- TclOOM(stringVal, size);
- if (MP_OKAY != mp_to_radix(&bignumVal, stringVal, size, NULL, 10)) {
+ stringVal = ckalloc((size_t) size);
+ status = mp_toradix_n(&bignumVal, stringVal, 10, size);
+ if (status != MP_OKAY) {
Tcl_Panic("conversion failure in UpdateStringOfBignum");
}
+ objPtr->bytes = stringVal;
+ objPtr->length = size - 1; /* size includes a trailing null byte */
}
/*
@@ -3629,7 +3258,7 @@ UpdateStringOfBignum(
*
* Tcl_NewBignumObj --
*
- * Creates and initializes a bignum object.
+ * Creates an initializes a bignum object.
*
* Results:
* Returns the newly created object.
@@ -3645,16 +3274,16 @@ UpdateStringOfBignum(
Tcl_Obj *
Tcl_NewBignumObj(
- void *bignumValue)
+ mp_int *bignumValue)
{
return Tcl_DbNewBignumObj(bignumValue, "unknown", 0);
}
#else
Tcl_Obj *
Tcl_NewBignumObj(
- void *bignumValue)
+ mp_int *bignumValue)
{
- Tcl_Obj *objPtr;
+ Tcl_Obj* objPtr;
TclNewObj(objPtr);
Tcl_SetBignumObj(objPtr, bignumValue);
@@ -3683,8 +3312,8 @@ Tcl_NewBignumObj(
#ifdef TCL_MEM_DEBUG
Tcl_Obj *
Tcl_DbNewBignumObj(
- void *bignumValue,
- const char *file,
+ mp_int *bignumValue,
+ CONST char *file,
int line)
{
Tcl_Obj *objPtr;
@@ -3696,9 +3325,9 @@ Tcl_DbNewBignumObj(
#else
Tcl_Obj *
Tcl_DbNewBignumObj(
- void *bignumValue,
- TCL_UNUSED(const char *) /*file*/,
- TCL_UNUSED(int) /*line*/)
+ mp_int *bignumValue,
+ CONST char *file,
+ int line)
{
return Tcl_NewBignumObj(bignumValue);
}
@@ -3736,41 +3365,38 @@ GetBignumFromObj(
if (objPtr->typePtr == &tclBignumType) {
if (copy || Tcl_IsShared(objPtr)) {
mp_int temp;
-
- TclUnpackBignum(objPtr, temp);
- if (mp_init_copy(bignumValue, &temp) != MP_OKAY) {
- return TCL_ERROR;
- }
+ UNPACK_BIGNUM(objPtr, temp);
+ mp_init_copy(bignumValue, &temp);
} else {
- TclUnpackBignum(objPtr, *bignumValue);
- /* Optimized TclFreeInternalRep */
- objPtr->internalRep.twoPtrValue.ptr1 = NULL;
- objPtr->internalRep.twoPtrValue.ptr2 = NULL;
+ UNPACK_BIGNUM(objPtr, *bignumValue);
+ objPtr->internalRep.ptrAndLongRep.ptr = NULL;
+ objPtr->internalRep.ptrAndLongRep.value = 0;
objPtr->typePtr = NULL;
- /*
- * TODO: If objPtr has a string rep, this leaves
- * it undisturbed. Not clear that's proper. Pure
- * bignum values are converted to empty string.
- */
if (objPtr->bytes == NULL) {
- TclInitEmptyStringRep(objPtr);
+ TclInitStringRep(objPtr, tclEmptyStringRep, 0);
}
}
return TCL_OK;
}
if (objPtr->typePtr == &tclIntType) {
- if (mp_init_i64(bignumValue,
- objPtr->internalRep.wideValue) != MP_OKAY) {
- return TCL_ERROR;
- }
+ TclBNInitBignumFromLong(bignumValue, objPtr->internalRep.longValue);
return TCL_OK;
}
+#ifndef NO_WIDE_TYPE
+ if (objPtr->typePtr == &tclWideIntType) {
+ TclBNInitBignumFromWideInt(bignumValue,
+ objPtr->internalRep.wideValue);
+ return TCL_OK;
+ }
+#endif
if (objPtr->typePtr == &tclDoubleType) {
if (interp != NULL) {
- Tcl_SetObjResult(interp, Tcl_ObjPrintf(
- "expected integer but got \"%s\"",
- TclGetString(objPtr)));
- Tcl_SetErrorCode(interp, "TCL", "VALUE", "INTEGER", (void *)NULL);
+ Tcl_Obj *msg;
+
+ TclNewLiteralStringObj(msg, "expected integer but got \"");
+ Tcl_AppendObjToObj(msg, objPtr);
+ Tcl_AppendToObj(msg, "\"", -1);
+ Tcl_SetObjResult(interp, msg);
}
return TCL_ERROR;
}
@@ -3808,9 +3434,9 @@ int
Tcl_GetBignumFromObj(
Tcl_Interp *interp, /* Tcl interpreter for error reporting */
Tcl_Obj *objPtr, /* Object to read */
- void *bignumValue) /* Returned bignum value. */
+ mp_int *bignumValue) /* Returned bignum value. */
{
- return GetBignumFromObj(interp, objPtr, 1, (mp_int *)bignumValue);
+ return GetBignumFromObj(interp, objPtr, 1, bignumValue);
}
/*
@@ -3826,7 +3452,7 @@ Tcl_GetBignumFromObj(
*
* Side effects:
* A copy of bignum is stored in *bignumValue, which is expected to be
- * uninitialized or cleared. If conversion fails and the 'interp'
+ * uninitialized or cleared. If conversion fails, an the 'interp'
* argument is not NULL, an error message is stored in the interpreter
* result.
*
@@ -3843,9 +3469,9 @@ int
Tcl_TakeBignumFromObj(
Tcl_Interp *interp, /* Tcl interpreter for error reporting */
Tcl_Obj *objPtr, /* Object to read */
- void *bignumValue) /* Returned bignum value. */
+ mp_int *bignumValue) /* Returned bignum value. */
{
- return GetBignumFromObj(interp, objPtr, 0, (mp_int *)bignumValue);
+ return GetBignumFromObj(interp, objPtr, 0, bignumValue);
}
/*
@@ -3868,71 +3494,77 @@ Tcl_TakeBignumFromObj(
void
Tcl_SetBignumObj(
Tcl_Obj *objPtr, /* Object to set */
- void *big) /* Value to store */
+ mp_int *bignumValue) /* Value to store */
{
- Tcl_WideUInt value = 0;
- size_t numBytes;
- Tcl_WideUInt scratch;
- unsigned char *bytes = (unsigned char *) &scratch;
- mp_int *bignumValue = (mp_int *) big;
-
if (Tcl_IsShared(objPtr)) {
Tcl_Panic("%s called with shared object", "Tcl_SetBignumObj");
}
- if (mp_to_ubin(bignumValue, bytes, sizeof(Tcl_WideUInt), &numBytes) != MP_OKAY) {
- goto tooLargeForWide;
- }
- while (numBytes-- > 0) {
- value = (value << CHAR_BIT) | *bytes++;
- }
- if (value > ((Tcl_WideUInt)WIDE_MAX + bignumValue->sign)) {
- goto tooLargeForWide;
+ if ((size_t)(bignumValue->used)
+ <= (CHAR_BIT * sizeof(long) + DIGIT_BIT - 1) / DIGIT_BIT) {
+ unsigned long value = 0, numBytes = sizeof(long);
+ long scratch;
+ unsigned char *bytes = (unsigned char *)&scratch;
+ if (mp_to_unsigned_bin_n(bignumValue, bytes, &numBytes) != MP_OKAY) {
+ goto tooLargeForLong;
+ }
+ while (numBytes-- > 0) {
+ value = (value << CHAR_BIT) | *bytes++;
+ }
+ if (value > (((~(unsigned long)0) >> 1) + bignumValue->sign)) {
+ goto tooLargeForLong;
+ }
+ if (bignumValue->sign) {
+ TclSetLongObj(objPtr, -(long)value);
+ } else {
+ TclSetLongObj(objPtr, (long)value);
+ }
+ mp_clear(bignumValue);
+ return;
}
- if (bignumValue->sign) {
- TclSetIntObj(objPtr, (Tcl_WideInt)(-value));
- } else {
- TclSetIntObj(objPtr, (Tcl_WideInt)value);
+ tooLargeForLong:
+#ifndef NO_WIDE_TYPE
+ if ((size_t)(bignumValue->used)
+ <= (CHAR_BIT * sizeof(Tcl_WideInt) + DIGIT_BIT - 1) / DIGIT_BIT) {
+ Tcl_WideUInt value = 0;
+ unsigned long numBytes = sizeof(Tcl_WideInt);
+ Tcl_WideInt scratch;
+ unsigned char *bytes = (unsigned char *)&scratch;
+ if (mp_to_unsigned_bin_n(bignumValue, bytes, &numBytes) != MP_OKAY) {
+ goto tooLargeForWide;
+ }
+ while (numBytes-- > 0) {
+ value = (value << CHAR_BIT) | *bytes++;
+ }
+ if (value > (((~(Tcl_WideUInt)0) >> 1) + bignumValue->sign)) {
+ goto tooLargeForWide;
+ }
+ if (bignumValue->sign) {
+ TclSetWideIntObj(objPtr, -(Tcl_WideInt)value);
+ } else {
+ TclSetWideIntObj(objPtr, (Tcl_WideInt)value);
+ }
+ mp_clear(bignumValue);
+ return;
}
- mp_clear(bignumValue);
- return;
tooLargeForWide:
+#endif
TclInvalidateStringRep(objPtr);
- TclFreeInternalRep(objPtr);
- TclSetBignumInternalRep(objPtr, bignumValue);
+ TclFreeIntRep(objPtr);
+ TclSetBignumIntRep(objPtr, bignumValue);
}
-/*
- *----------------------------------------------------------------------
- *
- * TclSetBignumInternalRep --
- *
- * Install a bignum into the internal representation of an object.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Object internal representation is updated and object type is set. The
- * bignum value is cleared, since ownership has transferred to the
- * object.
- *
- *----------------------------------------------------------------------
- */
-
void
-TclSetBignumInternalRep(
+TclSetBignumIntRep(
Tcl_Obj *objPtr,
- void *big)
+ mp_int *bignumValue)
{
- mp_int *bignumValue = (mp_int *)big;
objPtr->typePtr = &tclBignumType;
PACK_BIGNUM(*bignumValue, objPtr);
/*
* Clear the mp_int value.
- *
- * Don't call mp_clear() because it would free the digit array we just
- * packed into the Tcl_Obj.
+ * Don't call mp_clear() because it would free the digit array
+ * we just packed into the Tcl_Obj.
*/
bignumValue->dp = NULL;
@@ -3943,51 +3575,48 @@ TclSetBignumInternalRep(
/*
*----------------------------------------------------------------------
*
- * Tcl_GetNumberFromObj --
- *
- * Extracts a number (of any possible numeric type) from an object.
+ * TclGetNumberFromObj --
*
* Results:
- * Whether the extraction worked. The type is stored in the variable
- * referred to by the typePtr argument, and a pointer to the
- * representation is stored in the variable referred to by the
- * clientDataPtr.
*
* Side effects:
- * Can allocate thread-specific data for handling the copy-out space for
- * bignums; this space is shared within a thread.
*
*----------------------------------------------------------------------
*/
-int
-Tcl_GetNumberFromObj(
+int TclGetNumberFromObj(
Tcl_Interp *interp,
Tcl_Obj *objPtr,
- void **clientDataPtr,
+ ClientData *clientDataPtr,
int *typePtr)
{
do {
if (objPtr->typePtr == &tclDoubleType) {
- if (isnan(objPtr->internalRep.doubleValue)) {
+ if (TclIsNaN(objPtr->internalRep.doubleValue)) {
*typePtr = TCL_NUMBER_NAN;
} else {
*typePtr = TCL_NUMBER_DOUBLE;
}
- *clientDataPtr = &objPtr->internalRep.doubleValue;
+ *clientDataPtr = &(objPtr->internalRep.doubleValue);
return TCL_OK;
}
if (objPtr->typePtr == &tclIntType) {
- *typePtr = TCL_NUMBER_INT;
- *clientDataPtr = &objPtr->internalRep.wideValue;
+ *typePtr = TCL_NUMBER_LONG;
+ *clientDataPtr = &(objPtr->internalRep.longValue);
+ return TCL_OK;
+ }
+#ifndef NO_WIDE_TYPE
+ if (objPtr->typePtr == &tclWideIntType) {
+ *typePtr = TCL_NUMBER_WIDE;
+ *clientDataPtr = &(objPtr->internalRep.wideValue);
return TCL_OK;
}
+#endif
if (objPtr->typePtr == &tclBignumType) {
static Tcl_ThreadDataKey bignumKey;
- mp_int *bigPtr = (mp_int *)Tcl_GetThreadData(&bignumKey,
- sizeof(mp_int));
-
- TclUnpackBignum(objPtr, *bigPtr);
+ mp_int *bigPtr = Tcl_GetThreadData(&bignumKey,
+ (int) sizeof(mp_int));
+ UNPACK_BIGNUM( objPtr, *bigPtr );
*typePtr = TCL_NUMBER_BIG;
*clientDataPtr = bigPtr;
return TCL_OK;
@@ -3996,99 +3625,6 @@ Tcl_GetNumberFromObj(
TclParseNumber(interp, objPtr, "number", NULL, -1, NULL, 0));
return TCL_ERROR;
}
-
-int
-Tcl_GetNumber(
- Tcl_Interp *interp,
- const char *bytes,
- Tcl_Size numBytes,
- void **clientDataPtr,
- int *typePtr)
-{
- static Tcl_ThreadDataKey numberCacheKey;
- Tcl_Obj *objPtr = (Tcl_Obj *)Tcl_GetThreadData(&numberCacheKey,
- sizeof(Tcl_Obj));
-
- Tcl_FreeInternalRep(objPtr);
-
- if (bytes == NULL) {
- bytes = &tclEmptyString;
- numBytes = 0;
- }
- if (numBytes < 0) {
- numBytes = (int)strlen(bytes);
- }
-
- objPtr->bytes = (char *) bytes;
- objPtr->length = numBytes;
-
- return Tcl_GetNumberFromObj(interp, objPtr, clientDataPtr, typePtr);
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * Tcl_IncrRefCount --
- *
- * Increments the reference count of the object.
- *
- * Results:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-#undef Tcl_IncrRefCount
-void
-Tcl_IncrRefCount(
- Tcl_Obj *objPtr) /* The object we are registering a reference to. */
-{
- ++(objPtr)->refCount;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * Tcl_DecrRefCount --
- *
- * Decrements the reference count of the object.
- *
- * Results:
- * The storage for objPtr may be freed.
- *
- *----------------------------------------------------------------------
- */
-
-#undef Tcl_DecrRefCount
-void
-Tcl_DecrRefCount(
- Tcl_Obj *objPtr) /* The object we are releasing a reference to. */
-{
- if (objPtr->refCount-- <= 1) {
- TclFreeObj(objPtr);
- }
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * Tcl_IsShared --
- *
- * Tests if the object has a ref count greater than one.
- *
- * Results:
- * Boolean value that is the result of the test.
- *
- *----------------------------------------------------------------------
- */
-
-#undef Tcl_IsShared
-int
-Tcl_IsShared(
- Tcl_Obj *objPtr) /* The object to test for being shared. */
-{
- return ((objPtr)->refCount > 1);
-}
/*
*----------------------------------------------------------------------
@@ -4111,23 +3647,23 @@ Tcl_IsShared(
*----------------------------------------------------------------------
*/
-#ifdef TCL_MEM_DEBUG
void
Tcl_DbIncrRefCount(
- Tcl_Obj *objPtr, /* The object we are registering a reference
+ register Tcl_Obj *objPtr, /* The object we are registering a reference
* to. */
- const char *file, /* The name of the source file calling this
+ CONST char *file, /* The name of the source file calling this
* function; used for debugging. */
int line) /* Line number in the source file; used for
* debugging. */
{
+#ifdef TCL_MEM_DEBUG
if (objPtr->refCount == 0x61616161) {
fprintf(stderr, "file = %s, line = %d\n", file, line);
fflush(stderr);
Tcl_Panic("incrementing refCount of previously disposed object");
}
-#if TCL_THREADS
+# ifdef TCL_THREADS
/*
* Check to make sure that the Tcl_Obj was allocated by the current
* thread. Don't do this check when shutting down since thread local
@@ -4135,33 +3671,25 @@ Tcl_DbIncrRefCount(
*/
if (!TclInExit()) {
- ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
- Tcl_HashTable *tablePtr = tsdPtr->objThreadMap;
+ Tcl_HashTable *tablePtr;
Tcl_HashEntry *hPtr;
+ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
+ tablePtr = tsdPtr->objThreadMap;
if (!tablePtr) {
Tcl_Panic("object table not initialized");
}
- hPtr = Tcl_FindHashEntry(tablePtr, objPtr);
+ hPtr = Tcl_FindHashEntry(tablePtr, (char *) objPtr);
if (!hPtr) {
- Tcl_Panic("Trying to %s of Tcl_Obj allocated in another thread",
- "incr ref count");
+ Tcl_Panic("%s%s",
+ "Trying to incr ref count of "
+ "Tcl_Obj allocated in another thread");
}
}
-# endif /* TCL_THREADS */
- ++(objPtr)->refCount;
-}
-#else /* !TCL_MEM_DEBUG */
-void
-Tcl_DbIncrRefCount(
- Tcl_Obj *objPtr, /* The object we are registering a reference
- * to. */
- TCL_UNUSED(const char *) /*file*/,
- TCL_UNUSED(int) /*line*/)
-{
+# endif
+#endif
++(objPtr)->refCount;
}
-#endif /* TCL_MEM_DEBUG */
/*
*----------------------------------------------------------------------
@@ -4184,23 +3712,23 @@ Tcl_DbIncrRefCount(
*----------------------------------------------------------------------
*/
-#ifdef TCL_MEM_DEBUG
void
Tcl_DbDecrRefCount(
- Tcl_Obj *objPtr, /* The object we are releasing a reference
+ register Tcl_Obj *objPtr, /* The object we are releasing a reference
* to. */
- const char *file, /* The name of the source file calling this
+ CONST char *file, /* The name of the source file calling this
* function; used for debugging. */
int line) /* Line number in the source file; used for
* debugging. */
{
+#ifdef TCL_MEM_DEBUG
if (objPtr->refCount == 0x61616161) {
fprintf(stderr, "file = %s, line = %d\n", file, line);
fflush(stderr);
Tcl_Panic("decrementing refCount of previously disposed object");
}
-#if TCL_THREADS
+# ifdef TCL_THREADS
/*
* Check to make sure that the Tcl_Obj was allocated by the current
* thread. Don't do this check when shutting down since thread local
@@ -4208,38 +3736,27 @@ Tcl_DbDecrRefCount(
*/
if (!TclInExit()) {
- ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
- Tcl_HashTable *tablePtr = tsdPtr->objThreadMap;
+ Tcl_HashTable *tablePtr;
Tcl_HashEntry *hPtr;
+ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
+ tablePtr = tsdPtr->objThreadMap;
if (!tablePtr) {
Tcl_Panic("object table not initialized");
}
- hPtr = Tcl_FindHashEntry(tablePtr, objPtr);
+ hPtr = Tcl_FindHashEntry(tablePtr, (char *) objPtr);
if (!hPtr) {
- Tcl_Panic("Trying to %s of Tcl_Obj allocated in another thread",
- "decr ref count");
+ Tcl_Panic("%s%s",
+ "Trying to decr ref count of "
+ "Tcl_Obj allocated in another thread");
}
}
-# endif /* TCL_THREADS */
-
- if (objPtr->refCount-- <= 1) {
- TclFreeObj(objPtr);
- }
-}
-#else /* !TCL_MEM_DEBUG */
-void
-Tcl_DbDecrRefCount(
- Tcl_Obj *objPtr, /* The object we are releasing a reference
- * to. */
- TCL_UNUSED(const char *) /*file*/,
- TCL_UNUSED(int) /*line*/)
-{
- if (objPtr->refCount-- <= 1) {
+# endif
+#endif
+ if (--(objPtr)->refCount <= 0) {
TclFreeObj(objPtr);
}
}
-#endif /* TCL_MEM_DEBUG */
/*
*----------------------------------------------------------------------
@@ -4264,16 +3781,11 @@ Tcl_DbDecrRefCount(
int
Tcl_DbIsShared(
- Tcl_Obj *objPtr, /* The object to test for being shared. */
-#ifdef TCL_MEM_DEBUG
- const char *file, /* The name of the source file calling this
+ register Tcl_Obj *objPtr, /* The object to test for being shared. */
+ CONST char *file, /* The name of the source file calling this
* function; used for debugging. */
int line) /* Line number in the source file; used for
* debugging. */
-#else
- TCL_UNUSED(const char *) /*file*/,
- TCL_UNUSED(int) /*line*/)
-#endif
{
#ifdef TCL_MEM_DEBUG
if (objPtr->refCount == 0x61616161) {
@@ -4282,7 +3794,7 @@ Tcl_DbIsShared(
Tcl_Panic("checking whether previously disposed object is shared");
}
-#if TCL_THREADS
+# ifdef TCL_THREADS
/*
* Check to make sure that the Tcl_Obj was allocated by the current
* thread. Don't do this check when shutting down since thread local
@@ -4290,21 +3802,22 @@ Tcl_DbIsShared(
*/
if (!TclInExit()) {
- ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
- Tcl_HashTable *tablePtr = tsdPtr->objThreadMap;
+ Tcl_HashTable *tablePtr;
Tcl_HashEntry *hPtr;
-
+ ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
+ tablePtr = tsdPtr->objThreadMap;
if (!tablePtr) {
Tcl_Panic("object table not initialized");
}
- hPtr = Tcl_FindHashEntry(tablePtr, objPtr);
+ hPtr = Tcl_FindHashEntry(tablePtr, (char *) objPtr);
if (!hPtr) {
- Tcl_Panic("Trying to %s of Tcl_Obj allocated in another thread",
- "check shared status");
+ Tcl_Panic("%s%s",
+ "Trying to check shared status of"
+ "Tcl_Obj allocated in another thread");
}
}
-# endif /* TCL_THREADS */
-#endif /* TCL_MEM_DEBUG */
+# endif
+#endif
#ifdef TCL_COMPILE_STATS
Tcl_MutexLock(&tclObjMutex);
@@ -4316,7 +3829,7 @@ Tcl_DbIsShared(
tclObjsShared[0]++;
}
Tcl_MutexUnlock(&tclObjMutex);
-#endif /* TCL_COMPILE_STATS */
+#endif
return ((objPtr)->refCount > 1);
}
@@ -4341,7 +3854,7 @@ Tcl_DbIsShared(
void
Tcl_InitObjHashTable(
- Tcl_HashTable *tablePtr)
+ register Tcl_HashTable *tablePtr)
/* Pointer to table record, which is supplied
* by the caller. */
{
@@ -4367,13 +3880,14 @@ Tcl_InitObjHashTable(
static Tcl_HashEntry *
AllocObjEntry(
- TCL_UNUSED(Tcl_HashTable *),
+ Tcl_HashTable *tablePtr, /* Hash table. */
void *keyPtr) /* Key to store in the hash table entry. */
{
- Tcl_Obj *objPtr = (Tcl_Obj *)keyPtr;
- Tcl_HashEntry *hPtr = (Tcl_HashEntry *)ckalloc(sizeof(Tcl_HashEntry));
+ Tcl_Obj *objPtr = (Tcl_Obj *) keyPtr;
+ Tcl_HashEntry *hPtr;
- hPtr->key.objPtr = objPtr;
+ hPtr = (Tcl_HashEntry *) ckalloc((unsigned) (sizeof(Tcl_HashEntry)));
+ hPtr->key.oneWordValue = (char *) objPtr;
Tcl_IncrRefCount(objPtr);
hPtr->clientData = NULL;
@@ -4402,17 +3916,18 @@ TclCompareObjKeys(
void *keyPtr, /* New key to compare. */
Tcl_HashEntry *hPtr) /* Existing key to compare. */
{
- Tcl_Obj *objPtr1 = (Tcl_Obj *)keyPtr;
- Tcl_Obj *objPtr2 = (Tcl_Obj *)hPtr->key.oneWordValue;
- const char *p1, *p2;
- size_t l1, l2;
+ Tcl_Obj *objPtr1 = (Tcl_Obj *) keyPtr;
+ Tcl_Obj *objPtr2 = (Tcl_Obj *) hPtr->key.oneWordValue;
+ register CONST char *p1, *p2;
+ register int l1, l2;
/*
* If the object pointers are the same then they match.
- * OPT: this comparison was moved to the caller
+ */
- if (objPtr1 == objPtr2) return 1;
- */
+ if (objPtr1 == objPtr2) {
+ return 1;
+ }
/*
* Don't use Tcl_GetStringFromObj as it would prevent l1 and l2 being
@@ -4465,7 +3980,7 @@ TclFreeObjEntry(
Tcl_Obj *objPtr = (Tcl_Obj *) hPtr->key.oneWordValue;
Tcl_DecrRefCount(objPtr);
- ckfree(hPtr);
+ ckfree((char *) hPtr);
}
/*
@@ -4486,15 +4001,16 @@ TclFreeObjEntry(
*----------------------------------------------------------------------
*/
-TCL_HASH_TYPE
+unsigned int
TclHashObjKey(
- TCL_UNUSED(Tcl_HashTable *),
+ Tcl_HashTable *tablePtr, /* Hash table. */
void *keyPtr) /* Key from which to compute hash value. */
{
- Tcl_Obj *objPtr = (Tcl_Obj *)keyPtr;
- Tcl_Size length;
- const char *string = Tcl_GetStringFromObj(objPtr, &length);
- TCL_HASH_TYPE result = 0;
+ Tcl_Obj *objPtr = (Tcl_Obj *) keyPtr;
+ CONST char *string = TclGetString(objPtr);
+ int length = objPtr->length;
+ unsigned int result = 0;
+ int i;
/*
* I tried a zillion different hash functions and asked many other people
@@ -4504,37 +4020,16 @@ TclHashObjKey(
* following reasons:
*
* 1. Multiplying by 10 is perfect for keys that are decimal strings, and
- * multiplying by 9 is just about as good.
+ * multiplying by 9 is just about as good.
* 2. Times-9 is (shift-left-3) plus (old). This means that each
- * character's bits hang around in the low-order bits of the hash value
- * for ever, plus they spread fairly rapidly up to the high-order bits
- * to fill out the hash value. This seems works well both for decimal
- * and non-decimal strings.
- *
- * Note that this function is very weak against malicious strings; it's
- * very easy to generate multiple keys that have the same hashcode. On the
- * other hand, that hardly ever actually occurs and this function *is*
- * very cheap, even by comparison with industry-standard hashes like FNV.
- * If real strength of hash is required though, use a custom hash based on
- * Bob Jenkins's lookup3(), but be aware that it's significantly slower.
- * Tcl does not use that level of strength because it typically does not
- * need it (and some of the aspects of that strength are genuinely
- * unnecessary given the rest of Tcl's hash machinery, and the fact that
- * we do not either transfer hashes to another machine, use them as a true
- * substitute for equality, or attempt to minimize work in rebuilding the
- * hash table).
- *
- * See also HashStringKey in tclHash.c.
- * See also HashString in tclLiteral.c.
- *
- * See [tcl-Feature Request #2958832]
+ * character's bits hang around in the low-order bits of the hash value
+ * for ever, plus they spread fairly rapidly up to the high-order bits
+ * to fill out the hash value. This seems works well both for decimal
+ * and *non-decimal strings.
*/
- if (length > 0) {
- result = UCHAR(*string);
- while (--length) {
- result += (result << 3) + UCHAR(*++string);
- }
+ for (i=0 ; i<length ; i++) {
+ result += (result << 3) + string[i];
}
return result;
}
@@ -4562,13 +4057,16 @@ Tcl_Command
Tcl_GetCommandFromObj(
Tcl_Interp *interp, /* The interpreter in which to resolve the
* command and to report errors. */
- Tcl_Obj *objPtr) /* The object containing the command's name.
+ register Tcl_Obj *objPtr) /* The object containing the command's name.
* If the name starts with "::", will be
* looked up in global namespace. Else, looked
* up first in the current namespace, then in
* global namespace. */
{
- ResolvedCmdName *resPtr;
+ register ResolvedCmdName *resPtr;
+ register Command *cmdPtr;
+ Namespace *refNsPtr;
+ int result;
/*
* Get the internal representation, converting to a command type if
@@ -4589,36 +4087,31 @@ Tcl_GetCommandFromObj(
* to discard the old rep and create a new one.
*/
- resPtr = (ResolvedCmdName *)objPtr->internalRep.twoPtrValue.ptr1;
- if (objPtr->typePtr == &tclCmdNameType) {
- Command *cmdPtr = resPtr->cmdPtr;
-
- if ((cmdPtr->cmdEpoch == resPtr->cmdEpoch)
- && (interp == cmdPtr->nsPtr->interp)
- && !(cmdPtr->nsPtr->flags & NS_DYING)) {
- Namespace *refNsPtr = (Namespace *)
- TclGetCurrentNamespace(interp);
-
- if ((resPtr->refNsPtr == NULL)
- || ((refNsPtr == resPtr->refNsPtr)
- && (resPtr->refNsId == refNsPtr->nsId)
- && (resPtr->refNsCmdEpoch == refNsPtr->cmdRefEpoch))) {
- return (Tcl_Command) cmdPtr;
- }
- }
+ resPtr = (ResolvedCmdName *) objPtr->internalRep.twoPtrValue.ptr1;
+ if ((objPtr->typePtr != &tclCmdNameType)
+ || (resPtr == NULL)
+ || (cmdPtr = resPtr->cmdPtr, cmdPtr->cmdEpoch != resPtr->cmdEpoch)
+ || (cmdPtr->flags & CMD_IS_DELETED)
+ || (interp != cmdPtr->nsPtr->interp)
+ || (cmdPtr->nsPtr->flags & NS_DYING)
+ || ((resPtr->refNsPtr != NULL) &&
+ (((refNsPtr = (Namespace *) TclGetCurrentNamespace(interp))
+ != resPtr->refNsPtr)
+ || (resPtr->refNsId != refNsPtr->nsId)
+ || (resPtr->refNsCmdEpoch != refNsPtr->cmdRefEpoch)))
+ ) {
+
+ result = tclCmdNameType.setFromAnyProc(interp, objPtr);
+
+ resPtr = (ResolvedCmdName *) objPtr->internalRep.twoPtrValue.ptr1;
+ if ((result == TCL_OK) && resPtr) {
+ cmdPtr = resPtr->cmdPtr;
+ } else {
+ cmdPtr = NULL;
+ }
}
- /*
- * OK, must create a new internal representation (or fail) as any cache we
- * had is invalid one way or another.
- */
-
- /* See [07d13d99b0a9] why we cannot call SetCmdNameFromAny() directly here. */
- if (tclCmdNameType.setFromAnyProc(interp, objPtr) != TCL_OK) {
- return NULL;
- }
- resPtr = (ResolvedCmdName *)objPtr->internalRep.twoPtrValue.ptr1;
- return (Tcl_Command) (resPtr ? resPtr->cmdPtr : NULL);
+ return (Tcl_Command) cmdPtr;
}
/*
@@ -4633,86 +4126,62 @@ Tcl_GetCommandFromObj(
* None.
*
* Side effects:
- * The object's old internal rep is freed. Its string rep is not
+ * The object's old internal rep is freed. It's string rep is not
* changed. The refcount in the Command structure is incremented to keep
* it from being freed if the command is later deleted until
- * TclNRExecuteByteCode has a chance to recognize that it was deleted.
+ * TclExecuteByteCode has a chance to recognize that it was deleted.
*
*----------------------------------------------------------------------
*/
-static void
-SetCmdNameObj(
- Tcl_Interp *interp,
- Tcl_Obj *objPtr,
- Command *cmdPtr,
- ResolvedCmdName *resPtr)
+void
+TclSetCmdNameObj(
+ Tcl_Interp *interp, /* Points to interpreter containing command
+ * that should be cached in objPtr. */
+ register Tcl_Obj *objPtr, /* Points to Tcl object to be changed to a
+ * CmdName object. */
+ Command *cmdPtr) /* Points to Command structure that the
+ * CmdName object should refer to. */
{
Interp *iPtr = (Interp *) interp;
- ResolvedCmdName *fillPtr;
- const char *name = TclGetString(objPtr);
+ register ResolvedCmdName *resPtr;
+ register Namespace *currNsPtr;
+ char *name;
- if (resPtr) {
- fillPtr = resPtr;
- } else {
- fillPtr = (ResolvedCmdName *)ckalloc(sizeof(ResolvedCmdName));
- fillPtr->refCount = 1;
+ if (objPtr->typePtr == &tclCmdNameType) {
+ return;
}
- fillPtr->cmdPtr = cmdPtr;
cmdPtr->refCount++;
- fillPtr->cmdEpoch = cmdPtr->cmdEpoch;
+ resPtr = (ResolvedCmdName *) ckalloc(sizeof(ResolvedCmdName));
+ resPtr->cmdPtr = cmdPtr;
+ resPtr->cmdEpoch = cmdPtr->cmdEpoch;
+ resPtr->refCount = 1;
- /* NOTE: relying on NULL termination here. */
- if ((name[0] == ':') && (name[1] == ':')) {
+ name = TclGetString(objPtr);
+ if ((*name++ == ':') && (*name == ':')) {
/*
- * Fully qualified names always resolve to same thing. No need
- * to record resolution context information.
+ * The name is fully qualified: set the referring namespace to
+ * NULL.
*/
- fillPtr->refNsPtr = NULL;
- fillPtr->refNsId = 0; /* Will not be read */
- fillPtr->refNsCmdEpoch = 0; /* Will not be read */
+ resPtr->refNsPtr = NULL;
} else {
/*
- * Record current state of current namespace as the resolution
- * context of this command name lookup.
+ * Get the current namespace.
*/
- Namespace *currNsPtr = iPtr->varFramePtr->nsPtr;
-
- fillPtr->refNsPtr = currNsPtr;
- fillPtr->refNsId = currNsPtr->nsId;
- fillPtr->refNsCmdEpoch = currNsPtr->cmdRefEpoch;
- }
-
- if (resPtr == NULL) {
- TclFreeInternalRep(objPtr);
-
- objPtr->internalRep.twoPtrValue.ptr1 = fillPtr;
- objPtr->internalRep.twoPtrValue.ptr2 = NULL;
- objPtr->typePtr = &tclCmdNameType;
- }
-}
-void
-TclSetCmdNameObj(
- Tcl_Interp *interp, /* Points to interpreter containing command
- * that should be cached in objPtr. */
- Tcl_Obj *objPtr, /* Points to Tcl object to be changed to a
- * CmdName object. */
- Command *cmdPtr) /* Points to Command structure that the
- * CmdName object should refer to. */
-{
- ResolvedCmdName *resPtr;
+ currNsPtr = iPtr->varFramePtr->nsPtr;
- if (objPtr->typePtr == &tclCmdNameType) {
- resPtr = (ResolvedCmdName *)objPtr->internalRep.twoPtrValue.ptr1;
- if (resPtr != NULL && resPtr->cmdPtr == cmdPtr) {
- return;
- }
+ resPtr->refNsPtr = currNsPtr;
+ resPtr->refNsId = currNsPtr->nsId;
+ resPtr->refNsCmdEpoch = currNsPtr->cmdRefEpoch;
}
- SetCmdNameObj(interp, objPtr, cmdPtr, NULL);
+ TclFreeIntRep(objPtr);
+ objPtr->internalRep.twoPtrValue.ptr1 = (void *) resPtr;
+ objPtr->internalRep.twoPtrValue.ptr2 = NULL;
+ objPtr->typePtr = &tclCmdNameType;
}
/*
@@ -4738,17 +4207,20 @@ TclSetCmdNameObj(
static void
FreeCmdNameInternalRep(
- Tcl_Obj *objPtr) /* CmdName object with internal
+ register Tcl_Obj *objPtr) /* CmdName object with internal
* representation to free. */
{
- ResolvedCmdName *resPtr = (ResolvedCmdName *)objPtr->internalRep.twoPtrValue.ptr1;
+ register ResolvedCmdName *resPtr =
+ (ResolvedCmdName *) objPtr->internalRep.twoPtrValue.ptr1;
+ if (resPtr != NULL) {
/*
* Decrement the reference count of the ResolvedCmdName structure. If
* there are no more uses, free the ResolvedCmdName structure.
*/
- if (resPtr->refCount-- <= 1) {
+ resPtr->refCount--;
+ if (resPtr->refCount == 0) {
/*
* Now free the cached command, unless it is still in its hash
* table or if there are other references to it from other cmdName
@@ -4756,10 +4228,10 @@ FreeCmdNameInternalRep(
*/
Command *cmdPtr = resPtr->cmdPtr;
-
TclCleanupCommandMacro(cmdPtr);
- ckfree(resPtr);
+ ckfree((char *) resPtr);
}
+ }
objPtr->typePtr = NULL;
}
@@ -4786,13 +4258,16 @@ FreeCmdNameInternalRep(
static void
DupCmdNameInternalRep(
Tcl_Obj *srcPtr, /* Object with internal rep to copy. */
- Tcl_Obj *copyPtr) /* Object with internal rep to set. */
+ register Tcl_Obj *copyPtr) /* Object with internal rep to set. */
{
- ResolvedCmdName *resPtr = (ResolvedCmdName *)srcPtr->internalRep.twoPtrValue.ptr1;
+ register ResolvedCmdName *resPtr = (ResolvedCmdName *)
+ srcPtr->internalRep.twoPtrValue.ptr1;
- copyPtr->internalRep.twoPtrValue.ptr1 = resPtr;
+ copyPtr->internalRep.twoPtrValue.ptr1 = (void *) resPtr;
copyPtr->internalRep.twoPtrValue.ptr2 = NULL;
+ if (resPtr != NULL) {
resPtr->refCount++;
+ }
copyPtr->typePtr = &tclCmdNameType;
}
@@ -4820,11 +4295,13 @@ DupCmdNameInternalRep(
static int
SetCmdNameFromAny(
Tcl_Interp *interp, /* Used for error reporting if not NULL. */
- Tcl_Obj *objPtr) /* The object to convert. */
+ register Tcl_Obj *objPtr) /* The object to convert. */
{
- const char *name;
- Command *cmdPtr;
- ResolvedCmdName *resPtr;
+ Interp *iPtr = (Interp *) interp;
+ char *name;
+ register Command *cmdPtr;
+ Namespace *currNsPtr;
+ register ResolvedCmdName *resPtr;
if (interp == NULL) {
return TCL_ERROR;
@@ -4839,100 +4316,61 @@ SetCmdNameFromAny(
*/
name = TclGetString(objPtr);
- cmdPtr = (Command *)
- Tcl_FindCommand(interp, name, /*ns*/ NULL, /*flags*/ 0);
+ cmdPtr = (Command *) Tcl_FindCommand(interp, name, /*ns*/ NULL, /*flags*/ 0);
/*
- * Stop shimmering and caching nothing when we found nothing. Just
- * report the failure to find the command as an error.
+ * Free the old internalRep before setting the new one. Do this after
+ * getting the string rep to allow the conversion code (in particular,
+ * Tcl_GetStringFromObj) to use that old internalRep.
*/
- if (cmdPtr == NULL || !TclRoutineHasName(cmdPtr)) {
- return TCL_ERROR;
- }
-
- resPtr = (ResolvedCmdName *)objPtr->internalRep.twoPtrValue.ptr1;
- if ((objPtr->typePtr == &tclCmdNameType) && (resPtr->refCount == 1)) {
- /*
- * Re-use existing ResolvedCmdName struct when possible.
- * Cleanup the old fields that need it.
- */
-
- Command *oldCmdPtr = resPtr->cmdPtr;
+ if (cmdPtr) {
+ cmdPtr->refCount++;
+ resPtr = (ResolvedCmdName *) objPtr->internalRep.twoPtrValue.ptr1;
+ if ((objPtr->typePtr == &tclCmdNameType)
+ && resPtr && (resPtr->refCount == 1)) {
+ /*
+ * Reuse the old ResolvedCmdName struct instead of freeing it
+ */
- if (oldCmdPtr->refCount-- <= 1) {
- TclCleanupCommandMacro(oldCmdPtr);
+ Command *oldCmdPtr = resPtr->cmdPtr;
+ if (--oldCmdPtr->refCount == 0) {
+ TclCleanupCommandMacro(oldCmdPtr);
+ }
+ } else {
+ TclFreeIntRep(objPtr);
+ resPtr = (ResolvedCmdName *) ckalloc(sizeof(ResolvedCmdName));
+ resPtr->refCount = 1;
+ objPtr->internalRep.twoPtrValue.ptr1 = (void *) resPtr;
+ objPtr->internalRep.twoPtrValue.ptr2 = NULL;
+ objPtr->typePtr = &tclCmdNameType;
}
- } else {
- resPtr = NULL;
- }
-
- SetCmdNameObj(interp, objPtr, cmdPtr, resPtr);
- return TCL_OK;
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * Tcl_RepresentationCmd --
- *
- * Implementation of the "tcl::unsupported::representation" command.
- *
- * Results:
- * Reports the current representation (Tcl_Obj type) of its argument.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
-int
-Tcl_RepresentationCmd(
- TCL_UNUSED(void *),
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *const objv[])
-{
- Tcl_Obj *descObj;
-
- if (objc != 2) {
- Tcl_WrongNumArgs(interp, 1, objv, "value");
- return TCL_ERROR;
- }
+ resPtr->cmdPtr = cmdPtr;
+ resPtr->cmdEpoch = cmdPtr->cmdEpoch;
+ if ((*name++ == ':') && (*name == ':')) {
+ /*
+ * The name is fully qualified: set the referring namespace to
+ * NULL.
+ */
- /*
- * Value is a bignum with a refcount of 14, object pointer at 0x12345678,
- * internal representation 0x45671234:0x98765432, string representation
- * "1872361827361287"
- */
+ resPtr->refNsPtr = NULL;
+ } else {
+ /*
+ * Get the current namespace.
+ */
- descObj = Tcl_ObjPrintf("value is a %s with a refcount of %" TCL_SIZE_MODIFIER "d,"
- " object pointer at %p",
- objv[1]->typePtr ? objv[1]->typePtr->name : "pure string",
- objv[1]->refCount, objv[1]);
+ currNsPtr = iPtr->varFramePtr->nsPtr;
- if (objv[1]->typePtr) {
- if (objv[1]->typePtr == &tclDoubleType) {
- Tcl_AppendPrintfToObj(descObj, ", internal representation %g",
- objv[1]->internalRep.doubleValue);
- } else {
- Tcl_AppendPrintfToObj(descObj, ", internal representation %p:%p",
- (void *) objv[1]->internalRep.twoPtrValue.ptr1,
- (void *) objv[1]->internalRep.twoPtrValue.ptr2);
+ resPtr->refNsPtr = currNsPtr;
+ resPtr->refNsId = currNsPtr->nsId;
+ resPtr->refNsCmdEpoch = currNsPtr->cmdRefEpoch;
}
- }
-
- if (objv[1]->bytes) {
- Tcl_AppendToObj(descObj, ", string representation \"", -1);
- Tcl_AppendLimitedToObj(descObj, objv[1]->bytes, objv[1]->length,
- 16, "...");
- Tcl_AppendToObj(descObj, "\"", -1);
} else {
- Tcl_AppendToObj(descObj, ", no string representation", -1);
+ TclFreeIntRep(objPtr);
+ objPtr->internalRep.twoPtrValue.ptr1 = NULL;
+ objPtr->internalRep.twoPtrValue.ptr2 = NULL;
+ objPtr->typePtr = &tclCmdNameType;
}
-
- Tcl_SetObjResult(interp, descObj);
return TCL_OK;
}
@@ -4941,7 +4379,5 @@ Tcl_RepresentationCmd(
* mode: c
* c-basic-offset: 4
* fill-column: 78
- * tab-width: 8
- * indent-tabs-mode: nil
* End:
*/