Posted to tcl by cjo at Mon Sep 11 14:01:43 GMT 2017view raw
- diff --git a/generic/tclBasic.c b/generic/tclBasic.c
- index 5a33445..e5b09b8 100644
- --- a/generic/tclBasic.c
- +++ b/generic/tclBasic.c
- @@ -6141,7 +6141,10 @@ TclNREvalObjEx(
- iPtr->varFramePtr = iPtr->rootFramePtr;
- }
- Tcl_IncrRefCount(objPtr);
- - codePtr = TclCompileObj(interp, objPtr, invoker, word);
- + ByteCodeGetIntRep(objPtr, &tclByteCodeType, codePtr);
- + if (codePtr == NULL) {
- + codePtr = TclCompileObj(interp, objPtr, invoker, word);
- + }
- TclNRAddCallback(interp, TEOEx_ByteCodeCallback, savedVarFramePtr,
- objPtr, INT2PTR(allowExceptions), NULL);
- diff --git a/generic/tclDecls.h b/generic/tclDecls.h
- index 59d83b8..282e70b 100644
- --- a/generic/tclDecls.h
- +++ b/generic/tclDecls.h
- @@ -1836,6 +1836,8 @@ EXTERN void Tcl_StoreIntRep(Tcl_Obj *objPtr,
- const Tcl_ObjIntRep *irPtr);
- /* 636 */
- EXTERN int Tcl_HasStringRep(Tcl_Obj *objPtr);
- +/* 637 */
- +EXTERN void Tcl_FreeOtherIntReps(Tcl_Obj *objPtr, const Tcl_ObjType *typePtr);
- typedef struct {
- const struct TclPlatStubs *tclPlatStubs;
- @@ -2508,6 +2510,7 @@ typedef struct TclStubs {
- Tcl_ObjIntRep * (*tcl_FetchIntRep) (Tcl_Obj *objPtr, const Tcl_ObjType *typePtr); /* 634 */
- void (*tcl_StoreIntRep) (Tcl_Obj *objPtr, const Tcl_ObjType *typePtr, const Tcl_ObjIntRep *irPtr); /* 635 */
- int (*tcl_HasStringRep) (Tcl_Obj *objPtr); /* 636 */
- + void (*tcl_FreeOtherIntReps) (Tcl_Obj *objPtr, const Tcl_ObjType *typePtr); /* 637 */
- } TclStubs;
- extern const TclStubs *tclStubsPtr;
- @@ -3812,6 +3815,8 @@ extern const TclStubs *tclStubsPtr;
- (tclStubsPtr->tcl_StoreIntRep) /* 635 */
- #define Tcl_HasStringRep \
- (tclStubsPtr->tcl_HasStringRep) /* 636 */
- +#define Tcl_FreeOtherIntReps \
- + (tclStubsPtr->tcl_FreeOtherIntReps) /* 636 */
- #endif /* defined(USE_TCL_STUBS) */
- diff --git a/generic/tclDictObj.c b/generic/tclDictObj.c
- index f4e15a6..e4b06bc 100644
- --- a/generic/tclDictObj.c
- +++ b/generic/tclDictObj.c
- @@ -959,6 +959,7 @@ Tcl_DictObjPut(
- return TCL_ERROR;
- }
- + Tcl_FreeOtherIntReps(dictPtr, &tclDictType);
- TclInvalidateStringRep(dictPtr);
- hPtr = CreateChainEntry(dict, keyPtr, &isNew);
- Tcl_IncrRefCount(valuePtr);
- diff --git a/generic/tclExecute.c b/generic/tclExecute.c
- index 8389bef..728e52c 100644
- --- a/generic/tclExecute.c
- +++ b/generic/tclExecute.c
- @@ -9742,8 +9742,13 @@ TclGetSrcInfoForPc(
- ECL *locPtr = NULL;
- int srcOffset, i;
- Interp *iPtr = (Interp *) *codePtr->interpHandle;
- - Tcl_HashEntry *hePtr =
- - Tcl_FindHashEntry(iPtr->lineBCPtr, codePtr);
- + Tcl_HashEntry *hePtr;
- +
- + if (!iPtr->lineBCPtr) {
- + fprintf(stderr, "TclGetSrcInfoForPc: iPtr->lineBCPtr is invalid\n");
- + return;
- + }
- + hePtr = Tcl_FindHashEntry(iPtr->lineBCPtr, codePtr);
- if (!hePtr) {
- return;
- diff --git a/generic/tclListObj.c b/generic/tclListObj.c
- index c33b95e..6e81a23 100644
- --- a/generic/tclListObj.c
- +++ b/generic/tclListObj.c
- @@ -66,7 +66,13 @@ const Tcl_ObjType tclListType = {
- } while (0)
- #define ListResetIntRep(objPtr, listRepPtr) \
- - Tcl_FetchIntRep((objPtr), &tclListType)->twoPtrValue.ptr1 = (listRepPtr)
- + do { \
- + Tcl_ObjIntRep *irPtr; \
- + Tcl_FreeOtherIntReps((objPtr), &tclListType); \
- + irPtr = Tcl_FetchIntRep((objPtr), &tclListType); \
- + irPtr->twoPtrValue.ptr1 = (listRepPtr); \
- + irPtr->twoPtrValue.ptr2 = NULL; \
- + } while (0)
- #ifndef TCL_MIN_ELEMENT_GROWTH
- #define TCL_MIN_ELEMENT_GROWTH TCL_MIN_GROWTH/sizeof(Tcl_Obj *)
- @@ -1257,7 +1263,7 @@ TclLindexFlat(
- int index, listLen = 0;
- Tcl_Obj **elemPtrs = NULL, *sublistCopy;
- - /*
- + /* TODO hydra: is this still necessary if shimmering is no longer an issue?
- * Here we make a private copy of the current sublist, so we avoid any
- * shimmering issues that might invalidate the elemPtr array below
- * while we are still using it. See test lindex-8.4.
- diff --git a/generic/tclObj.c b/generic/tclObj.c
- index 6e4011e..8bf69ce 100644
- --- a/generic/tclObj.c
- +++ b/generic/tclObj.c
- @@ -206,6 +206,10 @@ static Tcl_ThreadDataKey pendingObjDataKey;
- * Prototypes for functions defined later in this file:
- */
- +static void FreeHydra(Tcl_Obj *objPtr);
- +static void DupHydra(Tcl_Obj *srcPtr, Tcl_Obj *copyPtr);
- +static void UpdateStringOfHydra(Tcl_Obj *objPtr);
- +static int SetHydraFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr);
- static int ParseBoolean(Tcl_Obj *objPtr);
- static int SetDoubleFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr);
- static int SetIntFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr);
- @@ -243,6 +247,26 @@ static int SetCmdNameFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr);
- * implementations.
- */
- +#define MAX_HYDRA_CLIENTS 5
- +static const Tcl_ObjType tclHydraType = {
- + "hydra", /* name */
- + FreeHydra, /* freeIntRepProc */
- + DupHydra, /* dupIntRepProc */
- + UpdateStringOfHydra, /* updateStringProc */
- + SetHydraFromAny /* setFromAnyProc */
- +};
- +
- +#define HydraGetIntRep(objPtr, hydraPtr) \
- + (hydraPtr) = (Hydra *)((objPtr)->internalRep.twoPtrValue.ptr1)
- +
- +typedef struct HydraClient {
- + const Tcl_ObjType *typePtr;
- + Tcl_ObjIntRep internalRep;
- +} HydraClient;
- +typedef struct Hydra {
- + HydraClient client[MAX_HYDRA_CLIENTS];
- +} Hydra;
- +
- static const Tcl_ObjType oldBooleanType = {
- "boolean", /* name */
- NULL, /* freeIntRepProc */
- @@ -1694,6 +1718,175 @@ Tcl_GetStringFromObj(
- return objPtr->bytes;
- }
- +static void
- +FreeHydra(
- + Tcl_Obj *objPtr)
- +{
- + int i;
- + Hydra *hydraPtr;
- + Tcl_Obj fakeObj;
- +
- + memset(&fakeObj, 0, sizeof(fakeObj));
- + fakeObj.refCount = 10;
- + HydraGetIntRep(objPtr, hydraPtr);
- +
- + for (i=0; i<MAX_HYDRA_CLIENTS; i++) {
- + HydraClient *clientPtr = &hydraPtr->client[i];
- +
- + if (clientPtr->typePtr) {
- + if (clientPtr->typePtr->freeIntRepProc) {
- + fakeObj.internalRep = hydraPtr->client[i].internalRep;
- + fakeObj.typePtr = hydraPtr->client[i].typePtr;
- + Tcl_FreeIntRep(&fakeObj);
- +
- + if (fakeObj.refCount != 10) {
- + Tcl_Panic("Invalid reference taken to fakeObj while "
- + "freeing intrep for %s",
- + hydraPtr->client[i].typePtr->name);
- + }
- + }
- +
- + hydraPtr->client[i].typePtr = NULL;
- + memset(&hydraPtr->client[i].internalRep, 0, sizeof(hydraPtr->client[i].internalRep));
- + }
- + }
- +
- + Tcl_Free((char *)hydraPtr);
- + hydraPtr = objPtr->internalRep.twoPtrValue.ptr1 = NULL;
- +}
- +
- +static void
- +DupHydra(
- + Tcl_Obj *srcPtr,
- + Tcl_Obj *copyPtr)
- +{
- + int i;
- + Hydra *hydraPtr;
- + Hydra *hydraCopyPtr;
- + Tcl_Obj fakeSrcObj, fakeCopyObj;
- +
- + if (Tcl_HasStringRep(srcPtr) && srcPtr->bytes == &tclEmptyString) {
- + return;
- + }
- +
- + memset(&fakeSrcObj, 0, sizeof(fakeSrcObj));
- + fakeSrcObj.refCount = 10;
- + memset(&fakeCopyObj, 0, sizeof(fakeCopyObj));
- + fakeCopyObj.refCount = 10;
- +
- + HydraGetIntRep(srcPtr, hydraPtr);
- +
- + hydraCopyPtr = (Hydra *)Tcl_Alloc(sizeof(Hydra));
- + memset(hydraCopyPtr, 0, sizeof(*hydraCopyPtr));
- +
- + for (i=0; i<MAX_HYDRA_CLIENTS; i++) {
- + HydraClient *clientPtr = &hydraPtr->client[i];
- + HydraClient *clientCopyPtr = &hydraCopyPtr->client[i];
- +
- + if (clientPtr->typePtr) {
- + if (clientPtr->typePtr->dupIntRepProc) {
- + fakeCopyObj.typePtr = NULL;
- + fakeSrcObj.internalRep = hydraPtr->client[i].internalRep;
- + fakeSrcObj.typePtr = hydraPtr->client[i].typePtr;
- +
- + fakeSrcObj.typePtr->dupIntRepProc(&fakeSrcObj, &fakeCopyObj);
- +
- + if (fakeSrcObj.refCount != 10) {
- + Tcl_Panic("Invalid reference taken to fakeSrcObj while "
- + "duplicating intrep for %s",
- + hydraPtr->client[i].typePtr->name);
- + }
- + if (fakeCopyObj.refCount != 10) {
- + Tcl_Panic("Invalid reference taken to fakeCopyObj while "
- + "duplicating intrep for %s",
- + hydraPtr->client[i].typePtr->name);
- + }
- +
- + if (clientCopyPtr->internalRep.twoPtrValue.ptr1 || clientCopyPtr->internalRep.twoPtrValue.ptr2) {
- + clientCopyPtr->internalRep = fakeCopyObj.internalRep;
- + clientCopyPtr->typePtr = fakeCopyObj.typePtr;
- + }
- + }
- + }
- + }
- +
- + TclFreeIntRep(copyPtr); /* Paranoia? */
- + copyPtr->internalRep.twoPtrValue.ptr1 = hydraPtr;
- + copyPtr->typePtr = &tclHydraType;
- +}
- +
- +static void
- +UpdateStringOfHydra(
- + Tcl_Obj *objPtr)
- +{
- + int i;
- + Hydra *hydraPtr;
- + Tcl_Obj fakeObj;
- +
- + memset(&fakeObj, 0, sizeof(fakeObj));
- + fakeObj.refCount = 10;
- +
- + HydraGetIntRep(objPtr, hydraPtr);
- +
- + for (i=0; i<MAX_HYDRA_CLIENTS; i++) {
- + HydraClient *clientPtr = &hydraPtr->client[i];
- +
- + if (clientPtr->typePtr) {
- + if (clientPtr->typePtr->updateStringProc) {
- + fakeObj.internalRep = hydraPtr->client[i].internalRep;
- + fakeObj.typePtr = hydraPtr->client[i].typePtr;
- + /* Don't know if this is necessary */
- + fakeObj.bytes = NULL;
- + fakeObj.length = 0;
- +
- + fakeObj.typePtr->updateStringProc(&fakeObj);
- +
- + if (fakeObj.refCount != 10) {
- + Tcl_Panic("Invalid reference taken to fakeObj while "
- + "updating string rep using %s",
- + hydraPtr->client[i].typePtr->name);
- + }
- +
- + if (TclHasStringRep(&fakeObj)) { /* Not sure about this */
- + objPtr->bytes = fakeObj.bytes;
- + objPtr->length = fakeObj.length;
- + fakeObj.bytes = NULL;
- + fakeObj.length = 0;
- + return;
- + }
- + }
- + }
- + }
- +
- + /* TODO: what? */
- + Tcl_Panic("Could not update string rep of hydra: %s",
- + "No clients capable of regenerating string rep found");
- +}
- +
- +static int
- +SetHydraFromAny(
- + Tcl_Interp *interp,
- + Tcl_Obj *objPtr)
- +{
- + Hydra *hydraPtr;
- +
- + if (objPtr->typePtr == &tclHydraType) {
- + return TCL_OK;
- + }
- +
- + hydraPtr = (Hydra *)Tcl_Alloc(sizeof(Hydra));
- + memset(hydraPtr, 0, sizeof(Hydra));
- +
- + hydraPtr->client[0].typePtr = objPtr->typePtr;
- + hydraPtr->client[0].internalRep = objPtr->internalRep;
- +
- + objPtr->internalRep.twoPtrValue.ptr1 = hydraPtr;
- + objPtr->internalRep.twoPtrValue.ptr2 = NULL;
- + objPtr->typePtr = &tclHydraType;
- +
- + return TCL_OK;
- +}
- +
- /*
- *----------------------------------------------------------------------
- *
- @@ -1852,16 +2045,125 @@ Tcl_StoreIntRep(
- const Tcl_ObjType *typePtr, /* New type for the object */
- const Tcl_ObjIntRep *irPtr) /* New IntRep for the object */
- {
- - /* Clear out any existing IntRep ( "shimmer" ) */
- - TclFreeIntRep(objPtr);
- + int i;
- + Hydra *hydraPtr;
- - /* When irPtr == NULL, just leave objPtr with no IntRep for typePtr */
- - if (irPtr) {
- - /* Copy the new IntRep into place */
- + if (objPtr->typePtr == NULL) {
- + /* Special case - updating (or clearing) a pure string object */
- + TclFreeIntRep(objPtr);
- objPtr->internalRep = *irPtr;
- -
- - /* Set the type to match */
- objPtr->typePtr = typePtr;
- + return;
- + }
- +
- + if (objPtr->typePtr == typePtr) {
- + /* Special case - updating (or clearing) an object's existing intrep */
- + TclFreeIntRep(objPtr);
- + if (irPtr) {
- + objPtr->internalRep = *irPtr;
- + } else {
- + memset(&objPtr->internalRep, 0, sizeof(objPtr->internalRep));
- + }
- + return;
- + }
- +
- + if (objPtr->typePtr != &tclHydraType) {
- + SetHydraFromAny(NULL, objPtr);
- + }
- +
- + HydraGetIntRep(objPtr, hydraPtr);
- +
- + if (irPtr) {
- + int firstAvailableSlot = -1;
- +
- + /* If we have an existing client with a matching type, we need to
- + * update that intrep even if there is an open slot before it */
- + for (i=0; i<MAX_HYDRA_CLIENTS; i++) {
- + HydraClient *clientPtr = &hydraPtr->client[i];
- +
- + if (clientPtr->typePtr == typePtr) {
- + if (irPtr) {
- + /* In the case where we are updating an intrep for a type we
- + * already have, take that as a sign that the value has changed
- + * ([incr], [lset], [append], etc), and free all the others.
- + * Since we will be left with a single intrep, drop back to a
- + * simple object (non-hydra) */
- + Tcl_FreeIntRep(objPtr);
- + objPtr->internalRep = *irPtr;
- + objPtr->typePtr = typePtr;
- + } else {
- + if (clientPtr->typePtr->freeIntRepProc) {
- + /* Free the matching client intrep, using a fake obj */
- + Tcl_Obj fakeObj;
- +
- + memset(&fakeObj, 0, sizeof(fakeObj));
- + fakeObj.refCount = 10;
- + fakeObj.typePtr = typePtr;
- + fakeObj.internalRep = clientPtr->internalRep;
- + TclFreeIntRep(&fakeObj);
- +
- + if (fakeObj.refCount != 10) {
- + Tcl_Panic("Invalid reference taken to fakeObj while "
- + "freeing hydra client interp for %s",
- + typePtr->name);
- + }
- + }
- +
- + /* Mark the client slot as available */
- + clientPtr->typePtr = NULL;
- + memset(&clientPtr->internalRep, 0, sizeof(clientPtr->internalRep));
- + return;
- + }
- + return;
- + } else if (firstAvailableSlot == -1 && clientPtr->typePtr == NULL) {
- + /* Record the first available slot in case we need to add this
- + * intrep there */
- + firstAvailableSlot = i;
- + }
- + }
- +
- + if (firstAvailableSlot > -1) {
- + HydraClient *clientPtr = &hydraPtr->client[firstAvailableSlot];
- +
- + if (clientPtr->typePtr == NULL) {
- + /* Found available slot, put this intrep there */
- + clientPtr->internalRep = *irPtr;
- + clientPtr->typePtr = typePtr;
- + return;
- + }
- + }
- +
- + /* No available client slots. Upconvert to linked list? */
- + Tcl_Panic("Unable to add client intrep for %s to hydra: "
- + "No slots available", typePtr->name);
- + } else {
- + for (i=0; i<MAX_HYDRA_CLIENTS; i++) {
- + HydraClient *clientPtr = &hydraPtr->client[i];
- +
- + if (clientPtr->typePtr == typePtr) {
- + if (clientPtr->typePtr->freeIntRepProc) {
- + /* Free the matching client intrep, using a fake obj */
- + Tcl_Obj fakeObj;
- +
- + memset(&fakeObj, 0, sizeof(fakeObj));
- + fakeObj.refCount = 10;
- + fakeObj.typePtr = typePtr;
- + fakeObj.internalRep = clientPtr->internalRep;
- + TclFreeIntRep(&fakeObj);
- +
- + if (fakeObj.refCount != 10) {
- + Tcl_Panic("Invalid reference taken to fakeObj while "
- + "freeing hydra client interp for %s",
- + typePtr->name);
- + }
- + }
- +
- + /* Mark the client slot as available */
- + clientPtr->typePtr = NULL;
- + memset(&clientPtr->internalRep, 0, sizeof(clientPtr->internalRep));
- + return;
- + }
- + }
- }
- }
- @@ -1878,8 +2180,7 @@ Tcl_StoreIntRep(
- * NULL if no such internal representation exists.
- *
- * Side effects:
- - * Calls the freeIntRepProc of the current Tcl_ObjType, if any.
- - * Sets the internalRep and typePtr fields to the submitted values.
- + * None.
- *
- *----------------------------------------------------------------------
- */
- @@ -1889,13 +2190,27 @@ Tcl_FetchIntRep(
- Tcl_Obj *objPtr, /* Object to fetch from. */
- const Tcl_ObjType *typePtr) /* Requested type */
- {
- - /* If objPtr type doesn't match request, nothing can be fetched */
- - if (objPtr->typePtr != typePtr) {
- - return NULL;
- + if (objPtr->typePtr == typePtr) {
- + /* Type match! objPtr IntRep is the one sought. */
- + return &(objPtr->internalRep);
- }
- - /* Type match! objPtr IntRep is the one sought. */
- - return &(objPtr->internalRep);
- + if (objPtr->typePtr == &tclHydraType) {
- + int i;
- + Hydra *hydraPtr;
- +
- + HydraGetIntRep(objPtr, hydraPtr);
- +
- + for (i=0; i<MAX_HYDRA_CLIENTS; i++) {
- + HydraClient *clientPtr = &hydraPtr->client[i];
- +
- + if (clientPtr->typePtr == typePtr) {
- + return &(clientPtr->internalRep);
- + }
- + }
- + }
- +
- + return NULL;
- }
- /*
- @@ -1922,6 +2237,43 @@ Tcl_FreeIntRep(
- TclFreeIntRep(objPtr);
- }
- +void
- +Tcl_FreeOtherIntReps(
- + Tcl_Obj *objPtr,
- + const Tcl_ObjType *typePtr)
- +{
- + if (objPtr->typePtr == NULL || objPtr->typePtr == typePtr) {
- + return;
- + }
- +
- + if (objPtr->typePtr == &tclHydraType) {
- + int i;
- + Hydra *hydraPtr;
- + Tcl_Obj fakeObj;
- +
- + HydraGetIntRep(objPtr, hydraPtr);
- + memset(&fakeObj, 0, sizeof(fakeObj));
- +
- + for (i=0; i<MAX_HYDRA_CLIENTS; i++) {
- + HydraClient *clientPtr = &hydraPtr->client[i];
- +
- + if (clientPtr->typePtr != NULL && clientPtr->typePtr != typePtr) {
- + if (clientPtr->typePtr->freeIntRepProc) {
- + fakeObj.typePtr = clientPtr->typePtr;
- + fakeObj.internalRep = clientPtr->internalRep;
- + fakeObj.typePtr->freeIntRepProc(&fakeObj);
- + }
- + clientPtr->typePtr = NULL;
- + memset(&clientPtr->internalRep, 0, sizeof(clientPtr->internalRep));
- + }
- + }
- +
- + /* Convert back to a plain object of type typePtr */
- + objPtr->internalRep = fakeObj.internalRep;
- + objPtr->typePtr = typePtr;
- + Tcl_Free((char *)hydraPtr);
- + }
- +}
- /*
- *----------------------------------------------------------------------
- *
- @@ -4694,6 +5046,32 @@ Tcl_RepresentationCmd(
- Tcl_AppendToObj(descObj, ", no string representation", -1);
- }
- + if (objv[1]->typePtr == &tclHydraType) {
- + int i;
- + Hydra *hydraPtr;
- +
- + Tcl_AppendToObj(descObj, ", with client representations:", -1);
- + HydraGetIntRep(objv[1], hydraPtr);
- + for (i=0; i<MAX_HYDRA_CLIENTS; i++) {
- + HydraClient *clientPtr = &hydraPtr->client[i];
- +
- + if (clientPtr->typePtr == NULL) {
- + continue;
- + }
- +
- + Tcl_AppendPrintfToObj(descObj, "\n\t%d: %s", i, clientPtr->typePtr->name);
- +
- + if (clientPtr->typePtr == &tclDoubleType) {
- + Tcl_AppendPrintfToObj(descObj, ", internal representation %g",
- + clientPtr->internalRep.doubleValue);
- + } else {
- + Tcl_AppendPrintfToObj(descObj, ", internal representation %p:%p",
- + (void *) clientPtr->internalRep.twoPtrValue.ptr1,
- + (void *) clientPtr->internalRep.twoPtrValue.ptr2);
- + }
- + }
- + }
- +
- Tcl_SetObjResult(interp, descObj);
- return TCL_OK;
- }
- diff --git a/generic/tclStringRep.h b/generic/tclStringRep.h
- index 1ef1957..506d2f7 100644
- --- a/generic/tclStringRep.h
- +++ b/generic/tclStringRep.h
- @@ -84,9 +84,21 @@ typedef struct {
- #define stringAttemptRealloc(ptr, numChars) \
- (String *) attemptckrealloc((ptr), STRING_SIZE(numChars))
- #define GET_STRING(objPtr) \
- - ((String *) (objPtr)->internalRep.twoPtrValue.ptr1)
- + ((String *) ((Tcl_FetchIntRep((objPtr), &tclStringType))->twoPtrValue.ptr1))
- #define SET_STRING(objPtr, stringPtr) \
- - ((objPtr)->internalRep.twoPtrValue.ptr1 = (void *) (stringPtr))
- + do { \
- + Tcl_ObjIntRep *irPtr; \
- + Tcl_FreeOtherIntReps((objPtr), &tclStringType); \
- + irPtr = Tcl_FetchIntRep((objPtr), &tclStringType); \
- + if (irPtr == NULL) { \
- + Tcl_ObjIntRep newIr; \
- + newIr.twoPtrValue.ptr1 = (void *) (stringPtr); \
- + newIr.twoPtrValue.ptr2 = NULL; \
- + Tcl_StoreIntRep((objPtr), &tclStringType, &newIr); \
- + } else { \
- + irPtr->twoPtrValue.ptr1 = (void *) (stringPtr); \
- + } \
- + } while (0)
- /*
- * Local Variables:
- diff --git a/generic/tclStubInit.c b/generic/tclStubInit.c
- index 8ff6291..449464a 100644
- --- a/generic/tclStubInit.c
- +++ b/generic/tclStubInit.c
- @@ -1531,6 +1531,7 @@ const TclStubs tclStubs = {
- Tcl_FetchIntRep, /* 634 */
- Tcl_StoreIntRep, /* 635 */
- Tcl_HasStringRep, /* 636 */
- + Tcl_FreeOtherIntReps, /* 637 */
- };
- /* !END!: Do not edit above this line. */
- diff --git a/generic/tclVar.c b/generic/tclVar.c
- index 4c3d4a1..fa65be4 100644
- --- a/generic/tclVar.c
- +++ b/generic/tclVar.c
- @@ -5564,10 +5564,13 @@ DupLocalVarName(
- Tcl_Obj *namePtr;
- LocalGetIntRep(srcPtr, index, namePtr);
- - if (!namePtr) {
- - namePtr = srcPtr;
- + if (namePtr) {
- + LocalSetIntRep(dupPtr, index, namePtr);
- + } else {
- + dupPtr->typePtr = NULL;
- + dupPtr->internalRep.twoPtrValue.ptr1 = NULL;
- + dupPtr->internalRep.twoPtrValue.ptr2 = NULL;
- }
- - LocalSetIntRep(dupPtr, index, namePtr);
- }
- /*