diff options
author | dgp <dgp@users.sourceforge.net> | 2016-10-13 16:56:23 (GMT) |
---|---|---|
committer | dgp <dgp@users.sourceforge.net> | 2016-10-13 16:56:23 (GMT) |
commit | c98e9eebb58e1b55ba13f8af8714a8a1e580d746 (patch) | |
tree | c39ef5c763275e6a9d929d7ab59e5579ca1fdb1b | |
parent | 6293f8f90ba51c630d5e941443b9ca582ba23357 (diff) | |
parent | 23b011c32d44c8182e0a04316704b590bd2920dd (diff) | |
download | tcl-c98e9eebb58e1b55ba13f8af8714a8a1e580d746.zip tcl-c98e9eebb58e1b55ba13f8af8714a8a1e580d746.tar.gz tcl-c98e9eebb58e1b55ba13f8af8714a8a1e580d746.tar.bz2 |
Merge INST_STR_REPLACE fixes and improvements.
-rw-r--r-- | generic/tclExecute.c | 127 | ||||
-rw-r--r-- | generic/tclStringObj.c | 10 |
2 files changed, 52 insertions, 85 deletions
diff --git a/generic/tclExecute.c b/generic/tclExecute.c index df36958..85e059b 100644 --- a/generic/tclExecute.c +++ b/generic/tclExecute.c @@ -19,7 +19,6 @@ #include "tclCompile.h" #include "tclOOInt.h" #include "tommath.h" -#include "tclStringRep.h" #include <math.h> #include <assert.h> @@ -5731,51 +5730,29 @@ TEBCresume( if (length3 - 1 == toIdx - fromIdx) { unsigned char *bytes1, *bytes2; - /* - * Flush the info in the string internal rep that refers to the - * about-to-be-invalidated UTF-8 rep. This indicates that a new - * buffer needs to be allocated, and assumes that the value is - * already of tclStringTypePtr type, which should be true provided - * we call it after Tcl_GetUnicodeFromObj. - */ -#define MarkStringInternalRepForFlush(objPtr) \ - (GET_STRING(objPtr)->allocated = 0) - if (Tcl_IsShared(valuePtr)) { objResultPtr = Tcl_DuplicateObj(valuePtr); - if (TclIsPureByteArray(objResultPtr) - && TclIsPureByteArray(value3Ptr)) { - bytes1 = Tcl_GetByteArrayFromObj(objResultPtr, NULL); - bytes2 = Tcl_GetByteArrayFromObj(value3Ptr, NULL); - memcpy(bytes1 + fromIdx, bytes2, length3); - } else { - ustring1 = Tcl_GetUnicodeFromObj(objResultPtr, NULL); - ustring2 = Tcl_GetUnicodeFromObj(value3Ptr, NULL); - memcpy(ustring1 + fromIdx, ustring2, - length3 * sizeof(Tcl_UniChar)); - MarkStringInternalRepForFlush(objResultPtr); - } - Tcl_InvalidateStringRep(objResultPtr); - TclDecrRefCount(value3Ptr); - TRACE_APPEND(("\"%.30s\"\n", O2S(objResultPtr))); - NEXT_INST_F(1, 1, 1); } else { - if (TclIsPureByteArray(valuePtr) - && TclIsPureByteArray(value3Ptr)) { - bytes1 = Tcl_GetByteArrayFromObj(valuePtr, NULL); - bytes2 = Tcl_GetByteArrayFromObj(value3Ptr, NULL); - memcpy(bytes1 + fromIdx, bytes2, length3); - } else { - ustring1 = Tcl_GetUnicodeFromObj(valuePtr, NULL); - ustring2 = Tcl_GetUnicodeFromObj(value3Ptr, NULL); - memcpy(ustring1 + fromIdx, ustring2, - length3 * sizeof(Tcl_UniChar)); - MarkStringInternalRepForFlush(valuePtr); - } - Tcl_InvalidateStringRep(valuePtr); - TclDecrRefCount(value3Ptr); - TRACE_APPEND(("\"%.30s\"\n", O2S(valuePtr))); + objResultPtr = valuePtr; + } + if (TclIsPureByteArray(objResultPtr) + && TclIsPureByteArray(value3Ptr)) { + bytes1 = Tcl_GetByteArrayFromObj(objResultPtr, NULL); + bytes2 = Tcl_GetByteArrayFromObj(value3Ptr, NULL); + memcpy(bytes1 + fromIdx, bytes2, length3); + } else { + ustring1 = Tcl_GetUnicodeFromObj(objResultPtr, NULL); + ustring2 = Tcl_GetUnicodeFromObj(value3Ptr, NULL); + memcpy(ustring1 + fromIdx, ustring2, + length3 * sizeof(Tcl_UniChar)); + } + Tcl_InvalidateStringRep(objResultPtr); + TclDecrRefCount(value3Ptr); + TRACE_APPEND(("\"%.30s\"\n", O2S(objResultPtr))); + if (objResultPtr == valuePtr) { NEXT_INST_F(1, 0, 0); + } else { + NEXT_INST_F(1, 1, 1); } } @@ -5791,57 +5768,37 @@ TEBCresume( * Remove substring using copying. */ - if (length3 == 0) { - if (fromIdx > 0) { - objResultPtr = Tcl_NewUnicodeObj(ustring1, fromIdx); - if (toIdx < length) { - Tcl_AppendUnicodeToObj(objResultPtr, ustring1 + toIdx + 1, - length - toIdx); - } - } else { - objResultPtr = Tcl_NewUnicodeObj(ustring1 + toIdx + 1, - length - toIdx); - } - TclDecrRefCount(value3Ptr); - TRACE_APPEND(("\"%.30s\"\n", O2S(objResultPtr))); - NEXT_INST_F(1, 1, 1); - } - - /* - * Splice string pieces by full copying. - */ - + objResultPtr = NULL; if (fromIdx > 0) { objResultPtr = Tcl_NewUnicodeObj(ustring1, fromIdx); - Tcl_AppendObjToObj(objResultPtr, value3Ptr); - if (toIdx < length) { - Tcl_AppendUnicodeToObj(objResultPtr, ustring1 + toIdx + 1, - length - toIdx); + } + if (length3 > 0) { + if (objResultPtr) { + Tcl_AppendObjToObj(objResultPtr, value3Ptr); + } else if (Tcl_IsShared(value3Ptr)) { + objResultPtr = Tcl_DuplicateObj(value3Ptr); + } else { + objResultPtr = value3Ptr; } - } else if (Tcl_IsShared(value3Ptr)) { - objResultPtr = Tcl_DuplicateObj(value3Ptr); - if (toIdx < length) { + } + if (toIdx < length) { + if (objResultPtr) { Tcl_AppendUnicodeToObj(objResultPtr, ustring1 + toIdx + 1, length - toIdx); - } - } else { - /* - * Be careful with splicing the stack in this case; we have a - * refCount:1 object in value3Ptr and we want to append to it and - * make it be the refCount:1 object at the top of the stack - * afterwards. [Bug 82e7f67325] - */ - - if (toIdx < length) { - Tcl_AppendUnicodeToObj(value3Ptr, ustring1 + toIdx + 1, + } else { + objResultPtr = Tcl_NewUnicodeObj(ustring1 + toIdx + 1, length - toIdx); } - TRACE_APPEND(("\"%.30s\"\n", O2S(value3Ptr))); - TclDecrRefCount(valuePtr); - OBJ_AT_TOS = value3Ptr; /* Tricky! */ - NEXT_INST_F(1, 0, 0); } - TclDecrRefCount(value3Ptr); + if (objResultPtr == NULL) { + /* This has to be the case [string replace $s 0 end {}] */ + /* which has result {} which is same as value3Ptr. */ + objResultPtr = value3Ptr; + } + if (objResultPtr != value3Ptr) { + /* See [Bug 82e7f67325] */ + TclDecrRefCount(value3Ptr); + } TRACE_APPEND(("\"%.30s\"\n", O2S(objResultPtr))); NEXT_INST_F(1, 1, 1); diff --git a/generic/tclStringObj.c b/generic/tclStringObj.c index e3cede6..2930fa1 100644 --- a/generic/tclStringObj.c +++ b/generic/tclStringObj.c @@ -2948,6 +2948,16 @@ UpdateStringOfString( { String *stringPtr = GET_STRING(objPtr); + /* + * This routine is only called when we need to generate the + * string rep objPtr->bytes because it does not exist -- it is NULL. + * In that circumstance, any lingering claim about the size of + * memory pointed to by that NULL pointer is clearly bogus, and + * needs a reset. + */ + + stringPtr->allocated = 0; + if (stringPtr->numChars == 0) { TclInitStringRep(objPtr, tclEmptyStringRep, 0); } else { |