summaryrefslogtreecommitdiffstats
path: root/generic/tclLiteral.c
diff options
context:
space:
mode:
Diffstat (limited to 'generic/tclLiteral.c')
-rw-r--r--generic/tclLiteral.c467
1 files changed, 165 insertions, 302 deletions
diff --git a/generic/tclLiteral.c b/generic/tclLiteral.c
index 3966901..fb7c28a 100644
--- a/generic/tclLiteral.c
+++ b/generic/tclLiteral.c
@@ -7,8 +7,8 @@
* general hashtable implementation of Tcl hash tables that appears in
* tclHash.c.
*
- * Copyright © 1997-1998 Sun Microsystems, Inc.
- * Copyright © 2004 Kevin B. Kenny. All rights reserved.
+ * Copyright (c) 1997-1998 Sun Microsystems, Inc.
+ * Copyright (c) 2004 by Kevin B. Kenny. All rights reserved.
*
* See the file "license.terms" for information on usage and redistribution of
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
@@ -31,7 +31,7 @@
static int AddLocalLiteralEntry(CompileEnv *envPtr,
Tcl_Obj *objPtr, int localHash);
static void ExpandLocalLiteralArray(CompileEnv *envPtr);
-static unsigned HashString(const char *string, int length);
+static unsigned int HashString(const char *bytes, int length);
#ifdef TCL_COMPILE_DEBUG
static LiteralEntry * LookupLiteralEntry(Tcl_Interp *interp,
Tcl_Obj *objPtr);
@@ -58,12 +58,12 @@ static void RebuildLiteralTable(LiteralTable *tablePtr);
void
TclInitLiteralTable(
- LiteralTable *tablePtr)
+ register LiteralTable *tablePtr)
/* Pointer to table structure, which is
* supplied by the caller. */
{
#if (TCL_SMALL_HASH_TABLE != 4)
- Tcl_Panic("%s: TCL_SMALL_HASH_TABLE is %d, not 4", "TclInitLiteralTable",
+ Tcl_Panic("TclInitLiteralTable: TCL_SMALL_HASH_TABLE is %d, not 4",
TCL_SMALL_HASH_TABLE);
#endif
@@ -104,7 +104,7 @@ TclDeleteLiteralTable(
{
LiteralEntry *entryPtr, *nextPtr;
Tcl_Obj *objPtr;
- size_t i;
+ int i;
/*
* Release remaining literals in the table. Note that releasing a literal
@@ -114,8 +114,6 @@ TclDeleteLiteralTable(
#ifdef TCL_COMPILE_DEBUG
TclVerifyGlobalLiteralTable((Interp *) interp);
-#else
- (void)interp;
#endif /*TCL_COMPILE_DEBUG*/
/*
@@ -133,7 +131,7 @@ TclDeleteLiteralTable(
objPtr = entryPtr->objPtr;
TclDecrRefCount(objPtr);
nextPtr = entryPtr->nextPtr;
- ckfree(entryPtr);
+ ckfree((char *) entryPtr);
entryPtr = nextPtr;
}
}
@@ -143,7 +141,7 @@ TclDeleteLiteralTable(
*/
if (tablePtr->buckets != tablePtr->staticBuckets) {
- ckfree(tablePtr->buckets);
+ ckfree((char *) tablePtr->buckets);
}
}
@@ -159,16 +157,16 @@ TclDeleteLiteralTable(
*
* Results:
* The literal object. If it was created in this call *newPtr is set to
- * 1, else 0. NULL is returned if newPtr==NULL and no literal is found.
+ * 1, else 0. NULL is returned if newPtr==NULL and no literal is found.
*
* Side effects:
- * Increments the ref count of the global LiteralEntry since the caller
- * now holds a reference. If LITERAL_ON_HEAP is set in flags, this
- * function is given ownership of the string: if an object is created
- * then its string representation is set directly from string, otherwise
- * the string is freed. Typically, a caller sets LITERAL_ON_HEAP if
- * "string" is an already heap-allocated buffer holding the result of
- * backslash substitutions.
+ * Increments the ref count of the global LiteralEntry since the caller
+ * now holds a reference.
+ * If LITERAL_ON_HEAP is set in flags, this function is given ownership
+ * of the string: if an object is created then its string representation
+ * is set directly from string, otherwise the string is freed. Typically,
+ * a caller sets LITERAL_ON_HEAP if "string" is an already heap-allocated
+ * buffer holding the result of backslash substitutions.
*
*----------------------------------------------------------------------
*/
@@ -176,111 +174,81 @@ TclDeleteLiteralTable(
Tcl_Obj *
TclCreateLiteral(
Interp *iPtr,
- const char *bytes, /* The start of the string. Note that this is
- * not a NUL-terminated string. */
- int length, /* Number of bytes in the string. */
- unsigned hash, /* The string's hash. If -1, it will be
- * computed here. */
+ char *bytes,
+ int length,
+ unsigned int hash, /* The string's hash. If -1, it will be computed here */
int *newPtr,
Namespace *nsPtr,
int flags,
LiteralEntry **globalPtrPtr)
{
- LiteralTable *globalTablePtr = &iPtr->literalTable;
+ LiteralTable *globalTablePtr = &(iPtr->literalTable);
LiteralEntry *globalPtr;
- unsigned int globalHash;
+ int globalHash;
Tcl_Obj *objPtr;
/*
* Is it in the interpreter's global literal table?
*/
- if (hash == (unsigned) -1) {
+ if (hash == (unsigned int) -1) {
hash = HashString(bytes, length);
}
globalHash = (hash & globalTablePtr->mask);
for (globalPtr=globalTablePtr->buckets[globalHash] ; globalPtr!=NULL;
globalPtr = globalPtr->nextPtr) {
objPtr = globalPtr->objPtr;
- if (globalPtr->nsPtr == nsPtr) {
+ if ((globalPtr->nsPtr == nsPtr)
+ && (objPtr->length == length) && ((length == 0)
+ || ((objPtr->bytes[0] == bytes[0])
+ && (memcmp(objPtr->bytes, bytes, (unsigned) length) == 0)))) {
/*
- * Literals should always have UTF-8 representations... but this
- * is not guaranteed so we need to be careful anyway.
- *
- * https://stackoverflow.com/q/54337750/301832
+ * A literal was found: return it
*/
- int objLength;
- const char *objBytes = TclGetStringFromObj(objPtr, &objLength);
-
- if ((objLength == length) && ((length == 0)
- || ((objBytes[0] == bytes[0])
- && (memcmp(objBytes, bytes, length) == 0)))) {
- /*
- * A literal was found: return it
- */
-
- if (newPtr) {
- *newPtr = 0;
- }
- if (globalPtrPtr) {
- *globalPtrPtr = globalPtr;
- }
- if (flags & LITERAL_ON_HEAP) {
- ckfree(bytes);
- }
- if (globalPtr->refCount != TCL_INDEX_NONE) {
- globalPtr->refCount++;
- }
- return objPtr;
+ if (newPtr) {
+ *newPtr = 0;
+ }
+ if (globalPtrPtr) {
+ *globalPtrPtr = globalPtr;
+ }
+ if (flags & LITERAL_ON_HEAP) {
+ ckfree(bytes);
}
+ globalPtr->refCount++;
+ return objPtr;
}
}
if (!newPtr) {
- if ((flags & LITERAL_ON_HEAP)) {
+ if (flags & LITERAL_ON_HEAP) {
ckfree(bytes);
}
return NULL;
}
/*
- * The literal is new to the interpreter.
+ * The literal is new to the interpreter. Add it to the global literal
+ * table.
*/
TclNewObj(objPtr);
- if ((flags & LITERAL_ON_HEAP)) {
- objPtr->bytes = (char *) bytes;
+ Tcl_IncrRefCount(objPtr);
+ if (flags & LITERAL_ON_HEAP) {
+ objPtr->bytes = bytes;
objPtr->length = length;
} else {
TclInitStringRep(objPtr, bytes, length);
}
- /* Should the new literal be shared globally? */
-
- if ((flags & LITERAL_UNSHARED)) {
- /*
- * No, do *not* add it the global literal table
- * Make clear, that no global value is returned
- */
- if (globalPtrPtr != NULL) {
- *globalPtrPtr = NULL;
- }
- return objPtr;
- }
-
- /*
- * Yes, add it to the global literal table.
- */
#ifdef TCL_COMPILE_DEBUG
if (LookupLiteralEntry((Tcl_Interp *) iPtr, objPtr) != NULL) {
- Tcl_Panic("%s: literal \"%.*s\" found globally but shouldn't be",
- "TclRegisterLiteral", (length>60? 60 : length), bytes);
+ Tcl_Panic("TclRegisterLiteral: literal \"%.*s\" found globally but shouldn't be",
+ (length>60? 60 : length), bytes);
}
#endif
- globalPtr = (LiteralEntry *)ckalloc(sizeof(LiteralEntry));
+ globalPtr = (LiteralEntry *) ckalloc((unsigned) sizeof(LiteralEntry));
globalPtr->objPtr = objPtr;
- Tcl_IncrRefCount(objPtr);
globalPtr->refCount = 1;
globalPtr->nsPtr = nsPtr;
globalPtr->nextPtr = globalTablePtr->buckets[globalHash];
@@ -300,8 +268,7 @@ TclCreateLiteral(
TclVerifyGlobalLiteralTable(iPtr);
{
LiteralEntry *entryPtr;
- int found;
- size_t i;
+ int found, i;
found = 0;
for (i=0 ; i<globalTablePtr->numBuckets ; i++) {
@@ -313,8 +280,8 @@ TclCreateLiteral(
}
}
if (!found) {
- Tcl_Panic("%s: literal \"%.*s\" wasn't global",
- "TclRegisterLiteral", (length>60? 60 : length), bytes);
+ Tcl_Panic("TclRegisterLiteral: literal \"%.*s\" wasn't global",
+ (length>60? 60 : length), bytes);
}
}
#endif /*TCL_COMPILE_DEBUG*/
@@ -336,33 +303,6 @@ TclCreateLiteral(
/*
*----------------------------------------------------------------------
*
- * TclFetchLiteral --
- *
- * Fetch from a CompileEnv the literal value identified by an index
- * value, as returned by a prior call to TclRegisterLiteral().
- *
- * Results:
- * The literal value, or NULL if the index is out of range.
- *
- *----------------------------------------------------------------------
- */
-
-Tcl_Obj *
-TclFetchLiteral(
- CompileEnv *envPtr, /* Points to the CompileEnv from which to
- * fetch the registered literal value. */
- unsigned int index) /* Index of the desired literal, as returned
- * by prior call to TclRegisterLiteral() */
-{
- if (index >= (unsigned int) envPtr->literalArrayNext) {
- return NULL;
- }
- return envPtr->literalArrayPtr[index].objPtr;
-}
-
-/*
- *----------------------------------------------------------------------
- *
* TclRegisterLiteral --
*
* Find, or if necessary create, an object in a CompileEnv literal array
@@ -389,9 +329,9 @@ TclFetchLiteral(
int
TclRegisterLiteral(
- void *ePtr, /* Points to the CompileEnv in whose object
+ CompileEnv *envPtr, /* Points to the CompileEnv in whose object
* array an object is found or created. */
- const char *bytes, /* Points to string for which to find or
+ register char *bytes, /* Points to string for which to find or
* create an object in CompileEnv's object
* array. */
int length, /* Number of bytes in the string. If < 0, the
@@ -399,18 +339,16 @@ TclRegisterLiteral(
* first null character. */
int flags) /* If LITERAL_ON_HEAP then the caller already
* malloc'd bytes and ownership is passed to
- * this function. If LITERAL_CMD_NAME then
- * the literal should not be shared across
+ * this function. If LITERAL_NS_SCOPE then
+ * the literal shouldnot be shared accross
* namespaces. */
{
- CompileEnv *envPtr = (CompileEnv *)ePtr;
Interp *iPtr = envPtr->iPtr;
- LiteralTable *localTablePtr = &envPtr->localLitTable;
+ LiteralTable *localTablePtr = &(envPtr->localLitTable);
LiteralEntry *globalPtr, *localPtr;
Tcl_Obj *objPtr;
- unsigned hash;
- unsigned int localHash;
- int objIndex, isNew;
+ unsigned int hash;
+ int localHash, objIndex, new;
Namespace *nsPtr;
if (length < 0) {
@@ -429,8 +367,8 @@ TclRegisterLiteral(
objPtr = localPtr->objPtr;
if ((objPtr->length == length) && ((length == 0)
|| ((objPtr->bytes[0] == bytes[0])
- && (memcmp(objPtr->bytes, bytes, length) == 0)))) {
- if ((flags & LITERAL_ON_HEAP)) {
+ && (memcmp(objPtr->bytes, bytes, (unsigned) length) == 0)))) {
+ if (flags & LITERAL_ON_HEAP) {
ckfree(bytes);
}
objIndex = (localPtr - envPtr->literalArrayPtr);
@@ -443,18 +381,14 @@ TclRegisterLiteral(
}
/*
- * The literal is new to this CompileEnv. If it is a command name, avoid
- * sharing it across namespaces, and try not to share it with non-cmd
- * literals. Note that FQ command names can be shared, so that we register
- * the namespace as the interp's global NS.
+ * The literal is new to this CompileEnv. Should it be shared accross
+ * namespaces? If it is a fully qualified name, the namespace
+ * specification is not needed to avoid sharing.
*/
- if ((flags & LITERAL_CMD_NAME)) {
- if ((length >= 2) && (bytes[0] == ':') && (bytes[1] == ':')) {
- nsPtr = iPtr->globalNsPtr;
- } else {
- nsPtr = iPtr->varFramePtr->nsPtr;
- }
+ if ((flags & LITERAL_NS_SCOPE) && iPtr->varFramePtr
+ && ((length <2) || (bytes[0] != ':') || (bytes[1] != ':'))) {
+ nsPtr = iPtr->varFramePtr->nsPtr;
} else {
nsPtr = NULL;
}
@@ -463,16 +397,14 @@ TclRegisterLiteral(
* Is it in the interpreter's global literal table? If not, create it.
*/
- globalPtr = NULL;
- objPtr = TclCreateLiteral(iPtr, bytes, length, hash, &isNew, nsPtr, flags,
- &globalPtr);
+ objPtr = TclCreateLiteral(iPtr, bytes, length, hash, &new, nsPtr,
+ flags, &globalPtr);
objIndex = AddLocalLiteralEntry(envPtr, objPtr, localHash);
#ifdef TCL_COMPILE_DEBUG
- if (globalPtr != NULL && globalPtr->refCount + 1 < 2) {
- Tcl_Panic("%s: global literal \"%.*s\" had bad refCount %d",
- "TclRegisterLiteral", (length>60? 60 : length), bytes,
- globalPtr->refCount);
+ if (globalPtr->refCount < 1) {
+ Tcl_Panic("TclRegisterLiteral: global literal \"%.*s\" had bad refCount %d",
+ (length>60? 60 : length), bytes, globalPtr->refCount);
}
TclVerifyLocalLiteralTable(envPtr);
#endif /*TCL_COMPILE_DEBUG*/
@@ -501,14 +433,14 @@ static LiteralEntry *
LookupLiteralEntry(
Tcl_Interp *interp, /* Interpreter for which objPtr was created to
* hold a literal. */
- Tcl_Obj *objPtr) /* Points to a Tcl object holding a literal
+ register Tcl_Obj *objPtr) /* Points to a Tcl object holding a literal
* that was previously created by a call to
* TclRegisterLiteral. */
{
Interp *iPtr = (Interp *) interp;
- LiteralTable *globalTablePtr = &iPtr->literalTable;
- LiteralEntry *entryPtr;
- const char *bytes;
+ LiteralTable *globalTablePtr = &(iPtr->literalTable);
+ register LiteralEntry *entryPtr;
+ char *bytes;
int length, globalHash;
bytes = TclGetStringFromObj(objPtr, &length);
@@ -547,19 +479,18 @@ void
TclHideLiteral(
Tcl_Interp *interp, /* Interpreter for which objPtr was created to
* hold a literal. */
- CompileEnv *envPtr,/* Points to CompileEnv whose literal array
+ register CompileEnv *envPtr,/* Points to CompileEnv whose literal array
* contains the entry being hidden. */
int index) /* The index of the entry in the literal
* array. */
{
LiteralEntry **nextPtrPtr, *entryPtr, *lPtr;
- LiteralTable *localTablePtr = &envPtr->localLitTable;
- unsigned int localHash;
- int length;
- const char *bytes;
+ LiteralTable *localTablePtr = &(envPtr->localLitTable);
+ int localHash, length;
+ char *bytes;
Tcl_Obj *newObjPtr;
- lPtr = &envPtr->literalArrayPtr[index];
+ lPtr = &(envPtr->literalArrayPtr[index]);
/*
* To avoid unwanted sharing we need to copy the object and remove it from
@@ -574,7 +505,7 @@ TclHideLiteral(
lPtr->objPtr = newObjPtr;
bytes = TclGetStringFromObj(newObjPtr, &length);
- localHash = HashString(bytes, length) & localTablePtr->mask;
+ localHash = (HashString(bytes, length) & localTablePtr->mask);
nextPtrPtr = &localTablePtr->buckets[localHash];
for (entryPtr=*nextPtrPtr ; entryPtr!=NULL ; entryPtr=*nextPtrPtr) {
@@ -611,14 +542,14 @@ TclHideLiteral(
int
TclAddLiteralObj(
- CompileEnv *envPtr,/* Points to CompileEnv in whose literal array
+ register CompileEnv *envPtr,/* Points to CompileEnv in whose literal array
* the object is to be inserted. */
Tcl_Obj *objPtr, /* The object to insert into the array. */
LiteralEntry **litPtrPtr) /* The location where the pointer to the new
* literal entry should be stored. May be
* NULL. */
{
- LiteralEntry *lPtr;
+ register LiteralEntry *lPtr;
int objIndex;
if (envPtr->literalArrayNext >= envPtr->literalArrayEnd) {
@@ -627,10 +558,10 @@ TclAddLiteralObj(
objIndex = envPtr->literalArrayNext;
envPtr->literalArrayNext++;
- lPtr = &envPtr->literalArrayPtr[objIndex];
+ lPtr = &(envPtr->literalArrayPtr[objIndex]);
lPtr->objPtr = objPtr;
Tcl_IncrRefCount(objPtr);
- lPtr->refCount = TCL_INDEX_NONE; /* i.e., unused */
+ lPtr->refCount = -1; /* i.e., unused */
lPtr->nextPtr = NULL;
if (litPtrPtr) {
@@ -653,19 +584,19 @@ TclAddLiteralObj(
*
* Side effects:
* Expands the literal array if necessary. May rebuild the hash bucket
- * array of the CompileEnv's literal array if it becomes too large.
+ * array of the CompileEnv's literal array if it becomes too large.
*
*----------------------------------------------------------------------
*/
static int
AddLocalLiteralEntry(
- CompileEnv *envPtr,/* Points to CompileEnv in whose literal array
+ register CompileEnv *envPtr,/* Points to CompileEnv in whose literal array
* the object is to be inserted. */
- Tcl_Obj *objPtr, /* The literal to add to the CompileEnv. */
+ Tcl_Obj *objPtr, /* The literal to add to the CompileEnv. */
int localHash) /* Hash value for the literal's string. */
{
- LiteralTable *localTablePtr = &envPtr->localLitTable;
+ register LiteralTable *localTablePtr = &(envPtr->localLitTable);
LiteralEntry *localPtr;
int objIndex;
@@ -692,8 +623,7 @@ AddLocalLiteralEntry(
TclVerifyLocalLiteralTable(envPtr);
{
char *bytes;
- int length, found;
- size_t i;
+ int length, found, i;
found = 0;
for (i=0 ; i<localTablePtr->numBuckets ; i++) {
@@ -706,9 +636,9 @@ AddLocalLiteralEntry(
}
if (!found) {
- bytes = TclGetStringFromObj(objPtr, &length);
- Tcl_Panic("%s: literal \"%.*s\" wasn't found locally",
- "AddLocalLiteralEntry", (length>60? 60 : length), bytes);
+ bytes = Tcl_GetStringFromObj(objPtr, &length);
+ Tcl_Panic("AddLocalLiteralEntry: literal \"%.*s\" wasn't found locally",
+ (length>60? 60 : length), bytes);
}
}
#endif /*TCL_COMPILE_DEBUG*/
@@ -738,7 +668,7 @@ AddLocalLiteralEntry(
static void
ExpandLocalLiteralArray(
- CompileEnv *envPtr)/* Points to the CompileEnv whose object array
+ register CompileEnv *envPtr)/* Points to the CompileEnv whose object array
* must be enlarged. */
{
/*
@@ -746,28 +676,28 @@ ExpandLocalLiteralArray(
* 0 and (envPtr->literalArrayNext - 1) [inclusive].
*/
- LiteralTable *localTablePtr = &envPtr->localLitTable;
- size_t currElems = envPtr->literalArrayNext;
+ LiteralTable *localTablePtr = &(envPtr->localLitTable);
+ int currElems = envPtr->literalArrayNext;
size_t currBytes = (currElems * sizeof(LiteralEntry));
LiteralEntry *currArrayPtr = envPtr->literalArrayPtr;
LiteralEntry *newArrayPtr;
- size_t i;
- size_t newSize = (currBytes <= UINT_MAX / 2) ? 2*currBytes : UINT_MAX;
+ int i;
+ unsigned int newSize = (currBytes <= UINT_MAX / 2) ? 2*currBytes : UINT_MAX;
if (currBytes == newSize) {
- Tcl_Panic("max size of Tcl literal array (%" TCL_Z_MODIFIER "u literals) exceeded",
+ Tcl_Panic("max size of Tcl literal array (%d literals) exceeded",
currElems);
}
if (envPtr->mallocedLiteralArray) {
- newArrayPtr = (LiteralEntry *)ckrealloc(currArrayPtr, newSize);
+ newArrayPtr = (LiteralEntry *) ckrealloc(
+ (char *)currArrayPtr, newSize);
} else {
/*
* envPtr->literalArrayPtr isn't a ckalloc'd pointer, so we must
- * code a ckrealloc equivalent for ourselves.
+ * code a ckrealloc equivalent for ourselves
*/
-
- newArrayPtr = (LiteralEntry *)ckalloc(newSize);
+ newArrayPtr = (LiteralEntry *) ckalloc(newSize);
memcpy(newArrayPtr, currArrayPtr, currBytes);
envPtr->mallocedLiteralArray = 1;
}
@@ -820,22 +750,16 @@ void
TclReleaseLiteral(
Tcl_Interp *interp, /* Interpreter for which objPtr was created to
* hold a literal. */
- Tcl_Obj *objPtr) /* Points to a literal object that was
+ register Tcl_Obj *objPtr) /* Points to a literal object that was
* previously created by a call to
* TclRegisterLiteral. */
{
Interp *iPtr = (Interp *) interp;
- LiteralTable *globalTablePtr;
- LiteralEntry *entryPtr, *prevPtr;
- const char *bytes;
- int length;
- unsigned int index;
-
- if (iPtr == NULL) {
- goto done;
- }
+ LiteralTable *globalTablePtr = &(iPtr->literalTable);
+ register LiteralEntry *entryPtr, *prevPtr;
+ char *bytes;
+ int length, index;
- globalTablePtr = &iPtr->literalTable;
bytes = TclGetStringFromObj(objPtr, &length);
index = (HashString(bytes, length) & globalTablePtr->mask);
@@ -848,19 +772,21 @@ TclReleaseLiteral(
for (prevPtr=NULL, entryPtr=globalTablePtr->buckets[index];
entryPtr!=NULL ; prevPtr=entryPtr, entryPtr=entryPtr->nextPtr) {
if (entryPtr->objPtr == objPtr) {
+ entryPtr->refCount--;
+
/*
* If the literal is no longer being used by any ByteCode, delete
* the entry then remove the reference corresponding to the global
* literal table entry (decrement the ref count of the object).
*/
- if ((entryPtr->refCount != TCL_INDEX_NONE) && (entryPtr->refCount-- <= 1)) {
+ if (entryPtr->refCount == 0) {
if (prevPtr == NULL) {
globalTablePtr->buckets[index] = entryPtr->nextPtr;
} else {
prevPtr->nextPtr = entryPtr->nextPtr;
}
- ckfree(entryPtr);
+ ckfree((char *) entryPtr);
globalTablePtr->numEntries--;
TclDecrRefCount(objPtr);
@@ -877,7 +803,6 @@ TclReleaseLiteral(
* Remove the reference corresponding to the local literal table entry.
*/
- done:
Tcl_DecrRefCount(objPtr);
}
@@ -898,12 +823,13 @@ TclReleaseLiteral(
*----------------------------------------------------------------------
*/
-static unsigned
+static unsigned int
HashString(
- const char *string, /* String for which to compute hash value. */
+ register const char *bytes, /* String for which to compute hash value. */
int length) /* Number of bytes in the string. */
{
- unsigned int result = 0;
+ register unsigned int result;
+ register int i;
/*
* I tried a zillion different hash functions and asked many other people
@@ -913,33 +839,17 @@ HashString(
* 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 scripts tend to not have a big issue in this area, and literals
- * mostly aren't looked up by name anyway.
- *
- * See also HashStringKey in tclHash.c.
- * See also TclObjHashKey in tclObj.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);
- }
+ result = 0;
+ for (i=0 ; i<length ; i++) {
+ result += (result<<3) + bytes[i];
}
return result;
}
@@ -964,16 +874,16 @@ HashString(
static void
RebuildLiteralTable(
- LiteralTable *tablePtr)
+ register LiteralTable *tablePtr)
/* Local or global table to enlarge. */
{
LiteralEntry **oldBuckets;
- LiteralEntry **oldChainPtr, **newChainPtr;
- LiteralEntry *entryPtr;
+ register LiteralEntry **oldChainPtr, **newChainPtr;
+ register LiteralEntry *entryPtr;
LiteralEntry **bucketPtr;
- const char *bytes;
- unsigned int oldSize, index;
- int count, length;
+ char *bytes;
+ unsigned int oldSize;
+ int count, index, length;
oldSize = tablePtr->numBuckets;
oldBuckets = tablePtr->buckets;
@@ -994,8 +904,8 @@ RebuildLiteralTable(
}
tablePtr->numBuckets *= 4;
- tablePtr->buckets = (LiteralEntry **)ckalloc(
- tablePtr->numBuckets * sizeof(LiteralEntry*));
+ tablePtr->buckets = (LiteralEntry **) ckalloc((unsigned)
+ (tablePtr->numBuckets * sizeof(LiteralEntry *)));
for (count=tablePtr->numBuckets, newChainPtr=tablePtr->buckets;
count>0 ; count--, newChainPtr++) {
*newChainPtr = NULL;
@@ -1013,7 +923,7 @@ RebuildLiteralTable(
index = (HashString(bytes, length) & tablePtr->mask);
*oldChainPtr = entryPtr->nextPtr;
- bucketPtr = &tablePtr->buckets[index];
+ bucketPtr = &(tablePtr->buckets[index]);
entryPtr->nextPtr = *bucketPtr;
*bucketPtr = entryPtr;
}
@@ -1024,52 +934,7 @@ RebuildLiteralTable(
*/
if (oldBuckets != tablePtr->staticBuckets) {
- ckfree(oldBuckets);
- }
-}
-
-/*
- *----------------------------------------------------------------------
- *
- * TclInvalidateCmdLiteral --
- *
- * Invalidate a command literal entry, if present in the literal hash
- * tables, by resetting its internal representation. This invalidation
- * leaves it in the literal tables and in existing literal arrays. As a
- * result, existing references continue to work but we force a fresh
- * command look-up upon the next use (see, in particular,
- * TclSetCmdNameObj()).
- *
- * Results:
- * None.
- *
- * Side effects:
- * Resets the internal representation of the CmdName Tcl_Obj
- * using TclFreeInternalRep().
- *
- *----------------------------------------------------------------------
- */
-
-void
-TclInvalidateCmdLiteral(
- Tcl_Interp *interp, /* Interpreter for which to invalidate a
- * command literal. */
- const char *name, /* Points to the start of the cmd literal
- * name. */
- Namespace *nsPtr) /* The namespace for which to lookup and
- * invalidate a cmd literal. */
-{
- Interp *iPtr = (Interp *) interp;
- Tcl_Obj *literalObjPtr = TclCreateLiteral(iPtr, name,
- strlen(name), -1, NULL, nsPtr, 0, NULL);
-
- if (literalObjPtr != NULL) {
- if (TclHasInternalRep(literalObjPtr, &tclCmdNameType)) {
- TclFreeInternalRep(literalObjPtr);
- }
- /* Balance the refcount effects of TclCreateLiteral() above */
- Tcl_IncrRefCount(literalObjPtr);
- TclReleaseLiteral(interp, literalObjPtr);
+ ckfree((char *) oldBuckets);
}
}
@@ -1097,11 +962,9 @@ TclLiteralStats(
LiteralTable *tablePtr) /* Table for which to produce stats. */
{
#define NUM_COUNTERS 10
- size_t count[NUM_COUNTERS];
- int overflow;
- size_t i, j;
+ int count[NUM_COUNTERS], overflow, i, j;
double average, tmp;
- LiteralEntry *entryPtr;
+ register LiteralEntry *entryPtr;
char *result, *p;
/*
@@ -1133,19 +996,19 @@ TclLiteralStats(
* Print out the histogram and a few other pieces of information.
*/
- result = (char *)ckalloc(NUM_COUNTERS*60 + 300);
- snprintf(result, 60, "%d entries in table, %d buckets\n",
+ result = (char *) ckalloc((unsigned) ((NUM_COUNTERS*60) + 300));
+ sprintf(result, "%d entries in table, %d buckets\n",
tablePtr->numEntries, tablePtr->numBuckets);
p = result + strlen(result);
for (i=0 ; i<NUM_COUNTERS ; i++) {
- snprintf(p, 60, "number of buckets with %" TCL_Z_MODIFIER "u entries: %" TCL_Z_MODIFIER "u\n",
+ sprintf(p, "number of buckets with %d entries: %d\n",
i, count[i]);
p += strlen(p);
}
- snprintf(p, 60, "number of buckets with %d or more entries: %d\n",
+ sprintf(p, "number of buckets with %d or more entries: %d\n",
NUM_COUNTERS, overflow);
p += strlen(p);
- snprintf(p, 60, "average search distance for entry: %.1f", average);
+ sprintf(p, "average search distance for entry: %.1f", average);
return result;
}
#endif /*TCL_COMPILE_STATS*/
@@ -1172,33 +1035,36 @@ TclVerifyLocalLiteralTable(
CompileEnv *envPtr) /* Points to CompileEnv whose literal table is
* to be validated. */
{
- LiteralTable *localTablePtr = &envPtr->localLitTable;
- LiteralEntry *localPtr;
+ register LiteralTable *localTablePtr = &(envPtr->localLitTable);
+ register LiteralEntry *localPtr;
char *bytes;
- size_t i, count;
- int length;
+ register int i;
+ int length, count;
count = 0;
for (i=0 ; i<localTablePtr->numBuckets ; i++) {
for (localPtr=localTablePtr->buckets[i] ; localPtr!=NULL;
localPtr=localPtr->nextPtr) {
count++;
- if (localPtr->refCount != TCL_INDEX_NONE) {
- bytes = TclGetStringFromObj(localPtr->objPtr, &length);
- Tcl_Panic("%s: local literal \"%.*s\" had bad refCount %u",
- "TclVerifyLocalLiteralTable",
+ if (localPtr->refCount != -1) {
+ bytes = Tcl_GetStringFromObj(localPtr->objPtr, &length);
+ Tcl_Panic("TclVerifyLocalLiteralTable: local literal \"%.*s\" had bad refCount %d",
(length>60? 60 : length), bytes, localPtr->refCount);
}
+ if (LookupLiteralEntry((Tcl_Interp *) envPtr->iPtr,
+ localPtr->objPtr) == NULL) {
+ bytes = Tcl_GetStringFromObj(localPtr->objPtr, &length);
+ Tcl_Panic("TclVerifyLocalLiteralTable: local literal \"%.*s\" is not global",
+ (length>60? 60 : length), bytes);
+ }
if (localPtr->objPtr->bytes == NULL) {
- Tcl_Panic("%s: literal has NULL string rep",
- "TclVerifyLocalLiteralTable");
+ Tcl_Panic("TclVerifyLocalLiteralTable: literal has NULL string rep");
}
}
}
if (count != localTablePtr->numEntries) {
- Tcl_Panic("%s: local literal table had %" TCL_Z_MODIFIER "u entries, should be %u",
- "TclVerifyLocalLiteralTable", count,
- localTablePtr->numEntries);
+ Tcl_Panic("TclVerifyLocalLiteralTable: local literal table had %d entries, should be %d",
+ count, localTablePtr->numEntries);
}
}
@@ -1223,33 +1089,30 @@ TclVerifyGlobalLiteralTable(
Interp *iPtr) /* Points to interpreter whose global literal
* table is to be validated. */
{
- LiteralTable *globalTablePtr = &iPtr->literalTable;
- LiteralEntry *globalPtr;
+ register LiteralTable *globalTablePtr = &(iPtr->literalTable);
+ register LiteralEntry *globalPtr;
char *bytes;
- size_t i, count;
- int length;
+ register int i;
+ int length, count;
count = 0;
for (i=0 ; i<globalTablePtr->numBuckets ; i++) {
for (globalPtr=globalTablePtr->buckets[i] ; globalPtr!=NULL;
globalPtr=globalPtr->nextPtr) {
count++;
- if (globalPtr->refCount + 1 < 2) {
- bytes = TclGetStringFromObj(globalPtr->objPtr, &length);
- Tcl_Panic("%s: global literal \"%.*s\" had bad refCount %d",
- "TclVerifyGlobalLiteralTable",
+ if (globalPtr->refCount < 1) {
+ bytes = Tcl_GetStringFromObj(globalPtr->objPtr, &length);
+ Tcl_Panic("TclVerifyGlobalLiteralTable: global literal \"%.*s\" had bad refCount %d",
(length>60? 60 : length), bytes, globalPtr->refCount);
}
if (globalPtr->objPtr->bytes == NULL) {
- Tcl_Panic("%s: literal has NULL string rep",
- "TclVerifyGlobalLiteralTable");
+ Tcl_Panic("TclVerifyGlobalLiteralTable: literal has NULL string rep");
}
}
}
if (count != globalTablePtr->numEntries) {
- Tcl_Panic("%s: global literal table had %" TCL_Z_MODIFIER "u entries, should be %u",
- "TclVerifyGlobalLiteralTable", count,
- globalTablePtr->numEntries);
+ Tcl_Panic("TclVerifyGlobalLiteralTable: global literal table had %d entries, should be %d",
+ count, globalTablePtr->numEntries);
}
}
#endif /*TCL_COMPILE_DEBUG*/