From 2cfbbdcb041073ed1f9aff2f2fd630b24e039e6d Mon Sep 17 00:00:00 2001 From: root Date: Wed, 11 Sep 2013 01:51:01 -0700 Subject: Wed Sep 11 01:49:28 PDT 2013 --- extra/tk/tk-xcircuit.patch | 317 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 317 insertions(+) create mode 100644 extra/tk/tk-xcircuit.patch (limited to 'extra/tk/tk-xcircuit.patch') diff --git a/extra/tk/tk-xcircuit.patch b/extra/tk/tk-xcircuit.patch new file mode 100644 index 000000000..1fe329e33 --- /dev/null +++ b/extra/tk/tk-xcircuit.patch @@ -0,0 +1,317 @@ +Index: generic/tkConfig.c +================================================================== +--- generic/tkConfig.c ++++ generic/tkConfig.c +@@ -29,11 +29,16 @@ + /* + * The following definition is an AssocData key used to keep track of all of + * the option tables that have been created for an interpreter. + */ + +-#define OPTION_HASH_KEY "TkOptionTable" ++typedef struct ThreadSpecificData { ++ int initialized; /* 0 means table below needs initializing. */ ++ Tcl_HashTable hashTable; ++} ThreadSpecificData; ++static Tcl_ThreadDataKey dataKey; ++ + + /* + * The following two structures are used along with Tk_OptionSpec structures + * to manage configuration options. Tk_OptionSpec is static templates that are + * compiled into the code of a widget or other object manager. However, to +@@ -98,12 +103,10 @@ + * templates, this points to the table + * corresponding to the next template in the + * chain. */ + int numOptions; /* The number of items in the options array + * below. */ +- int refCount2; /* Reference counter for controlling the freeing +- * of the memory occupied by this OptionTable */ + Option options[1]; /* Information about the individual options in + * the table. This must be the last field in + * the structure: the actual size of the array + * will be numOptions, not 1. */ + } OptionTable; +@@ -113,12 +116,10 @@ + */ + + static int DoObjConfig(Tcl_Interp *interp, char *recordPtr, + Option *optionPtr, Tcl_Obj *valuePtr, + Tk_Window tkwin, Tk_SavedOption *savePtr); +-static void DestroyOptionHashTable(ClientData clientData, +- Tcl_Interp *interp); + static void FreeResources(Option *optionPtr, Tcl_Obj *objPtr, + char *internalPtr, Tk_Window tkwin); + static Tcl_Obj * GetConfigList(char *recordPtr, + Option *optionPtr, Tk_Window tkwin); + static Tcl_Obj * GetObjectForOption(char *recordPtr, +@@ -168,42 +169,38 @@ + * in which this table will be used. */ + const Tk_OptionSpec *templatePtr) + /* Static information about the configuration + * options. */ + { +- Tcl_HashTable *hashTablePtr; + Tcl_HashEntry *hashEntryPtr; + int newEntry; + OptionTable *tablePtr; + const Tk_OptionSpec *specPtr, *specPtr2; + Option *optionPtr; + int numOptions, i; ++ ThreadSpecificData *tsdPtr = ++ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + + /* +- * We use an AssocData value in the interpreter to keep a hash table of +- * all the option tables we've created for this application. This is used +- * for two purposes. First, it allows us to share the tables (e.g. in +- * several chains) and second, we use the deletion callback for the +- * AssocData to delete all the option tables when the interpreter is +- * deleted. The code below finds the hash table or creates a new one if it ++ * We use an TSD in the thread to keep a hash table of ++ * all the option tables we've created for this application. This is ++ * used for allowing us to share the tables (e.g. in several chains). ++ * The code below finds the hash table or creates a new one if it + * doesn't already exist. + */ + +- hashTablePtr = Tcl_GetAssocData(interp, OPTION_HASH_KEY, NULL); +- if (hashTablePtr == NULL) { +- hashTablePtr = ckalloc(sizeof(Tcl_HashTable)); +- Tcl_InitHashTable(hashTablePtr, TCL_ONE_WORD_KEYS); +- Tcl_SetAssocData(interp, OPTION_HASH_KEY, DestroyOptionHashTable, +- hashTablePtr); ++ if (!tsdPtr->initialized) { ++ Tcl_InitHashTable(&tsdPtr->hashTable, TCL_ONE_WORD_KEYS); ++ tsdPtr->initialized = 1; + } + + /* + * See if a table has already been created for this template. If so, just + * reuse the existing table. + */ + +- hashEntryPtr = Tcl_CreateHashEntry(hashTablePtr, (char *) templatePtr, ++ hashEntryPtr = Tcl_CreateHashEntry(&tsdPtr->hashTable, (char *) templatePtr, + &newEntry); + if (!newEntry) { + tablePtr = Tcl_GetHashValue(hashEntryPtr); + tablePtr->refCount++; + return (Tk_OptionTable) tablePtr; +@@ -218,11 +215,10 @@ + for (specPtr = templatePtr; specPtr->type != TK_OPTION_END; specPtr++) { + numOptions++; + } + tablePtr = ckalloc(sizeof(OptionTable) + (numOptions * sizeof(Option))); + tablePtr->refCount = 1; +- tablePtr->refCount2 = 1; + tablePtr->hashEntryPtr = hashEntryPtr; + tablePtr->nextPtr = NULL; + tablePtr->numOptions = numOptions; + + /* +@@ -332,13 +328,20 @@ + Tk_OptionTable optionTable) /* The option table to delete. */ + { + OptionTable *tablePtr = (OptionTable *) optionTable; + Option *optionPtr; + int count; ++ ThreadSpecificData *tsdPtr = ++ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + +- tablePtr->refCount--; +- if (tablePtr->refCount > 0) { ++ if (tablePtr->refCount > 1) { ++ tablePtr->refCount--; ++ return; ++ } ++ ++ if (!tsdPtr->initialized || !Tcl_FindHashEntry(&tsdPtr->hashTable, ++ tablePtr->hashEntryPtr)) { + return; + } + + if (tablePtr->nextPtr != NULL) { + Tk_DeleteOptionTable((Tk_OptionTable) tablePtr->nextPtr); +@@ -354,66 +357,11 @@ + && (optionPtr->extra.monoColorPtr != NULL)) { + Tcl_DecrRefCount(optionPtr->extra.monoColorPtr); + } + } + Tcl_DeleteHashEntry(tablePtr->hashEntryPtr); +- tablePtr->refCount2--; +- if (tablePtr->refCount2 <= 0) { +- ckfree(tablePtr); +- } +-} +- +-/* +- *---------------------------------------------------------------------- +- * +- * DestroyOptionHashTable -- +- * +- * This function is the deletion callback associated with the AssocData +- * entry created by Tk_CreateOptionTable. It is invoked when an +- * interpreter is deleted, and deletes all of the option tables +- * associated with that interpreter. +- * +- * Results: +- * None. +- * +- * Side effects: +- * The option hash table is destroyed along with all of the OptionTable +- * structures that it refers to. +- * +- *---------------------------------------------------------------------- +- */ +- +-static void +-DestroyOptionHashTable( +- ClientData clientData, /* The hash table we are destroying */ +- Tcl_Interp *interp) /* The interpreter we are destroying */ +-{ +- Tcl_HashTable *hashTablePtr = clientData; +- Tcl_HashSearch search; +- Tcl_HashEntry *hashEntryPtr; +- +- for (hashEntryPtr = Tcl_FirstHashEntry(hashTablePtr, &search); +- hashEntryPtr != NULL; +- hashEntryPtr = Tcl_NextHashEntry(&search)) { +- OptionTable *tablePtr = Tcl_GetHashValue(hashEntryPtr); +- +- /* +- * The following statements do two tricky things: +- * 1. They ensure that the option table is deleted, even if there are +- * outstanding references to it. +- * 2. They ensure that Tk_DeleteOptionTable doesn't delete other +- * tables chained from this one; we'll do it when we come across +- * the hash table entry for the chained table (in fact, the chained +- * table may already have been deleted). +- */ +- +- tablePtr->refCount = 1; +- tablePtr->nextPtr = NULL; +- Tk_DeleteOptionTable((Tk_OptionTable) tablePtr); +- } +- Tcl_DeleteHashTable(hashTablePtr); +- ckfree(hashTablePtr); ++ ckfree(tablePtr); + } + + /* + *-------------------------------------------------------------- + * +@@ -1149,11 +1097,11 @@ + objPtr->typePtr->freeIntRepProc(objPtr); + } + objPtr->internalRep.twoPtrValue.ptr1 = (void *) tablePtr; + objPtr->internalRep.twoPtrValue.ptr2 = (void *) bestPtr; + objPtr->typePtr = &optionObjType; +- tablePtr->refCount2++; ++ tablePtr->refCount++; + return bestPtr; + + error: + if (interp != NULL) { + Tcl_SetObjResult(interp, Tcl_ObjPrintf( +@@ -1222,16 +1170,13 @@ + + static void + FreeOptionInternalRep( + register Tcl_Obj *objPtr) /* Object whose internal rep to free. */ + { +- register OptionTable *tablePtr = (OptionTable *) objPtr->internalRep.twoPtrValue.ptr1; ++ register Tk_OptionTable tablePtr = (Tk_OptionTable) objPtr->internalRep.twoPtrValue.ptr1; + +- tablePtr->refCount2--; +- if (tablePtr->refCount2 <= 0) { +- ckfree(tablePtr); +- } ++ Tk_DeleteOptionTable(tablePtr); + objPtr->typePtr = NULL; + objPtr->internalRep.twoPtrValue.ptr1 = NULL; + objPtr->internalRep.twoPtrValue.ptr2 = NULL; + } + +@@ -2111,27 +2056,27 @@ + Tk_OptionTable table) /* Table about which information is to be + * returned. May not necessarily exist in the + * interpreter anymore. */ + { + OptionTable *tablePtr = (OptionTable *) table; +- Tcl_HashTable *hashTablePtr; + Tcl_HashEntry *hashEntryPtr; + Tcl_HashSearch search; + Tcl_Obj *objPtr; ++ ThreadSpecificData *tsdPtr = ++ Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + + objPtr = Tcl_NewObj(); +- hashTablePtr = Tcl_GetAssocData(interp, OPTION_HASH_KEY, NULL); +- if (hashTablePtr == NULL) { ++ if (!tablePtr || !tsdPtr->initialized) { + return objPtr; + } + + /* + * Scan all the tables for this interpreter to make sure that the one we + * want still is valid. + */ + +- for (hashEntryPtr = Tcl_FirstHashEntry(hashTablePtr, &search); ++ for (hashEntryPtr = Tcl_FirstHashEntry(&tsdPtr->hashTable, &search); + hashEntryPtr != NULL; + hashEntryPtr = Tcl_NextHashEntry(&search)) { + if (tablePtr == (OptionTable *) Tcl_GetHashValue(hashEntryPtr)) { + for ( ; tablePtr != NULL; tablePtr = tablePtr->nextPtr) { + Tcl_ListObjAppendElement(NULL, objPtr, + +Index: generic/tkTest.c +================================================================== +--- generic/tkTest.c ++++ generic/tkTest.c +@@ -801,10 +801,11 @@ + sizeof(char *), "table", 0, &index) != TCL_OK) { + return TCL_ERROR; + } + if (tables[index] != NULL) { + Tk_DeleteOptionTable(tables[index]); ++ tables[index] = NULL; + } + break; + + case INFO: + if (objc != 3) { + +Index: tests/config.test +================================================================== +--- tests/config.test ++++ tests/config.test +@@ -96,11 +96,11 @@ + testobjconfig chain2 .b + testobjconfig chain1 .a + testobjconfig info chain2 + } -cleanup { + killTables +-} -result {1 4 -three 2 2 -one} ++} -result {2 4 -three 2 2 -one} + test config-1.8 {Tk_CreateOptionTable - chained tables} -constraints { + testobjconfig + } -body { + testobjconfig chain1 .a + testobjconfig chain2 .b +@@ -132,11 +132,11 @@ + lappend x [testobjconfig info chain2] [testobjconfig info chain1] + testobjconfig delete chain2 + lappend x [testobjconfig info chain2] [testobjconfig info chain1] + } -cleanup { + killTables +-} -result {{1 4 -three 2 2 -one} {2 2 -one} {} {1 2 -one}} ++} -result {{} {2 2 -one} {} {2 2 -one}} + + # No tests for DestroyOptionHashTable; couldn't figure out how to test. + + test config-3.1 {Tk_InitOptions - priority of chained tables} -constraints { + testobjconfig + -- cgit v1.2.3-54-g00ecf