diff options
Diffstat (limited to 'generic/tclObj.c')
-rw-r--r-- | generic/tclObj.c | 394 |
1 files changed, 0 insertions, 394 deletions
diff --git a/generic/tclObj.c b/generic/tclObj.c index 542d6d1..7b27fab 100644 --- a/generic/tclObj.c +++ b/generic/tclObj.c @@ -77,17 +77,6 @@ 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. */ #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 @@ -97,10 +86,6 @@ typedef struct ThreadSpecificData { static Tcl_ThreadDataKey dataKey; -static void ContLineLocFree(char *clientData); -static void TclThreadFinalizeContLines(ClientData clientData); -static ThreadSpecificData *TclGetContLineTable(void); - /* * Nested Tcl_Obj deletion management support * @@ -510,341 +495,6 @@ TclFinalizeObjects(void) } /* - *---------------------------------------------------------------------- - * - * TclGetContLineTable -- - * - * This procedure is a helper which returns the thread-specific - * hash-table used to track continuation line information associated with - * Tcl_Obj*, and the objThreadMap, etc. - * - * Results: - * A reference to the thread-data. - * - * Side effects: - * May allocate memory for the thread-data. - * - * TIP #280 - *---------------------------------------------------------------------- - */ - -static ThreadSpecificData * -TclGetContLineTable(void) -{ - /* - * Initialize the hashtable tracking invisible continuation lines. For - * the release we use a thread exit handler to ensure that this is done - * before TSD blocks are made invalid. The TclFinalizeObjects() which - * would be the natural place for this is invoked afterwards, meaning that - * we try to operate on a data structure already gone. - */ - - ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); - - if (!tsdPtr->lineCLPtr) { - tsdPtr->lineCLPtr = ckalloc(sizeof(Tcl_HashTable)); - Tcl_InitHashTable(tsdPtr->lineCLPtr, TCL_ONE_WORD_KEYS); - Tcl_CreateThreadExitHandler(TclThreadFinalizeContLines,NULL); - } - return tsdPtr; -} - -/* - *---------------------------------------------------------------------- - * - * TclContinuationsEnter -- - * - * This procedure is a helper which saves the continuation line - * information associated with a Tcl_Obj*. - * - * Results: - * A reference to the newly created continuation line location table. - * - * Side effects: - * Allocates memory for the table of continuation line locations. - * - * TIP #280 - *---------------------------------------------------------------------- - */ - -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)); - - if (!newEntry) { - /* - * We're entering ContLineLoc data for the same value more than one - * time. Taking care not to leak the old entry. - * - * This can happen when literals in a proc body are shared. See for - * example test info-30.19 where the action (code) for all branches of - * the switch command is identical, mapping them all to the same - * literal. An interesting result of this is that the number and - * locations (offset) of invisible continuation lines in the literal - * are the same for all occurences. - * - * Note that while reusing the existing entry is possible it requires - * the same actions as for a new entry because we have to copy the - * 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. - */ - - ckfree(Tcl_GetHashValue(hPtr)); - } - - clLocPtr->num = num; - memcpy(&clLocPtr->loc, loc, num*sizeof(int)); - clLocPtr->loc[num] = CLL_END; /* Sentinel */ - Tcl_SetHashValue(hPtr, clLocPtr); - - return clLocPtr; -} - -/* - *---------------------------------------------------------------------- - * - * TclContinuationsEnterDerived -- - * - * This procedure is a helper which computes the continuation line - * information associated with a Tcl_Obj* cut from the middle of a - * script. - * - * Results: - * None. - * - * Side effects: - * Allocates memory for the table of continuation line locations. - * - * TIP #280 - *---------------------------------------------------------------------- - */ - -void -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 - * our script is the sole argument to an 'eval' command, for example, the - * scriptCLLocPtr we are using was generated by a previous call to TST, - * and while the words we have here may contain continuation lines they - * are invisible already, and the inner call to TST had no bs+nl sequences - * to trigger its code. - * - * Luckily for us, the table we have to create here for the current word - * has to be a slice of the table currently in use, with the locations - * suitably modified to be relative to the start of the word instead of - * relative to the script. - * - * That is what we are doing now. Determine the slice we need, and if not - * empty, wrap it into a new table, and save the result into our - * thread-global hashtable, as usual. - */ - - /* - * First compute the range of the word within the script. (Is there a - * better way which doesn't shimmer?) - */ - - Tcl_GetStringFromObj(objPtr, &length); - end = start + length; /* First char after the word */ - - /* - * Then compute the table slice covering the range of the word. - */ - - while (*wordCLLast >= 0 && *wordCLLast < end) { - wordCLLast++; - } - - /* - * 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); - - /* - * Re-base the locations. - */ - - for (i=0 ; i<num ; i++) { - clLocPtr->loc[i] -= start; - - /* - * Continuation lines coming before the string and affecting us - * should not happen, due to the proper maintenance of clNext - * during compilation. - */ - - if (clLocPtr->loc[i] < 0) { - Tcl_Panic("Derived ICL data for object using offsets from before the script"); - } - } - } -} - -/* - *---------------------------------------------------------------------- - * - * 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. - * - * Results: - * None. - * - * Side effects: - * Allocates memory for the table of continuation line locations. - * - * TIP #280 - *---------------------------------------------------------------------- - */ - -void -TclContinuationsCopy( - Tcl_Obj *objPtr, - Tcl_Obj *originObjPtr) -{ - ThreadSpecificData *tsdPtr = TclGetContLineTable(); - Tcl_HashEntry *hPtr = - Tcl_FindHashEntry(tsdPtr->lineCLPtr, originObjPtr); - - if (hPtr) { - ContLineLoc *clLocPtr = Tcl_GetHashValue(hPtr); - - TclContinuationsEnter(objPtr, clLocPtr->num, clLocPtr->loc); - } -} - -/* - *---------------------------------------------------------------------- - * - * TclContinuationsGet -- - * - * This procedure is a helper which retrieves the continuation line - * 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. - * - * Side effects: - * None. - * - * TIP #280 - *---------------------------------------------------------------------- - */ - -ContLineLoc * -TclContinuationsGet( - Tcl_Obj *objPtr) -{ - ThreadSpecificData *tsdPtr = TclGetContLineTable(); - Tcl_HashEntry *hPtr = - Tcl_FindHashEntry(tsdPtr->lineCLPtr, objPtr); - - if (!hPtr) { - return NULL; - } - return Tcl_GetHashValue(hPtr); -} - -/* - *---------------------------------------------------------------------- - * - * TclThreadFinalizeContLines -- - * - * This procedure is a helper which releases all continuation line - * information currently known. It is run as a thread exit handler. - * - * Results: - * None. - * - * Side effects: - * Releases memory. - * - * TIP #280 - *---------------------------------------------------------------------- - */ - -static void -TclThreadFinalizeContLines( - ClientData clientData) -{ - /* - * Release the hashtable tracking invisible continuation lines. - */ - - ThreadSpecificData *tsdPtr = TclGetContLineTable(); - Tcl_HashEntry *hPtr; - Tcl_HashSearch hSearch; - - for (hPtr = Tcl_FirstHashEntry(tsdPtr->lineCLPtr, &hSearch); - 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); - 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 -- @@ -1388,28 +1038,6 @@ TclFreeObj( ObjDeletionUnlock(context); } - /* - * 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). - */ - - { - ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); - Tcl_HashEntry *hPtr; - - if (tsdPtr->lineCLPtr) { - hPtr = Tcl_FindHashEntry(tsdPtr->lineCLPtr, objPtr); - if (hPtr) { - Tcl_EventuallyFree(Tcl_GetHashValue(hPtr), ContLineLocFree); - Tcl_DeleteHashEntry(hPtr); - } - } - } } #else /* TCL_MEM_DEBUG */ @@ -1479,28 +1107,6 @@ 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). - */ - - { - ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); - Tcl_HashEntry *hPtr; - - if (tsdPtr->lineCLPtr) { - hPtr = Tcl_FindHashEntry(tsdPtr->lineCLPtr, objPtr); - if (hPtr) { - Tcl_EventuallyFree(Tcl_GetHashValue(hPtr), ContLineLocFree); - Tcl_DeleteHashEntry(hPtr); - } - } - } } #endif /* TCL_MEM_DEBUG */ |