⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tclliteral.c

📁 tcl是工具命令语言
💻 C
📖 第 1 页 / 共 3 页
字号:
	    if (entryPtr->refCount == 0) {		if (prevPtr == NULL) {		    globalTablePtr->buckets[index] = entryPtr->nextPtr;		} else {		    prevPtr->nextPtr = entryPtr->nextPtr;		}		ckfree((char *) entryPtr);		globalTablePtr->numEntries--;		TclDecrRefCount(objPtr);		/*		 * Check if the LiteralEntry is only being kept alive by 		 * a circular reference from a ByteCode stored as its 		 * internal rep. In that case, set the ByteCode object array 		 * entry NULL to signal to TclCleanupByteCode to not try to 		 * release this about to be freed literal again.		 */	    		if (objPtr->typePtr == &tclByteCodeType) {		    codePtr = (ByteCode *) objPtr->internalRep.otherValuePtr;		    if ((codePtr->numLitObjects == 1)		            && (codePtr->objArrayPtr[0] == objPtr)) {						codePtr->objArrayPtr[0] = NULL;		    }		}#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.     */    Tcl_DecrRefCount(objPtr);}/* *---------------------------------------------------------------------- * * 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 intHashString(bytes, length)    register CONST char *bytes; /* String for which to compute hash				 * value. */    int length;			/* Number of bytes in the string. */{    register unsigned int result;    register int i;    /*     * 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.     */    result = 0;    for (i = 0;  i < length;  i++) {	result += (result<<3) + *bytes++;    }    return result;}/* *---------------------------------------------------------------------- * * RebuildLiteralTable -- * *	This procedure 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 voidRebuildLiteralTable(tablePtr)    register LiteralTable *tablePtr; /* Local or global table to enlarge. */{    LiteralEntry **oldBuckets;    register LiteralEntry **oldChainPtr, **newChainPtr;    register LiteralEntry *entryPtr;    LiteralEntry **bucketPtr;    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 = (LiteralEntry **) ckalloc((unsigned)	    (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 = Tcl_GetStringFromObj(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((char *) oldBuckets);    }}#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(tablePtr)    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 = (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++) {	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*/#ifdef TCL_COMPILE_DEBUG/* *---------------------------------------------------------------------- * * TclVerifyLocalLiteralTable -- * *	Check a CompileEnv's local literal table for consistency. * * Results: *	None. * * Side effects: *	Panics if problems are found. * *---------------------------------------------------------------------- */voidTclVerifyLocalLiteralTable(envPtr)    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);		panic("TclVerifyLocalLiteralTable: local literal \"%.*s\" had bad refCount %d",		        (length>60? 60 : length), bytes,		        localPtr->refCount);	    }	    if (TclLookupLiteralEntry((Tcl_Interp *) envPtr->iPtr,		    localPtr->objPtr) == NULL) {		bytes = Tcl_GetStringFromObj(localPtr->objPtr, &length);		panic("TclVerifyLocalLiteralTable: local literal \"%.*s\" is not global",		         (length>60? 60 : length), bytes);	    }	    if (localPtr->objPtr->bytes == NULL) {		panic("TclVerifyLocalLiteralTable: literal has NULL string rep");	    }	}    }    if (count != localTablePtr->numEntries) {	panic("TclVerifyLocalLiteralTable: local literal table had %d entries, should be %d",	      count, localTablePtr->numEntries);    }}/* *---------------------------------------------------------------------- * * TclVerifyGlobalLiteralTable -- * *	Check an interpreter's global literal table literal for consistency. * * Results: *	None. * * Side effects: *	Panics if problems are found. * *---------------------------------------------------------------------- */voidTclVerifyGlobalLiteralTable(iPtr)    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);		panic("TclVerifyGlobalLiteralTable: global literal \"%.*s\" had bad refCount %d",		        (length>60? 60 : length), bytes,		        globalPtr->refCount);	    }	    if (globalPtr->objPtr->bytes == NULL) {		panic("TclVerifyGlobalLiteralTable: literal has NULL string rep");	    }	}    }    if (count != globalTablePtr->numEntries) {	panic("TclVerifyGlobalLiteralTable: global literal table had %d entries, should be %d",	      count, globalTablePtr->numEntries);    }}#endif /*TCL_COMPILE_DEBUG*/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -