summaryrefslogtreecommitdiffstats
path: root/generic/tclObj.c
diff options
context:
space:
mode:
Diffstat (limited to 'generic/tclObj.c')
-rw-r--r--generic/tclObj.c1228
1 files changed, 553 insertions, 675 deletions
diff --git a/generic/tclObj.c b/generic/tclObj.c
index 1abbb31..230842a 100644
--- a/generic/tclObj.c
+++ b/generic/tclObj.c
@@ -16,6 +16,7 @@
#include "tclInt.h"
#include "tommath.h"
+#include <float.h>
#include <math.h>
/*
@@ -49,17 +50,18 @@ Tcl_Mutex tclObjMutex;
*/
char tclEmptyString = '\0';
-
+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 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,28 +78,33 @@ typedef struct ObjData {
*/
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 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. */
+ 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)
- Tcl_HashTable *objThreadMap;/* Thread local table that is used to check
- * that a Tcl_Obj was not allocated by some
- * other thread. */
+ /*
+ * 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(ClientData 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
@@ -146,11 +153,11 @@ typedef struct PendingObjData {
#define ObjOnStack(contextPtr) ((contextPtr)->deletionStack != NULL)
#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; \
+ (objPtrVar) = (contextPtr)->deletionStack; \
(contextPtr)->deletionStack = (Tcl_Obj *) (objPtrVar)->bytes
/*
@@ -159,15 +166,11 @@ typedef struct PendingObjData {
#ifndef TCL_THREADS
static PendingObjData pendingObjData;
#define ObjInitDeletionContext(contextPtr) \
- PendingObjData *const contextPtr = &pendingObjData
-#elif 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 *CONST contextPtr = (PendingObjData *) \
Tcl_GetThreadData(&pendingObjDataKey, sizeof(PendingObjData))
#endif
@@ -176,29 +179,29 @@ static Tcl_ThreadDataKey pendingObjDataKey;
*/
#define PACK_BIGNUM(bignum, objPtr) \
- if ((bignum).used > 0x7fff) { \
- mp_int *temp = (void *) ckalloc((unsigned) sizeof(mp_int)); \
- *temp = bignum; \
- (objPtr)->internalRep.twoPtrValue.ptr1 = temp; \
- (objPtr)->internalRep.twoPtrValue.ptr2 = INT2PTR(-1); \
- } else { \
- if ((bignum).alloc > 0x7fff) { \
- mp_shrink(&(bignum)); \
- } \
- (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.twoPtrValue.ptr2 == INT2PTR(-1)) { \
- (bignum) = *((mp_int *) ((objPtr)->internalRep.twoPtrValue.ptr1)); \
- } else { \
- (bignum).dp = (objPtr)->internalRep.twoPtrValue.ptr1; \
- (bignum).sign = PTR2INT((objPtr)->internalRep.twoPtrValue.ptr2) >> 30; \
- (bignum).alloc = \
- (PTR2INT((objPtr)->internalRep.twoPtrValue.ptr2) >> 15) & 0x7fff; \
- (bignum).used = PTR2INT((objPtr)->internalRep.twoPtrValue.ptr2) & 0x7fff; \
+ 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; \
}
/*
@@ -206,11 +209,12 @@ 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);
-#ifndef TCL_WIDE_INT_IS_LONG
+#ifndef NO_WIDE_TYPE
static void UpdateStringOfWideInt(Tcl_Obj *objPtr);
static int SetWideIntFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr);
#endif
@@ -242,56 +246,56 @@ static int SetCmdNameFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr);
* implementations.
*/
-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 */
};
-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 = {
- "int", /* name */
- NULL, /* freeIntRepProc */
- NULL, /* dupIntRepProc */
- UpdateStringOfInt, /* updateStringProc */
- SetIntFromAny /* setFromAnyProc */
+Tcl_ObjType tclIntType = {
+ "int", /* name */
+ NULL, /* freeIntRepProc */
+ NULL, /* dupIntRepProc */
+ UpdateStringOfInt, /* updateStringProc */
+ SetIntFromAny /* setFromAnyProc */
};
-#ifndef TCL_WIDE_INT_IS_LONG
-const Tcl_ObjType tclWideIntType = {
- "wideInt", /* name */
- NULL, /* freeIntRepProc */
- NULL, /* dupIntRepProc */
- UpdateStringOfWideInt, /* updateStringProc */
- SetWideIntFromAny /* 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 */
@@ -313,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 */
};
/*
@@ -360,7 +356,7 @@ typedef struct ResolvedCmdName {
* 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
@@ -401,13 +397,14 @@ TclInitObjSubsystem(void)
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 ... */
Tcl_RegisterObjType(&oldBooleanType);
-#ifndef TCL_WIDE_INT_IS_LONG
+#ifndef NO_WIDE_TYPE
Tcl_RegisterObjType(&tclWideIntType);
#endif
@@ -417,7 +414,6 @@ TclInitObjSubsystem(void)
tclObjsFreed = 0;
{
int i;
-
for (i=0 ; i<TCL_MAX_SHARED_OBJ_STATS ; i++) {
tclObjsShared[i] = 0;
}
@@ -458,12 +454,12 @@ TclFinalizeThreadObjects(void)
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
@@ -525,8 +521,8 @@ TclFinalizeObjects(void)
*----------------------------------------------------------------------
*/
-static ThreadSpecificData *
-TclGetContLineTable(void)
+static ThreadSpecificData*
+TclGetContLineTable()
{
/*
* Initialize the hashtable tracking invisible continuation lines. For
@@ -537,11 +533,10 @@ TclGetContLineTable(void)
*/
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
-
if (!tsdPtr->lineCLPtr) {
- tsdPtr->lineCLPtr = 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;
}
@@ -564,17 +559,18 @@ TclGetContLineTable(void)
*----------------------------------------------------------------------
*/
-ContLineLoc *
-TclContinuationsEnter(
- Tcl_Obj *objPtr,
- int num,
- int *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 = ckalloc(sizeof(ContLineLoc) + num*sizeof(int));
+ Tcl_HashEntry* hPtr =
+ Tcl_CreateHashEntry (tsdPtr->lineCLPtr, (char*) objPtr, &newEntry);
+
+ ContLineLoc* clLocPtr =
+ (ContLineLoc*) ckalloc (sizeof(ContLineLoc) + num*sizeof(int));
if (!newEntry) {
/*
@@ -593,18 +589,18 @@ TclContinuationsEnter(
* 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(int));
- 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;
}
@@ -629,14 +625,8 @@ TclContinuationsEnter(
*/
void
-TclContinuationsEnterDerived(
- Tcl_Obj *objPtr,
- int start,
- int *clNext)
+TclContinuationsEnterDerived(Tcl_Obj* objPtr, int start, int* clNext)
{
- int length, end, num;
- int *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
@@ -657,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) {
@@ -673,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) {
int i;
- ContLineLoc *clLocPtr = TclContinuationsEnter(objPtr, num, clNext);
+ 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;
/*
@@ -707,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.
@@ -722,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 = Tcl_GetHashValue(hPtr);
+ ContLineLoc* clLocPtr = (ContLineLoc*) Tcl_GetHashValue (hPtr);
TclContinuationsEnter(objPtr, clLocPtr->num, clLocPtr->loc);
}
@@ -746,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.
@@ -756,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 Tcl_GetHashValue(hPtr);
}
/*
@@ -789,8 +782,7 @@ TclContinuationsGet(
*/
static void
-TclThreadFinalizeContLines(
- ClientData clientData)
+TclThreadFinalizeContLines (ClientData clientData)
{
/*
* Release the hashtable tracking invisible continuation lines.
@@ -801,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 --
@@ -831,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). */
{
@@ -918,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. */
{
register Tcl_HashEntry *hPtr;
- const Tcl_ObjType *typePtr = NULL;
+ Tcl_ObjType *typePtr = NULL;
Tcl_MutexLock(&tableMutex);
hPtr = Tcl_FindHashEntry(&typeTable, typeName);
if (hPtr != NULL) {
- typePtr = Tcl_GetHashValue(hPtr);
+ typePtr = (Tcl_ObjType *) Tcl_GetHashValue(hPtr);
}
Tcl_MutexUnlock(&tableMutex);
return typePtr;
@@ -958,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;
@@ -1053,13 +1075,13 @@ TclDbDumpActiveObjects(
void
TclDbInitNewObj(
register Tcl_Obj *objPtr,
- register 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. */
register int line) /* Line number in the source file; used for
* debugging. */
{
objPtr->refCount = 0;
- objPtr->bytes = &tclEmptyString;
+ objPtr->bytes = tclEmptyStringRep;
objPtr->length = 0;
objPtr->typePtr = NULL;
@@ -1077,11 +1099,12 @@ TclDbInitNewObj(
ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
if (tsdPtr->objThreadMap == NULL) {
- tsdPtr->objThreadMap = 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");
}
@@ -1090,7 +1113,7 @@ TclDbInitNewObj(
* Record the debugging information.
*/
- objData = ckalloc(sizeof(ObjData));
+ objData = (ObjData *) ckalloc(sizeof(ObjData));
objData->objPtr = objPtr;
objData->file = file;
objData->line = line;
@@ -1182,7 +1205,7 @@ Tcl_NewObj(void)
Tcl_Obj *
Tcl_DbNewObj(
- register 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. */
register int line) /* Line number in the source file; used for
* debugging. */
@@ -1200,7 +1223,7 @@ Tcl_DbNewObj(
Tcl_Obj *
Tcl_DbNewObj(
- 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. */
@@ -1249,12 +1272,12 @@ TclAllocateFreeObjects(void)
* Purify apparently can't figure that out, and fires a false alarm.
*/
- basePtr = 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++;
}
@@ -1291,7 +1314,7 @@ void
TclFreeObj(
register Tcl_Obj *objPtr) /* The object to be freed. */
{
- register const Tcl_ObjType *typePtr = objPtr->typePtr;
+ register Tcl_ObjType *typePtr = objPtr->typePtr;
/*
* This macro declares a variable, so must come here...
@@ -1324,7 +1347,7 @@ TclFreeObj(
ObjData *objData = Tcl_GetHashValue(hPtr);
if (objData != NULL) {
- ckfree(objData);
+ ckfree((char *) objData);
}
Tcl_DeleteHashEntry(hPtr);
@@ -1339,7 +1362,7 @@ 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
@@ -1348,11 +1371,9 @@ TclFreeObj(
*/
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 == -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 = -1;
@@ -1368,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);
TclFreeIntRep(objToFree);
Tcl_MutexLock(&tclObjMutex);
- ckfree(objToFree);
+ ckfree((char *) objToFree);
Tcl_MutexUnlock(&tclObjMutex);
TclIncrObjsFreed();
}
@@ -1389,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 un-initialized 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);
}
}
}
@@ -1416,11 +1436,9 @@ void
TclFreeObj(
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 = -1;
@@ -1464,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)) {
@@ -1480,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 un-initialized 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
/*
*----------------------------------------------------------------------
@@ -1527,6 +1543,7 @@ TclObjBeingDeleted(
{
return (objPtr->length == -1);
}
+
/*
*----------------------------------------------------------------------
@@ -1557,47 +1574,30 @@ TclObjBeingDeleted(
*----------------------------------------------------------------------
*/
-#define SetDuplicateObj(dupPtr, objPtr) \
- { \
- const Tcl_ObjType *typePtr = (objPtr)->typePtr; \
- const char *bytes = (objPtr)->bytes; \
- if (bytes) { \
- TclInitStringRep((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);
- TclFreeIntRep(dupPtr);
- SetDuplicateObj(dupPtr, objPtr);
+ return dupPtr;
}
/*
@@ -1630,29 +1630,11 @@ Tcl_GetString(
return objPtr->bytes;
}
- /*
- * 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. This panic was added in Tcl 8.1.
- */
-
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);
return objPtr->bytes;
}
@@ -1687,7 +1669,13 @@ Tcl_GetStringFromObj(
* rep's byte array length should * be stored.
* If NULL, no length is stored. */
{
- (void) TclGetString(objPtr);
+ if (objPtr->bytes == NULL) {
+ if (objPtr->typePtr->updateStringProc == NULL) {
+ Tcl_Panic("UpdateStringProc should not be invoked for type %s",
+ objPtr->typePtr->name);
+ }
+ (*objPtr->typePtr->updateStringProc)(objPtr);
+ }
if (lengthPtr != NULL) {
*lengthPtr = objPtr->length;
@@ -1720,6 +1708,7 @@ Tcl_InvalidateStringRep(
{
TclInvalidateStringRep(objPtr);
}
+
/*
*----------------------------------------------------------------------
@@ -1751,7 +1740,7 @@ Tcl_Obj *
Tcl_NewBooleanObj(
register int boolValue) /* Boolean used to initialize new object. */
{
- return Tcl_DbNewBooleanObj(boolValue, "unknown", 0);
+ return Tcl_DbNewLongObj(boolValue!=0, "unknown", 0);
}
#else /* if not TCL_MEM_DEBUG */
@@ -1762,7 +1751,7 @@ Tcl_NewBooleanObj(
{
register Tcl_Obj *objPtr;
- TclNewBooleanObj(objPtr, boolValue);
+ TclNewIntObj(objPtr, boolValue!=0);
return objPtr;
}
#endif /* TCL_MEM_DEBUG */
@@ -1799,7 +1788,7 @@ Tcl_NewBooleanObj(
Tcl_Obj *
Tcl_DbNewBooleanObj(
register int boolValue, /* Boolean used to initialize 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. */
@@ -1809,7 +1798,7 @@ Tcl_DbNewBooleanObj(
TclDbNewObj(objPtr, file, line);
objPtr->bytes = NULL;
- objPtr->internalRep.longValue = (boolValue != 0);
+ objPtr->internalRep.longValue = (boolValue? 1 : 0);
objPtr->typePtr = &tclIntType;
return objPtr;
}
@@ -1819,7 +1808,7 @@ Tcl_DbNewBooleanObj(
Tcl_Obj *
Tcl_DbNewBooleanObj(
register int boolValue, /* Boolean used to initialize 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. */
@@ -1856,7 +1845,7 @@ Tcl_SetBooleanObj(
Tcl_Panic("%s called with shared object", "Tcl_SetBooleanObj");
}
- TclSetBooleanObj(objPtr, boolValue);
+ TclSetIntObj(objPtr, boolValue!=0);
}
/*
@@ -1880,7 +1869,7 @@ Tcl_SetBooleanObj(
int
Tcl_GetBooleanFromObj(
- Tcl_Interp *interp, /* Used for error reporting if not NULL. */
+ 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. */
{
@@ -1902,7 +1891,7 @@ Tcl_GetBooleanFromObj(
* sets the proper error message for us.
*/
- double d;
+ double d;
if (Tcl_GetDoubleFromObj(interp, objPtr, &d) != TCL_OK) {
return TCL_ERROR;
@@ -1914,7 +1903,7 @@ Tcl_GetBooleanFromObj(
*boolPtr = 1;
return TCL_OK;
}
-#ifndef TCL_WIDE_INT_IS_LONG
+#ifndef NO_WIDE_TYPE
if (objPtr->typePtr == &tclWideIntType) {
*boolPtr = (objPtr->internalRep.wideValue != 0);
return TCL_OK;
@@ -1928,7 +1917,7 @@ Tcl_GetBooleanFromObj(
/*
*----------------------------------------------------------------------
*
- * TclSetBooleanFromAny --
+ * SetBooleanFromAny --
*
* Attempt to generate a boolean internal form for the Tcl object
* "objPtr".
@@ -1945,8 +1934,8 @@ Tcl_GetBooleanFromObj(
*----------------------------------------------------------------------
*/
-int
-TclSetBooleanFromAny(
+static int
+SetBooleanFromAny(
Tcl_Interp *interp, /* Used for error reporting if not NULL. */
register Tcl_Obj *objPtr) /* The object to convert. */
{
@@ -1969,7 +1958,7 @@ TclSetBooleanFromAny(
goto badBoolean;
}
-#ifndef TCL_WIDE_INT_IS_LONG
+#ifndef NO_WIDE_TYPE
if (objPtr->typePtr == &tclWideIntType) {
goto badBoolean;
}
@@ -1987,14 +1976,13 @@ TclSetBooleanFromAny(
badBoolean:
if (interp != NULL) {
int length;
- const char *str = TclGetStringFromObj(objPtr, &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", NULL);
}
return TCL_ERROR;
}
@@ -2003,16 +1991,11 @@ static int
ParseBoolean(
register Tcl_Obj *objPtr) /* The object to parse/convert. */
{
- int newBool;
- char lowerCase[6];
- const char *str = TclGetString(objPtr);
- size_t i, length = objPtr->length;
+ int i, length, newBool;
+ char lowerCase[6], *str = TclGetStringFromObj(objPtr, &length);
if ((length == 0) || (length > 5)) {
- /*
- * Longest valid boolean string rep. is "false".
- */
-
+ /* longest valid boolean string rep. is "false" */
return TCL_ERROR;
}
@@ -2038,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':
@@ -2058,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;
}
@@ -2085,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;
}
@@ -2192,7 +2174,7 @@ Tcl_NewDoubleObj(
Tcl_Obj *
Tcl_DbNewDoubleObj(
register double dblValue, /* Double used to initialize the 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. */
@@ -2212,7 +2194,7 @@ Tcl_DbNewDoubleObj(
Tcl_Obj *
Tcl_DbNewDoubleObj(
register double dblValue, /* Double used to initialize the 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. */
@@ -2273,7 +2255,7 @@ Tcl_SetDoubleObj(
int
Tcl_GetDoubleFromObj(
- Tcl_Interp *interp, /* Used for error reporting if not NULL. */
+ 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. */
{
@@ -2283,8 +2265,6 @@ Tcl_GetDoubleFromObj(
if (interp != NULL) {
Tcl_SetObjResult(interp, Tcl_NewStringObj(
"floating point value is Not a Number", -1));
- Tcl_SetErrorCode(interp, "TCL", "VALUE", "DOUBLE", "NAN",
- NULL);
}
return TCL_ERROR;
}
@@ -2297,12 +2277,11 @@ Tcl_GetDoubleFromObj(
}
if (objPtr->typePtr == &tclBignumType) {
mp_int big;
-
- UNPACK_BIGNUM(objPtr, big);
- *dblPtr = TclBignumToDouble(&big);
+ UNPACK_BIGNUM( objPtr, big );
+ *dblPtr = TclBignumToDouble( &big );
return TCL_OK;
}
-#ifndef TCL_WIDE_INT_IS_LONG
+#ifndef NO_WIDE_TYPE
if (objPtr->typePtr == &tclWideIntType) {
*dblPtr = (double) objPtr->internalRep.wideValue;
return TCL_OK;
@@ -2372,8 +2351,8 @@ UpdateStringOfDouble(
Tcl_PrintDouble(NULL, objPtr->internalRep.doubleValue, buffer);
len = strlen(buffer);
- objPtr->bytes = ckalloc(len + 1);
- memcpy(objPtr->bytes, buffer, (unsigned) len + 1);
+ objPtr->bytes = (char *) ckalloc((unsigned) len + 1);
+ strcpy(objPtr->bytes, buffer);
objPtr->length = len;
}
@@ -2407,8 +2386,8 @@ UpdateStringOfDouble(
*----------------------------------------------------------------------
*/
-#undef Tcl_NewIntObj
#ifdef TCL_MEM_DEBUG
+#undef Tcl_NewIntObj
Tcl_Obj *
Tcl_NewIntObj(
@@ -2425,7 +2404,7 @@ Tcl_NewIntObj(
{
register Tcl_Obj *objPtr;
- TclNewLongObj(objPtr, intValue);
+ TclNewIntObj(objPtr, intValue);
return objPtr;
}
#endif /* if TCL_MEM_DEBUG */
@@ -2448,7 +2427,6 @@ Tcl_NewIntObj(
*----------------------------------------------------------------------
*/
-#undef Tcl_SetIntObj
void
Tcl_SetIntObj(
register Tcl_Obj *objPtr, /* Object whose internal rep to init. */
@@ -2489,7 +2467,7 @@ Tcl_SetIntObj(
int
Tcl_GetIntFromObj(
- Tcl_Interp *interp, /* Used for error reporting if not NULL. */
+ 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. */
{
@@ -2503,7 +2481,7 @@ Tcl_GetIntFromObj(
}
if ((ULONG_MAX > UINT_MAX) && ((l > UINT_MAX) || (l < -(long)UINT_MAX))) {
if (interp != NULL) {
- const char *s =
+ 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, NULL);
@@ -2537,7 +2515,6 @@ SetIntFromAny(
Tcl_Obj *objPtr) /* Pointer to the object to convert */
{
long l;
-
return TclGetLongFromObj(interp, objPtr, &l);
}
@@ -2569,8 +2546,8 @@ UpdateStringOfInt(
len = TclFormatInt(buffer, objPtr->internalRep.longValue);
- objPtr->bytes = ckalloc(len + 1);
- memcpy(objPtr->bytes, buffer, (unsigned) len + 1);
+ objPtr->bytes = ckalloc((unsigned) len + 1);
+ strcpy(objPtr->bytes, buffer);
objPtr->length = len;
}
@@ -2667,7 +2644,7 @@ Tcl_Obj *
Tcl_DbNewLongObj(
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. */
@@ -2688,7 +2665,7 @@ Tcl_Obj *
Tcl_DbNewLongObj(
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. */
@@ -2751,7 +2728,7 @@ Tcl_SetLongObj(
int
Tcl_GetLongFromObj(
- Tcl_Interp *interp, /* Used for error reporting if not NULL. */
+ 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. */
{
@@ -2760,7 +2737,7 @@ Tcl_GetLongFromObj(
*longPtr = objPtr->internalRep.longValue;
return TCL_OK;
}
-#ifndef TCL_WIDE_INT_IS_LONG
+#ifndef NO_WIDE_TYPE
if (objPtr->typePtr == &tclWideIntType) {
/*
* We return any integer in the range -ULONG_MAX to ULONG_MAX
@@ -2771,7 +2748,6 @@ Tcl_GetLongFromObj(
*/
Tcl_WideInt w = objPtr->internalRep.wideValue;
-
if (w >= -(Tcl_WideInt)(ULONG_MAX)
&& w <= (Tcl_WideInt)(ULONG_MAX)) {
*longPtr = Tcl_WideAsLong(w);
@@ -2780,16 +2756,18 @@ Tcl_GetLongFromObj(
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", 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
@@ -2800,12 +2778,11 @@ Tcl_GetLongFromObj(
mp_int big;
UNPACK_BIGNUM(objPtr, big);
- if ((size_t) big.used <= (CHAR_BIT * sizeof(long) + DIGIT_BIT - 1)
+ 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;
-
+ 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++;
@@ -2818,7 +2795,7 @@ Tcl_GetLongFromObj(
return TCL_OK;
}
}
-#ifndef TCL_WIDE_INT_IS_LONG
+#ifndef NO_WIDE_TYPE
tooLarge:
#endif
if (interp != NULL) {
@@ -2834,7 +2811,7 @@ Tcl_GetLongFromObj(
TCL_PARSE_INTEGER_ONLY)==TCL_OK);
return TCL_ERROR;
}
-#ifndef TCL_WIDE_INT_IS_LONG
+#ifndef NO_WIDE_TYPE
/*
*----------------------------------------------------------------------
@@ -2872,11 +2849,11 @@ UpdateStringOfWideInt(
sprintf(buffer, "%" TCL_LL_MODIFIER "d", wideVal);
len = strlen(buffer);
- objPtr->bytes = ckalloc(len + 1);
+ objPtr->bytes = ckalloc((unsigned) len + 1);
memcpy(objPtr->bytes, buffer, len + 1);
objPtr->length = len;
}
-#endif /* !TCL_WIDE_INT_IS_LONG */
+#endif /* !NO_WIDE_TYPE */
/*
*----------------------------------------------------------------------
@@ -2970,7 +2947,7 @@ Tcl_DbNewWideIntObj(
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. */
@@ -2989,7 +2966,7 @@ Tcl_DbNewWideIntObj(
register Tcl_WideInt wideValue,
/* 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. */
@@ -3031,7 +3008,7 @@ Tcl_SetWideIntObj(
&& (wideValue <= (Tcl_WideInt) LONG_MAX)) {
TclSetLongObj(objPtr, (long) wideValue);
} else {
-#ifndef TCL_WIDE_INT_IS_LONG
+#ifndef NO_WIDE_TYPE
TclSetWideIntObj(objPtr, wideValue);
#else
mp_int big;
@@ -3065,13 +3042,13 @@ Tcl_SetWideIntObj(
int
Tcl_GetWideIntFromObj(
- Tcl_Interp *interp, /* Used for error reporting if not NULL. */
+ 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 {
-#ifndef TCL_WIDE_INT_IS_LONG
+#ifndef NO_WIDE_TYPE
if (objPtr->typePtr == &tclWideIntType) {
*wideIntPtr = objPtr->internalRep.wideValue;
return TCL_OK;
@@ -3081,16 +3058,18 @@ Tcl_GetWideIntFromObj(
*wideIntPtr = (Tcl_WideInt) objPtr->internalRep.longValue;
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", 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
* Tcl_WideInt, even when auto-narrowing is enabled.
@@ -3099,7 +3078,7 @@ Tcl_GetWideIntFromObj(
mp_int big;
UNPACK_BIGNUM(objPtr, big);
- if ((size_t) big.used <= (CHAR_BIT * sizeof(Tcl_WideInt)
+ 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);
@@ -3120,7 +3099,7 @@ Tcl_GetWideIntFromObj(
}
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, NULL);
@@ -3131,7 +3110,7 @@ Tcl_GetWideIntFromObj(
TCL_PARSE_INTEGER_ONLY)==TCL_OK);
return TCL_ERROR;
}
-#ifndef TCL_WIDE_INT_IS_LONG
+#ifndef NO_WIDE_TYPE
/*
*----------------------------------------------------------------------
@@ -3157,7 +3136,7 @@ SetWideIntFromAny(
Tcl_WideInt w;
return Tcl_GetWideIntFromObj(interp, objPtr, &w);
}
-#endif /* !TCL_WIDE_INT_IS_LONG */
+#endif /* !NO_WIDE_TYPE */
/*
*----------------------------------------------------------------------
@@ -3180,10 +3159,9 @@ FreeBignum(
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;
}
/*
@@ -3245,18 +3223,20 @@ UpdateStringOfBignum(
mp_int bignumVal;
int size;
int status;
- char *stringVal;
+ char* stringVal;
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.
@@ -3264,13 +3244,13 @@ UpdateStringOfBignum(
Tcl_Panic("UpdateStringOfBignum: string length limit exceeded");
}
- stringVal = ckalloc(size);
+ 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 NUL byte. */
+ objPtr->length = size - 1; /* size includes a trailing null byte */
}
/*
@@ -3303,7 +3283,7 @@ Tcl_Obj *
Tcl_NewBignumObj(
mp_int *bignumValue)
{
- Tcl_Obj *objPtr;
+ Tcl_Obj* objPtr;
TclNewObj(objPtr);
Tcl_SetBignumObj(objPtr, bignumValue);
@@ -3333,7 +3313,7 @@ Tcl_NewBignumObj(
Tcl_Obj *
Tcl_DbNewBignumObj(
mp_int *bignumValue,
- const char *file,
+ CONST char *file,
int line)
{
Tcl_Obj *objPtr;
@@ -3346,7 +3326,7 @@ Tcl_DbNewBignumObj(
Tcl_Obj *
Tcl_DbNewBignumObj(
mp_int *bignumValue,
- const char *file,
+ CONST char *file,
int line)
{
return Tcl_NewBignumObj(bignumValue);
@@ -3385,16 +3365,15 @@ GetBignumFromObj(
if (objPtr->typePtr == &tclBignumType) {
if (copy || Tcl_IsShared(objPtr)) {
mp_int temp;
-
UNPACK_BIGNUM(objPtr, temp);
mp_init_copy(bignumValue, &temp);
} else {
UNPACK_BIGNUM(objPtr, *bignumValue);
- objPtr->internalRep.twoPtrValue.ptr1 = NULL;
- objPtr->internalRep.twoPtrValue.ptr2 = NULL;
+ objPtr->internalRep.ptrAndLongRep.ptr = NULL;
+ objPtr->internalRep.ptrAndLongRep.value = 0;
objPtr->typePtr = NULL;
if (objPtr->bytes == NULL) {
- TclInitStringRep(objPtr, &tclEmptyString, 0);
+ TclInitStringRep(objPtr, tclEmptyStringRep, 0);
}
}
return TCL_OK;
@@ -3403,7 +3382,7 @@ GetBignumFromObj(
TclBNInitBignumFromLong(bignumValue, objPtr->internalRep.longValue);
return TCL_OK;
}
-#ifndef TCL_WIDE_INT_IS_LONG
+#ifndef NO_WIDE_TYPE
if (objPtr->typePtr == &tclWideIntType) {
TclBNInitBignumFromWideInt(bignumValue,
objPtr->internalRep.wideValue);
@@ -3412,10 +3391,12 @@ GetBignumFromObj(
#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", 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;
}
@@ -3518,12 +3499,11 @@ Tcl_SetBignumObj(
if (Tcl_IsShared(objPtr)) {
Tcl_Panic("%s called with shared object", "Tcl_SetBignumObj");
}
- if ((size_t) bignumValue->used
+ 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;
-
+ unsigned char *bytes = (unsigned char *)&scratch;
if (mp_to_unsigned_bin_n(bignumValue, bytes, &numBytes) != MP_OKAY) {
goto tooLargeForLong;
}
@@ -3542,14 +3522,13 @@ Tcl_SetBignumObj(
return;
}
tooLargeForLong:
-#ifndef TCL_WIDE_INT_IS_LONG
- if ((size_t) bignumValue->used
+#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;
}
@@ -3574,24 +3553,6 @@ Tcl_SetBignumObj(
TclSetBignumIntRep(objPtr, bignumValue);
}
-/*
- *----------------------------------------------------------------------
- *
- * TclSetBignumIntRep --
- *
- * 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
TclSetBignumIntRep(
Tcl_Obj *objPtr,
@@ -3602,9 +3563,8 @@ TclSetBignumIntRep(
/*
* 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;
@@ -3617,23 +3577,14 @@ TclSetBignumIntRep(
*
* TclGetNumberFromObj --
*
- * Extracts a number (of any possible numeric type) from an object.
- *
* 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
-TclGetNumberFromObj(
+int TclGetNumberFromObj(
Tcl_Interp *interp,
Tcl_Obj *objPtr,
ClientData *clientDataPtr,
@@ -3646,18 +3597,18 @@ TclGetNumberFromObj(
} else {
*typePtr = TCL_NUMBER_DOUBLE;
}
- *clientDataPtr = &objPtr->internalRep.doubleValue;
+ *clientDataPtr = &(objPtr->internalRep.doubleValue);
return TCL_OK;
}
if (objPtr->typePtr == &tclIntType) {
*typePtr = TCL_NUMBER_LONG;
- *clientDataPtr = &objPtr->internalRep.longValue;
+ *clientDataPtr = &(objPtr->internalRep.longValue);
return TCL_OK;
}
-#ifndef TCL_WIDE_INT_IS_LONG
+#ifndef NO_WIDE_TYPE
if (objPtr->typePtr == &tclWideIntType) {
*typePtr = TCL_NUMBER_WIDE;
- *clientDataPtr = &objPtr->internalRep.wideValue;
+ *clientDataPtr = &(objPtr->internalRep.wideValue);
return TCL_OK;
}
#endif
@@ -3665,8 +3616,7 @@ TclGetNumberFromObj(
static Tcl_ThreadDataKey bignumKey;
mp_int *bigPtr = Tcl_GetThreadData(&bignumKey,
(int) sizeof(mp_int));
-
- UNPACK_BIGNUM(objPtr, *bigPtr);
+ UNPACK_BIGNUM( objPtr, *bigPtr );
*typePtr = TCL_NUMBER_BIG;
*clientDataPtr = bigPtr;
return TCL_OK;
@@ -3701,7 +3651,7 @@ void
Tcl_DbIncrRefCount(
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. */
@@ -3721,21 +3671,23 @@ 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 */
-#endif /* TCL_MEM_DEBUG */
+# endif
+#endif
++(objPtr)->refCount;
}
@@ -3764,7 +3716,7 @@ void
Tcl_DbDecrRefCount(
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. */
@@ -3784,23 +3736,24 @@ 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 */
-#endif /* TCL_MEM_DEBUG */
-
- if (objPtr->refCount-- <= 1) {
+# endif
+#endif
+ if (--(objPtr)->refCount <= 0) {
TclFreeObj(objPtr);
}
}
@@ -3829,7 +3782,7 @@ Tcl_DbDecrRefCount(
int
Tcl_DbIsShared(
register Tcl_Obj *objPtr, /* The object to test for being shared. */
- 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. */
@@ -3849,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);
@@ -3875,7 +3829,7 @@ Tcl_DbIsShared(
tclObjsShared[0]++;
}
Tcl_MutexUnlock(&tclObjMutex);
-#endif /* TCL_COMPILE_STATS */
+#endif
return ((objPtr)->refCount > 1);
}
@@ -3929,10 +3883,11 @@ AllocObjEntry(
Tcl_HashTable *tablePtr, /* Hash table. */
void *keyPtr) /* Key to store in the hash table entry. */
{
- Tcl_Obj *objPtr = keyPtr;
- Tcl_HashEntry *hPtr = 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;
@@ -3961,17 +3916,18 @@ TclCompareObjKeys(
void *keyPtr, /* New key to compare. */
Tcl_HashEntry *hPtr) /* Existing key to compare. */
{
- Tcl_Obj *objPtr1 = keyPtr;
+ Tcl_Obj *objPtr1 = (Tcl_Obj *) keyPtr;
Tcl_Obj *objPtr2 = (Tcl_Obj *) hPtr->key.oneWordValue;
- register const char *p1, *p2;
- register size_t l1, l2;
+ 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
@@ -4024,7 +3980,7 @@ TclFreeObjEntry(
Tcl_Obj *objPtr = (Tcl_Obj *) hPtr->key.oneWordValue;
Tcl_DecrRefCount(objPtr);
- ckfree(hPtr);
+ ckfree((char *) hPtr);
}
/*
@@ -4045,15 +4001,16 @@ TclFreeObjEntry(
*----------------------------------------------------------------------
*/
-TCL_HASH_TYPE
+unsigned int
TclHashObjKey(
Tcl_HashTable *tablePtr, /* Hash table. */
void *keyPtr) /* Key from which to compute hash value. */
{
- Tcl_Obj *objPtr = keyPtr;
- int length;
- const char *string = TclGetStringFromObj(objPtr, &length);
+ 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
@@ -4063,39 +4020,18 @@ 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 (TCL_HASH_TYPE) result;
+ return result;
}
/*
@@ -4128,6 +4064,9 @@ Tcl_GetCommandFromObj(
* global namespace. */
{
register ResolvedCmdName *resPtr;
+ register Command *cmdPtr;
+ Namespace *refNsPtr;
+ int result;
/*
* Get the internal representation, converting to a command type if
@@ -4148,36 +4087,31 @@ Tcl_GetCommandFromObj(
* to discard the old rep and create a new one.
*/
- resPtr = objPtr->internalRep.twoPtrValue.ptr1;
- if (objPtr->typePtr == &tclCmdNameType) {
- register Command *cmdPtr = resPtr->cmdPtr;
-
- if ((cmdPtr->cmdEpoch == resPtr->cmdEpoch)
- && (interp == cmdPtr->nsPtr->interp)
- && !(cmdPtr->nsPtr->flags & NS_DYING)) {
- register 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 = objPtr->internalRep.twoPtrValue.ptr1;
- return (Tcl_Command) (resPtr ? resPtr->cmdPtr : NULL);
+ return (Tcl_Command) cmdPtr;
}
/*
@@ -4195,83 +4129,59 @@ Tcl_GetCommandFromObj(
* 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 = 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) {
- TclFreeIntRep(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. */
- 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. */
-{
- register ResolvedCmdName *resPtr;
+ currNsPtr = iPtr->varFramePtr->nsPtr;
- if (objPtr->typePtr == &tclCmdNameType) {
- resPtr = 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;
}
/*
@@ -4300,14 +4210,17 @@ FreeCmdNameInternalRep(
register Tcl_Obj *objPtr) /* CmdName object with internal
* representation to free. */
{
- register ResolvedCmdName *resPtr = 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
@@ -4315,10 +4228,10 @@ FreeCmdNameInternalRep(
*/
Command *cmdPtr = resPtr->cmdPtr;
-
TclCleanupCommandMacro(cmdPtr);
- ckfree(resPtr);
+ ckfree((char *) resPtr);
}
+ }
objPtr->typePtr = NULL;
}
@@ -4347,11 +4260,14 @@ DupCmdNameInternalRep(
Tcl_Obj *srcPtr, /* Object with internal rep to copy. */
register Tcl_Obj *copyPtr) /* Object with internal rep to set. */
{
- register ResolvedCmdName *resPtr = 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;
}
@@ -4381,8 +4297,10 @@ SetCmdNameFromAny(
Tcl_Interp *interp, /* Used for error reporting if not NULL. */
register Tcl_Obj *objPtr) /* The object to convert. */
{
- const char *name;
+ Interp *iPtr = (Interp *) interp;
+ char *name;
register Command *cmdPtr;
+ Namespace *currNsPtr;
register ResolvedCmdName *resPtr;
if (interp == NULL) {
@@ -4398,99 +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) {
- return TCL_ERROR;
- }
-
- resPtr = 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(
- ClientData clientData,
- Tcl_Interp *interp,
- int objc,
- Tcl_Obj *const objv[])
-{
- char ptrBuffer[2*TCL_INTEGER_SPACE+6];
- 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.
+ */
- sprintf(ptrBuffer, "%p", (void *) objv[1]);
- descObj = Tcl_ObjPrintf("value is a %s with a refcount of %d,"
- " object pointer at %s",
- objv[1]->typePtr ? objv[1]->typePtr->name : "pure string",
- objv[1]->refCount, ptrBuffer);
-
- if (objv[1]->typePtr) {
- sprintf(ptrBuffer, "%p:%p",
- (void *) objv[1]->internalRep.twoPtrValue.ptr1,
- (void *) objv[1]->internalRep.twoPtrValue.ptr2);
- Tcl_AppendPrintfToObj(descObj, ", internal representation %s",
- ptrBuffer);
- }
+ currNsPtr = iPtr->varFramePtr->nsPtr;
- if (objv[1]->bytes) {
- Tcl_AppendToObj(descObj, ", string representation \"", -1);
- Tcl_AppendLimitedToObj(descObj, objv[1]->bytes, objv[1]->length,
- 16, "...");
- Tcl_AppendToObj(descObj, "\"", -1);
+ resPtr->refNsPtr = currNsPtr;
+ resPtr->refNsId = currNsPtr->nsId;
+ resPtr->refNsCmdEpoch = currNsPtr->cmdRefEpoch;
+ }
} 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;
}
@@ -4499,7 +4379,5 @@ Tcl_RepresentationCmd(
* mode: c
* c-basic-offset: 4
* fill-column: 78
- * tab-width: 8
- * indent-tabs-mode: nil
* End:
*/