OSDN Git Service

Please enter the commit message for your changes. Lines starting
[eos/base.git] / util / src / TclTk / tcl8.6.4 / generic / tclLiteral.c
diff --git a/util/src/TclTk/tcl8.6.4/generic/tclLiteral.c b/util/src/TclTk/tcl8.6.4/generic/tclLiteral.c
deleted file mode 100644 (file)
index 2b0cc7e..0000000
+++ /dev/null
@@ -1,1216 +0,0 @@
-/*
- * tclLiteral.c --
- *
- *     Implementation of the global and ByteCode-local literal tables used to
- *     manage the Tcl objects created for literal values during compilation
- *     of Tcl scripts. This implementation borrows heavily from the more
- *     general hashtable implementation of Tcl hash tables that appears in
- *     tclHash.c.
- *
- * 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.
- */
-
-#include "tclInt.h"
-#include "tclCompile.h"
-
-/*
- * When there are this many entries per bucket, on average, rebuild a
- * literal's hash table to make it larger.
- */
-
-#define REBUILD_MULTIPLIER     3
-
-/*
- * Function prototypes for static functions in this file:
- */
-
-static int             AddLocalLiteralEntry(CompileEnv *envPtr,
-                           Tcl_Obj *objPtr, int localHash);
-static void            ExpandLocalLiteralArray(CompileEnv *envPtr);
-static unsigned                HashString(const char *string, int length);
-#ifdef TCL_COMPILE_DEBUG
-static LiteralEntry *  LookupLiteralEntry(Tcl_Interp *interp,
-                           Tcl_Obj *objPtr);
-#endif
-static void            RebuildLiteralTable(LiteralTable *tablePtr);
-\f
-/*
- *----------------------------------------------------------------------
- *
- * TclInitLiteralTable --
- *
- *     This function is called to initialize the fields of a literal table
- *     structure for either an interpreter or a compilation's CompileEnv
- *     structure.
- *
- * Results:
- *     None.
- *
- * Side effects:
- *     The literal table is made ready for use.
- *
- *----------------------------------------------------------------------
- */
-
-void
-TclInitLiteralTable(
-    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_SMALL_HASH_TABLE);
-#endif
-
-    tablePtr->buckets = tablePtr->staticBuckets;
-    tablePtr->staticBuckets[0] = tablePtr->staticBuckets[1] = 0;
-    tablePtr->staticBuckets[2] = tablePtr->staticBuckets[3] = 0;
-    tablePtr->numBuckets = TCL_SMALL_HASH_TABLE;
-    tablePtr->numEntries = 0;
-    tablePtr->rebuildSize = TCL_SMALL_HASH_TABLE * REBUILD_MULTIPLIER;
-    tablePtr->mask = 3;
-}
-\f
-/*
- *----------------------------------------------------------------------
- *
- * TclDeleteLiteralTable --
- *
- *     This function frees up everything associated with a literal table
- *     except for the table's structure itself. It is called when the
- *     interpreter is deleted.
- *
- * Results:
- *     None.
- *
- * Side effects:
- *     Each literal in the table is released: i.e., its reference count in
- *     the global literal table is decremented and, if it becomes zero, the
- *     literal is freed. In addition, the table's bucket array is freed.
- *
- *----------------------------------------------------------------------
- */
-
-void
-TclDeleteLiteralTable(
-    Tcl_Interp *interp,                /* Interpreter containing shared literals
-                                * referenced by the table to delete. */
-    LiteralTable *tablePtr)    /* Points to the literal table to delete. */
-{
-    LiteralEntry *entryPtr, *nextPtr;
-    Tcl_Obj *objPtr;
-    int i;
-
-    /*
-     * Release remaining literals in the table. Note that releasing a literal
-     * might release other literals, modifying the table, so we restart the
-     * search from the bucket chain we last found an entry.
-     */
-
-#ifdef TCL_COMPILE_DEBUG
-    TclVerifyGlobalLiteralTable((Interp *) interp);
-#endif /*TCL_COMPILE_DEBUG*/
-
-    /*
-     * We used to call TclReleaseLiteral for each literal in the table, which
-     * is rather inefficient as it causes one lookup-by-hash for each
-     * reference to the literal. We now rely at interp-deletion on each
-     * bytecode object to release its references to the literal Tcl_Obj
-     * without requiring that it updates the global table itself, and deal
-     * here only with the table.
-     */
-
-    for (i=0 ; i<tablePtr->numBuckets ; i++) {
-       entryPtr = tablePtr->buckets[i];
-       while (entryPtr != NULL) {
-           objPtr = entryPtr->objPtr;
-           TclDecrRefCount(objPtr);
-           nextPtr = entryPtr->nextPtr;
-           ckfree(entryPtr);
-           entryPtr = nextPtr;
-       }
-    }
-
-    /*
-     * Free up the table's bucket array if it was dynamically allocated.
-     */
-
-    if (tablePtr->buckets != tablePtr->staticBuckets) {
-       ckfree(tablePtr->buckets);
-    }
-}
-\f
-/*
- *----------------------------------------------------------------------
- *
- * TclCreateLiteral --
- *
- *     Find, or if necessary create, an object in the interpreter's literal
- *     table that has a string representation matching the argument
- *     string. If nsPtr!=NULL then only literals stored for the namespace are
- *     considered.
- *
- * 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.
- *
- * 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.
- *
- *----------------------------------------------------------------------
- */
-
-Tcl_Obj *
-TclCreateLiteral(
-    Interp *iPtr,
-    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. */
-    int *newPtr,
-    Namespace *nsPtr,
-    int flags,
-    LiteralEntry **globalPtrPtr)
-{
-    LiteralTable *globalTablePtr = &iPtr->literalTable;
-    LiteralEntry *globalPtr;
-    int globalHash;
-    Tcl_Obj *objPtr;
-
-    /*
-     * Is it in the interpreter's global literal table?
-     */
-
-    if (hash == (unsigned) -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)
-               && (objPtr->length == length) && ((length == 0)
-               || ((objPtr->bytes[0] == bytes[0])
-               && (memcmp(objPtr->bytes, bytes, (unsigned) length) == 0)))) {
-           /*
-            * A literal was found: return it
-            */
-
-           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) {
-           ckfree(bytes);
-       }
-       return NULL;
-    }
-
-    /*
-     * The literal is new to the interpreter. Add it to the global literal
-     * table.
-     */
-
-    TclNewObj(objPtr);
-    Tcl_IncrRefCount(objPtr);
-    if (flags & LITERAL_ON_HEAP) {
-       objPtr->bytes = bytes;
-       objPtr->length = length;
-    } else {
-       TclInitStringRep(objPtr, bytes, length);
-    }
-
-#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);
-    }
-#endif
-
-    globalPtr = ckalloc(sizeof(LiteralEntry));
-    globalPtr->objPtr = objPtr;
-    globalPtr->refCount = 1;
-    globalPtr->nsPtr = nsPtr;
-    globalPtr->nextPtr = globalTablePtr->buckets[globalHash];
-    globalTablePtr->buckets[globalHash] = globalPtr;
-    globalTablePtr->numEntries++;
-
-    /*
-     * If the global literal table has exceeded a decent size, rebuild it with
-     * more buckets.
-     */
-
-    if (globalTablePtr->numEntries >= globalTablePtr->rebuildSize) {
-       RebuildLiteralTable(globalTablePtr);
-    }
-
-#ifdef TCL_COMPILE_DEBUG
-    TclVerifyGlobalLiteralTable(iPtr);
-    {
-       LiteralEntry *entryPtr;
-       int found, i;
-
-       found = 0;
-       for (i=0 ; i<globalTablePtr->numBuckets ; i++) {
-           for (entryPtr=globalTablePtr->buckets[i]; entryPtr!=NULL ;
-                   entryPtr=entryPtr->nextPtr) {
-               if ((entryPtr == globalPtr) && (entryPtr->objPtr == objPtr)) {
-                   found = 1;
-               }
-           }
-       }
-       if (!found) {
-           Tcl_Panic("%s: literal \"%.*s\" wasn't global",
-                   "TclRegisterLiteral", (length>60? 60 : length), bytes);
-       }
-    }
-#endif /*TCL_COMPILE_DEBUG*/
-
-#ifdef TCL_COMPILE_STATS
-    iPtr->stats.numLiteralsCreated++;
-    iPtr->stats.totalLitStringBytes += (double) (length + 1);
-    iPtr->stats.currentLitStringBytes += (double) (length + 1);
-    iPtr->stats.literalCount[TclLog2(length)]++;
-#endif /*TCL_COMPILE_STATS*/
-
-    if (globalPtrPtr) {
-       *globalPtrPtr = globalPtr;
-    }
-    *newPtr = 1;
-    return objPtr;
-}
-\f
-/*
- *----------------------------------------------------------------------
- *
- * 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;
-}
-\f
-/*
- *----------------------------------------------------------------------
- *
- * TclRegisterLiteral --
- *
- *     Find, or if necessary create, an object in a CompileEnv literal array
- *     that has a string representation matching the argument string.
- *
- * Results:
- *     The index in the CompileEnv's literal array that references a shared
- *     literal matching the string. The object is created if necessary.
- *
- * Side effects:
- *     To maximize sharing, we look up the string in the interpreter's global
- *     literal table. If not found, we create a new shared literal in the
- *     global table. We then add a reference to the shared literal in the
- *     CompileEnv's literal array.
- *
- *     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.
- *
- *----------------------------------------------------------------------
- */
-
-int
-TclRegisterLiteral(
-    void *ePtr,                /* Points to the CompileEnv in whose object
-                                * array an object is found or created. */
-    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
-                                * string consists of all bytes up to the
-                                * 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 accross
-                                * namespaces. */
-{
-    CompileEnv *envPtr = ePtr;
-    Interp *iPtr = envPtr->iPtr;
-    LiteralTable *localTablePtr = &envPtr->localLitTable;
-    LiteralEntry *globalPtr, *localPtr;
-    Tcl_Obj *objPtr;
-    unsigned hash;
-    int localHash, objIndex, new;
-    Namespace *nsPtr;
-
-    if (length < 0) {
-       length = (bytes ? strlen(bytes) : 0);
-    }
-    hash = HashString(bytes, length);
-
-    /*
-     * Is the literal already in the CompileEnv's local literal array? If so,
-     * just return its index.
-     */
-
-    localHash = (hash & localTablePtr->mask);
-    for (localPtr=localTablePtr->buckets[localHash] ; localPtr!=NULL;
-           localPtr = localPtr->nextPtr) {
-       objPtr = localPtr->objPtr;
-       if ((objPtr->length == length) && ((length == 0)
-               || ((objPtr->bytes[0] == bytes[0])
-               && (memcmp(objPtr->bytes, bytes, (unsigned) length) == 0)))) {
-           if (flags & LITERAL_ON_HEAP) {
-               ckfree(bytes);
-           }
-           objIndex = (localPtr - envPtr->literalArrayPtr);
-#ifdef TCL_COMPILE_DEBUG
-           TclVerifyLocalLiteralTable(envPtr);
-#endif /*TCL_COMPILE_DEBUG*/
-
-           return objIndex;
-       }
-    }
-
-    /*
-     * The literal is new to this CompileEnv. If it is a command name, avoid
-     * sharing it accross 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.
-     */
-
-    if (flags & LITERAL_CMD_NAME) {
-       if ((length >= 2) && (bytes[0] == ':') && (bytes[1] == ':')) {
-           nsPtr = iPtr->globalNsPtr;
-       } else {
-           nsPtr = iPtr->varFramePtr->nsPtr;
-       }
-    } else {
-       nsPtr = NULL;
-    }
-    
-    /*
-     * Is it in the interpreter's global literal table? If not, create it.
-     */
-
-    objPtr = TclCreateLiteral(iPtr, bytes, length, hash, &new, nsPtr, flags,
-           &globalPtr);
-    objIndex = AddLocalLiteralEntry(envPtr, objPtr, localHash);
-
-#ifdef TCL_COMPILE_DEBUG
-    if (globalPtr->refCount < 1) {
-       Tcl_Panic("%s: global literal \"%.*s\" had bad refCount %d",
-               "TclRegisterLiteral", (length>60? 60 : length), bytes,
-               globalPtr->refCount);
-    }
-    TclVerifyLocalLiteralTable(envPtr);
-#endif /*TCL_COMPILE_DEBUG*/
-    return objIndex;
-}
-\f
-#ifdef TCL_COMPILE_DEBUG
-/*
- *----------------------------------------------------------------------
- *
- * LookupLiteralEntry --
- *
- *     Finds the LiteralEntry that corresponds to a literal Tcl object
- *     holding a literal.
- *
- * Results:
- *     Returns the matching LiteralEntry if found, otherwise NULL.
- *
- * Side effects:
- *     None.
- *
- *----------------------------------------------------------------------
- */
-
-static LiteralEntry *
-LookupLiteralEntry(
-    Tcl_Interp *interp,                /* Interpreter for which objPtr was created to
-                                * hold 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;
-    register LiteralEntry *entryPtr;
-    const char *bytes;
-    int length, globalHash;
-
-    bytes = TclGetStringFromObj(objPtr, &length);
-    globalHash = (HashString(bytes, length) & globalTablePtr->mask);
-    for (entryPtr=globalTablePtr->buckets[globalHash] ; entryPtr!=NULL;
-           entryPtr=entryPtr->nextPtr) {
-       if (entryPtr->objPtr == objPtr) {
-           return entryPtr;
-       }
-    }
-    return NULL;
-}
-\f
-#endif
-/*
- *----------------------------------------------------------------------
- *
- * TclHideLiteral --
- *
- *     Remove a literal entry from the literal hash tables, leaving it in the
- *     literal array so existing references continue to function. This makes
- *     it possible to turn a shared literal into a private literal that
- *     cannot be shared.
- *
- * Results:
- *     None.
- *
- * Side effects:
- *     Removes the literal from the local hash table and decrements the
- *     global hash entry's reference count.
- *
- *----------------------------------------------------------------------
- */
-
-void
-TclHideLiteral(
-    Tcl_Interp *interp,                /* Interpreter for which objPtr was created to
-                                * hold a literal. */
-    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;
-    int localHash, length;
-    const char *bytes;
-    Tcl_Obj *newObjPtr;
-
-    lPtr = &envPtr->literalArrayPtr[index];
-
-    /*
-     * To avoid unwanted sharing we need to copy the object and remove it from
-     * the local and global literal tables. It still has a slot in the literal
-     * array so it can be referred to by byte codes, but it will not be
-     * matched by literal searches.
-     */
-
-    newObjPtr = Tcl_DuplicateObj(lPtr->objPtr);
-    Tcl_IncrRefCount(newObjPtr);
-    TclReleaseLiteral(interp, lPtr->objPtr);
-    lPtr->objPtr = newObjPtr;
-
-    bytes = TclGetStringFromObj(newObjPtr, &length);
-    localHash = (HashString(bytes, length) & localTablePtr->mask);
-    nextPtrPtr = &localTablePtr->buckets[localHash];
-
-    for (entryPtr=*nextPtrPtr ; entryPtr!=NULL ; entryPtr=*nextPtrPtr) {
-       if (entryPtr == lPtr) {
-           *nextPtrPtr = lPtr->nextPtr;
-           lPtr->nextPtr = NULL;
-           localTablePtr->numEntries--;
-           break;
-       }
-       nextPtrPtr = &entryPtr->nextPtr;
-    }
-}
-\f
-/*
- *----------------------------------------------------------------------
- *
- * TclAddLiteralObj --
- *
- *     Add a single literal object to the literal array. This function does
- *     not add the literal to the local or global literal tables. The caller
- *     is expected to add the entry to whatever tables are appropriate.
- *
- * Results:
- *     The index in the CompileEnv's literal array that references the
- *     literal. Stores the pointer to the new literal entry in the location
- *     referenced by the localPtrPtr argument.
- *
- * Side effects:
- *     Expands the literal array if necessary. Increments the refcount on the
- *     literal object.
- *
- *----------------------------------------------------------------------
- */
-
-int
-TclAddLiteralObj(
-    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. */
-{
-    register LiteralEntry *lPtr;
-    int objIndex;
-
-    if (envPtr->literalArrayNext >= envPtr->literalArrayEnd) {
-       ExpandLocalLiteralArray(envPtr);
-    }
-    objIndex = envPtr->literalArrayNext;
-    envPtr->literalArrayNext++;
-
-    lPtr = &envPtr->literalArrayPtr[objIndex];
-    lPtr->objPtr = objPtr;
-    Tcl_IncrRefCount(objPtr);
-    lPtr->refCount = -1;       /* i.e., unused */
-    lPtr->nextPtr = NULL;
-
-    if (litPtrPtr) {
-       *litPtrPtr = lPtr;
-    }
-
-    return objIndex;
-}
-\f
-/*
- *----------------------------------------------------------------------
- *
- * AddLocalLiteralEntry --
- *
- *     Insert a new literal into a CompileEnv's local literal array.
- *
- * Results:
- *     The index in the CompileEnv's literal array that references the
- *     literal.
- *
- * 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.
- *
- *----------------------------------------------------------------------
- */
-
-static int
-AddLocalLiteralEntry(
-    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. */
-    int localHash)             /* Hash value for the literal's string. */
-{
-    register LiteralTable *localTablePtr = &envPtr->localLitTable;
-    LiteralEntry *localPtr;
-    int objIndex;
-
-    objIndex = TclAddLiteralObj(envPtr, objPtr, &localPtr);
-
-    /*
-     * Add the literal to the local table.
-     */
-
-    localPtr->nextPtr = localTablePtr->buckets[localHash];
-    localTablePtr->buckets[localHash] = localPtr;
-    localTablePtr->numEntries++;
-
-    /*
-     * If the CompileEnv's local literal table has exceeded a decent size,
-     * rebuild it with more buckets.
-     */
-
-    if (localTablePtr->numEntries >= localTablePtr->rebuildSize) {
-       RebuildLiteralTable(localTablePtr);
-    }
-
-#ifdef TCL_COMPILE_DEBUG
-    TclVerifyLocalLiteralTable(envPtr);
-    {
-       char *bytes;
-       int length, found, i;
-
-       found = 0;
-       for (i=0 ; i<localTablePtr->numBuckets ; i++) {
-           for (localPtr=localTablePtr->buckets[i] ; localPtr!=NULL ;
-                   localPtr=localPtr->nextPtr) {
-               if (localPtr->objPtr == objPtr) {
-                   found = 1;
-               }
-           }
-       }
-
-       if (!found) {
-           bytes = Tcl_GetStringFromObj(objPtr, &length);
-           Tcl_Panic("%s: literal \"%.*s\" wasn't found locally",
-                   "AddLocalLiteralEntry", (length>60? 60 : length), bytes);
-       }
-    }
-#endif /*TCL_COMPILE_DEBUG*/
-
-    return objIndex;
-}
-\f
-/*
- *----------------------------------------------------------------------
- *
- * ExpandLocalLiteralArray --
- *
- *     Function that uses malloc to allocate more storage for a CompileEnv's
- *     local literal array.
- *
- * Results:
- *     None.
- *
- * Side effects:
- *     The literal array in *envPtr is reallocated to a new array of double
- *     the size, and if envPtr->mallocedLiteralArray is non-zero the old
- *     array is freed. Entries are copied from the old array to the new one.
- *     The local literal table is updated to refer to the new entries.
- *
- *----------------------------------------------------------------------
- */
-
-static void
-ExpandLocalLiteralArray(
-    register CompileEnv *envPtr)/* Points to the CompileEnv whose object array
-                                * must be enlarged. */
-{
-    /*
-     * The current allocated local literal entries are stored between elements
-     * 0 and (envPtr->literalArrayNext - 1) [inclusive].
-     */
-
-    LiteralTable *localTablePtr = &envPtr->localLitTable;
-    int currElems = envPtr->literalArrayNext;
-    size_t currBytes = (currElems * sizeof(LiteralEntry));
-    LiteralEntry *currArrayPtr = envPtr->literalArrayPtr;
-    LiteralEntry *newArrayPtr;
-    int i;
-
-    if (envPtr->mallocedLiteralArray) {
-       newArrayPtr = ckrealloc(currArrayPtr, 2 * currBytes);
-    } else {
-       /*
-        * envPtr->literalArrayPtr isn't a ckalloc'd pointer, so we must
-        * code a ckrealloc equivalent for ourselves.
-        */
-
-       newArrayPtr = ckalloc(2 * currBytes);
-       memcpy(newArrayPtr, currArrayPtr, currBytes);
-       envPtr->mallocedLiteralArray = 1;
-    }
-
-    /*
-     * Update the local literal table's bucket array.
-     */
-
-    if (currArrayPtr != newArrayPtr) {
-       for (i=0 ; i<currElems ; i++) {
-           if (newArrayPtr[i].nextPtr != NULL) {
-               newArrayPtr[i].nextPtr = newArrayPtr
-                       + (newArrayPtr[i].nextPtr - currArrayPtr);
-           }
-       }
-       for (i=0 ; i<localTablePtr->numBuckets ; i++) {
-           if (localTablePtr->buckets[i] != NULL) {
-               localTablePtr->buckets[i] = newArrayPtr
-                       + (localTablePtr->buckets[i] - currArrayPtr);
-           }
-       }
-    }
-
-    envPtr->literalArrayPtr = newArrayPtr;
-    envPtr->literalArrayEnd = (2 * currElems);
-}
-\f
-/*
- *----------------------------------------------------------------------
- *
- * TclReleaseLiteral --
- *
- *     This function releases a reference to one of the shared Tcl objects
- *     that hold literals. It is called to release the literals referenced by
- *     a ByteCode that is being destroyed, and it is also called by
- *     TclDeleteLiteralTable.
- *
- * Results:
- *     None.
- *
- * Side effects:
- *     The reference count for the global LiteralTable entry that corresponds
- *     to the literal is decremented. If no other reference to a global
- *     literal object remains, it is freed.
- *
- *----------------------------------------------------------------------
- */
-
-void
-TclReleaseLiteral(
-    Tcl_Interp *interp,                /* Interpreter for which objPtr was created to
-                                * hold a literal. */
-    register Tcl_Obj *objPtr)  /* Points to a literal object that was
-                                * previously created by a call to
-                                * TclRegisterLiteral. */
-{
-    Interp *iPtr = (Interp *) interp;
-    LiteralTable *globalTablePtr;
-    register LiteralEntry *entryPtr, *prevPtr;
-    const char *bytes;
-    int length, index;
-
-    if (iPtr == NULL) {
-       goto done;
-    }
-
-    globalTablePtr = &iPtr->literalTable;
-    bytes = TclGetStringFromObj(objPtr, &length);
-    index = (HashString(bytes, length) & globalTablePtr->mask);
-
-    /*
-     * Check to see if the object is in the global literal table and remove
-     * this reference. The object may not be in the table if it is a hidden
-     * local literal.
-     */
-
-    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 == 0) {
-               if (prevPtr == NULL) {
-                   globalTablePtr->buckets[index] = entryPtr->nextPtr;
-               } else {
-                   prevPtr->nextPtr = entryPtr->nextPtr;
-               }
-               ckfree(entryPtr);
-               globalTablePtr->numEntries--;
-
-               TclDecrRefCount(objPtr);
-
-#ifdef TCL_COMPILE_STATS
-               iPtr->stats.currentLitStringBytes -= (double) (length + 1);
-#endif /*TCL_COMPILE_STATS*/
-           }
-           break;
-       }
-    }
-
-    /*
-     * Remove the reference corresponding to the local literal table entry.
-     */
-
-    done:
-    Tcl_DecrRefCount(objPtr);
-}
-\f
-/*
- *----------------------------------------------------------------------
- *
- * HashString --
- *
- *     Compute a one-word summary of a text string, which can be used to
- *     generate a hash index.
- *
- * Results:
- *     The return value is a one-word summary of the information in string.
- *
- * Side effects:
- *     None.
- *
- *----------------------------------------------------------------------
- */
-
-static unsigned
-HashString(
-    register const char *string,       /* String for which to compute hash value. */
-    int length)                        /* Number of bytes in the string. */
-{
-    register unsigned int result = 0;
-
-    /*
-     * I tried a zillion different hash functions and asked many other people
-     * for advice. Many people had their own favorite functions, all
-     * different, but no-one had much idea why they were good ones. I chose
-     * the one below (multiply by 9 and add new character) because of the
-     * following reasons:
-     *
-     * 1. Multiplying by 10 is perfect for keys that are decimal strings, and
-     *    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]
-     */
-
-    if (length > 0) {
-       result = UCHAR(*string);
-       while (--length) {
-           result += (result << 3) + UCHAR(*++string);
-       }
-    }
-    return result;
-}
-\f
-/*
- *----------------------------------------------------------------------
- *
- * RebuildLiteralTable --
- *
- *     This function is invoked when the ratio of entries to hash buckets
- *     becomes too large in a local or global literal table. It allocates a
- *     larger bucket array and moves the entries into the new buckets.
- *
- * Results:
- *     None.
- *
- * Side effects:
- *     Memory gets reallocated and entries get rehashed into new buckets.
- *
- *----------------------------------------------------------------------
- */
-
-static void
-RebuildLiteralTable(
-    register LiteralTable *tablePtr)
-                               /* Local or global table to enlarge. */
-{
-    LiteralEntry **oldBuckets;
-    register LiteralEntry **oldChainPtr, **newChainPtr;
-    register LiteralEntry *entryPtr;
-    LiteralEntry **bucketPtr;
-    const char *bytes;
-    int oldSize, count, index, length;
-
-    oldSize = tablePtr->numBuckets;
-    oldBuckets = tablePtr->buckets;
-
-    /*
-     * Allocate and initialize the new bucket array, and set up hashing
-     * constants for new array size.
-     */
-
-    tablePtr->numBuckets *= 4;
-    tablePtr->buckets = ckalloc(tablePtr->numBuckets * sizeof(LiteralEntry*));
-    for (count=tablePtr->numBuckets, newChainPtr=tablePtr->buckets;
-           count>0 ; count--, newChainPtr++) {
-       *newChainPtr = NULL;
-    }
-    tablePtr->rebuildSize *= 4;
-    tablePtr->mask = (tablePtr->mask << 2) + 3;
-
-    /*
-     * Rehash all of the existing entries into the new bucket array.
-     */
-
-    for (oldChainPtr=oldBuckets ; oldSize>0 ; oldSize--,oldChainPtr++) {
-       for (entryPtr=*oldChainPtr ; entryPtr!=NULL ; entryPtr=*oldChainPtr) {
-           bytes = TclGetStringFromObj(entryPtr->objPtr, &length);
-           index = (HashString(bytes, length) & tablePtr->mask);
-
-           *oldChainPtr = entryPtr->nextPtr;
-           bucketPtr = &tablePtr->buckets[index];
-           entryPtr->nextPtr = *bucketPtr;
-           *bucketPtr = entryPtr;
-       }
-    }
-
-    /*
-     * Free up the old bucket array, if it was dynamically allocated.
-     */
-
-    if (oldBuckets != tablePtr->staticBuckets) {
-       ckfree(oldBuckets);
-    }
-}
-\f
-/*
- *----------------------------------------------------------------------
- *
- * 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 TclFreeIntRep().
- *
- *----------------------------------------------------------------------
- */
-
-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, (char *) name,
-           strlen(name), -1, NULL, nsPtr, 0, NULL);
-
-    if (literalObjPtr != NULL) {
-       if (literalObjPtr->typePtr == &tclCmdNameType) {
-           TclFreeIntRep(literalObjPtr);
-       }
-       /* Balance the refcount effects of TclCreateLiteral() above */
-       Tcl_IncrRefCount(literalObjPtr);
-       TclReleaseLiteral(interp, literalObjPtr);
-    }
-}
-\f
-#ifdef TCL_COMPILE_STATS
-/*
- *----------------------------------------------------------------------
- *
- * TclLiteralStats --
- *
- *     Return statistics describing the layout of the hash table in its hash
- *     buckets.
- *
- * Results:
- *     The return value is a malloc-ed string containing information about
- *     tablePtr. It is the caller's responsibility to free this string.
- *
- * Side effects:
- *     None.
- *
- *----------------------------------------------------------------------
- */
-
-char *
-TclLiteralStats(
-    LiteralTable *tablePtr)    /* Table for which to produce stats. */
-{
-#define NUM_COUNTERS 10
-    int count[NUM_COUNTERS], overflow, i, j;
-    double average, tmp;
-    register LiteralEntry *entryPtr;
-    char *result, *p;
-
-    /*
-     * Compute a histogram of bucket usage. For each bucket chain i, j is the
-     * number of entries in the chain.
-     */
-
-    for (i=0 ; i<NUM_COUNTERS ; i++) {
-       count[i] = 0;
-    }
-    overflow = 0;
-    average = 0.0;
-    for (i=0 ; i<tablePtr->numBuckets ; i++) {
-       j = 0;
-       for (entryPtr=tablePtr->buckets[i] ; entryPtr!=NULL;
-               entryPtr=entryPtr->nextPtr) {
-           j++;
-       }
-       if (j < NUM_COUNTERS) {
-           count[j]++;
-       } else {
-           overflow++;
-       }
-       tmp = j;
-       average += (tmp+1.0)*(tmp/tablePtr->numEntries)/2.0;
-    }
-
-    /*
-     * Print out the histogram and a few other pieces of information.
-     */
-
-    result = ckalloc(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++) {
-       sprintf(p, "number of buckets with %d entries: %d\n",
-               i, count[i]);
-       p += strlen(p);
-    }
-    sprintf(p, "number of buckets with %d or more entries: %d\n",
-           NUM_COUNTERS, overflow);
-    p += strlen(p);
-    sprintf(p, "average search distance for entry: %.1f", average);
-    return result;
-}
-#endif /*TCL_COMPILE_STATS*/
-\f
-#ifdef TCL_COMPILE_DEBUG
-/*
- *----------------------------------------------------------------------
- *
- * TclVerifyLocalLiteralTable --
- *
- *     Check a CompileEnv's local literal table for consistency.
- *
- * Results:
- *     None.
- *
- * Side effects:
- *     Tcl_Panic if problems are found.
- *
- *----------------------------------------------------------------------
- */
-
-void
-TclVerifyLocalLiteralTable(
-    CompileEnv *envPtr)                /* Points to CompileEnv whose literal table is
-                                * to be validated. */
-{
-    register LiteralTable *localTablePtr = &envPtr->localLitTable;
-    register LiteralEntry *localPtr;
-    char *bytes;
-    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 != -1) {
-               bytes = Tcl_GetStringFromObj(localPtr->objPtr, &length);
-               Tcl_Panic("%s: local literal \"%.*s\" had bad refCount %d",
-                       "TclVerifyLocalLiteralTable",
-                       (length>60? 60 : length), bytes, localPtr->refCount);
-           }
-           if (LookupLiteralEntry((Tcl_Interp *) envPtr->iPtr,
-                   localPtr->objPtr) == NULL) {
-               bytes = Tcl_GetStringFromObj(localPtr->objPtr, &length);
-               Tcl_Panic("%s: local literal \"%.*s\" is not global",
-                       "TclVerifyLocalLiteralTable",
-                       (length>60? 60 : length), bytes);
-           }
-           if (localPtr->objPtr->bytes == NULL) {
-               Tcl_Panic("%s: literal has NULL string rep",
-                       "TclVerifyLocalLiteralTable");
-           }
-       }
-    }
-    if (count != localTablePtr->numEntries) {
-       Tcl_Panic("%s: local literal table had %d entries, should be %d",
-               "TclVerifyLocalLiteralTable", count,
-               localTablePtr->numEntries);
-    }
-}
-\f
-/*
- *----------------------------------------------------------------------
- *
- * TclVerifyGlobalLiteralTable --
- *
- *     Check an interpreter's global literal table literal for consistency.
- *
- * Results:
- *     None.
- *
- * Side effects:
- *     Tcl_Panic if problems are found.
- *
- *----------------------------------------------------------------------
- */
-
-void
-TclVerifyGlobalLiteralTable(
-    Interp *iPtr)              /* Points to interpreter whose global literal
-                                * table is to be validated. */
-{
-    register LiteralTable *globalTablePtr = &iPtr->literalTable;
-    register LiteralEntry *globalPtr;
-    char *bytes;
-    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) {
-               bytes = Tcl_GetStringFromObj(globalPtr->objPtr, &length);
-               Tcl_Panic("%s: global literal \"%.*s\" had bad refCount %d",
-                       "TclVerifyGlobalLiteralTable",
-                       (length>60? 60 : length), bytes, globalPtr->refCount);
-           }
-           if (globalPtr->objPtr->bytes == NULL) {
-               Tcl_Panic("%s: literal has NULL string rep",
-                       "TclVerifyGlobalLiteralTable");
-           }
-       }
-    }
-    if (count != globalTablePtr->numEntries) {
-       Tcl_Panic("%s: global literal table had %d entries, should be %d",
-               "TclVerifyGlobalLiteralTable", count,
-               globalTablePtr->numEntries);
-    }
-}
-#endif /*TCL_COMPILE_DEBUG*/
-\f
-/*
- * Local Variables:
- * mode: c
- * c-basic-offset: 4
- * fill-column: 78
- * End:
- */