Compare commits

...
Author SHA1 Message Date
dgp 6fd2ed3f11 Convert the "bytearray" Tcl_ObjType to use the proposed Tcl_ObjIntRep
manipulation routines.  This works, but requires too much ugliness.
The ugliness reveals that the interface needs some refinement, making
this a rejected branch of development.
2016-03-26 12:36:01 +00:00
dgp 0276b6e644 irPtr = NULL passed to Tcl_StoreIntRep clears out any value for typePtr. 2016-03-25 20:01:39 +00:00
dgp 3bd8840931 Get signatures in sync. 2016-03-25 19:56:56 +00:00
dgp 36cf99464d First demonstration conversion to the new intrep manipulation routines. 2016-03-25 14:01:00 +00:00
dgp f19cbcbff5 New routines Tcl_FetchIntRep() and Tcl_StoreIntRep(). 2016-03-25 13:06:53 +00:00
dgp c7039276a0 Create a type Tcl_ObjIntRep so we can pass intreps as arguments. 2016-03-25 12:24:04 +00:00
dgp 1f136d8cb6 merge trunk 2016-03-24 21:22:51 +00:00
dgp a5e1e1f33e Revise the "index" Tcl_ObjType to use the new routine. 2016-03-24 21:11:52 +00:00
dgp 1bebb796bb Revise the "instname" Tcl_ObjType to use the routines. 2016-03-24 20:33:27 +00:00
dgp a19375e928 oops 2016-03-24 20:17:52 +00:00
dgp 413706af15 Update Tcl_InitStringRep callers to handle OOM condition. 2016-03-24 20:15:01 +00:00
dgp 8370f3e275 Revise Tcl_InitStringRep() to do non-panic attempt at allocation.
Let caller decide how catastrophic it is.
Revise [string repeat] to use new routine.
2016-03-24 19:21:47 +00:00
dgp 959413c95a More purging of direct access to bytes field where it isn't important. 2016-03-24 15:01:43 +00:00
dgp 325b2f4ade Update more Tcl_ObjTypes to use Tcl_InitStringRep().
Adapt TclInitStringRep macro to accept TclInitStringRep(objptr, NULL, 0)
without warning -- requires outwitting compiler.
2016-03-24 14:40:35 +00:00
dgp 83ac8470a0 TclInitStringRep() already knows about tclEmptyStringRep. 2016-03-24 13:50:59 +00:00
dgp f6b543ae94 oops 2016-03-24 13:16:42 +00:00
dgp e9a10d7cda stay out of internals when nice interfaces are available. 2016-03-24 12:59:06 +00:00
dgp dc0adeafb4 Revised "end-offset" Tcl_ObjType to use new routine. 2016-03-24 12:51:49 +00:00
dgp 80bc5b30c2 Revise "osType" Tcl_ObjType to use new routine. 2016-03-24 01:50:58 +00:00
dgp 0412f3af19 Revise "ensembleCommand" Tcl_ObjType to use new routines. 2016-03-23 21:50:15 +00:00
dgp c79a28077f Convert "dict" Tcl_ObjType to use new routines. 2016-03-23 21:36:29 +00:00
dgp 6bd1189ac2 merge trunk 2016-03-23 15:21:35 +00:00
dgp 422d353b0a Tcl_InitStringRep() bug. Truncation assumed length == allocated. Wrong!
Convert "bytearray" Tcl_ObjType to used new facilities. No longer directly
refers to bytes or length fields, or any ckalloc of string rep.
2016-03-23 15:19:05 +00:00
dgp 847f2ba0d5 Revise Tcl_InitStringRep(); numBytes is unsigned. Only truncation permitted. 2016-03-23 14:10:39 +00:00
dgp cae0944eda Release memory after truncation. 2016-03-23 10:10:10 +00:00
dgp 37f5c2af03 Make sure no path emerges to write on tclEmptyStringRep. 2016-03-23 04:50:21 +00:00
dgp 95de12dbb4 Next step: new routine Tcl_InitStringRep() 2016-03-23 04:31:24 +00:00
dgp de712c24fb First simple step implementing TIP 445. 2016-03-22 23:45:12 +00:00
18 changed files with 498 additions and 257 deletions
+19
View File
@@ -2326,6 +2326,25 @@ declare 630 {
# ----- BASELINE -- FOR -- 8.6.0 ----- #
# TIP #445
declare 631 {
void Tcl_FreeIntRep(Tcl_Obj *objPtr)
}
declare 632 {
char *Tcl_InitStringRep(Tcl_Obj *objPtr, const char *bytes,
unsigned int numBytes)
}
declare 633 {
const Tcl_ObjIntRep *Tcl_FetchIntRep(Tcl_Obj *objPtr,
const Tcl_ObjType *typePtr)
}
declare 634 {
void Tcl_StoreIntRep(Tcl_Obj *objPtr, const Tcl_ObjType *typePtr,
const Tcl_ObjIntRep *irPtr)
}
# ----- BASELINE -- FOR -- 8.7.0 ----- #
##############################################################################
# Define the platform specific public Tcl interface. These functions are only
+24 -20
View File
@@ -800,6 +800,29 @@ typedef struct Tcl_ObjType {
* old type. Returns TCL_ERROR on failure. */
} Tcl_ObjType;
/*
* The following structure stores an internal representation (intrep) for
* a Tcl value. An intrep is associated with an Tcl_ObjType when both
* are stored in the same Tcl_Obj. The routines of the Tcl_ObjType govern
* the handling of the intrep.
*/
typedef union Tcl_ObjIntRep { /* The internal representation: */
long longValue; /* - an long integer value. */
double doubleValue; /* - a double-precision floating value. */
void *otherValuePtr; /* - another, type-specific value, */
/* not used internally any more. */
Tcl_WideInt wideValue; /* - an integer value >= 64bits */
struct { /* - internal rep as two pointers. */
void *ptr1;
void *ptr2;
} twoPtrValue;
struct { /* - internal rep as a pointer and a long, */
void *ptr; /* not used internally any more. */
unsigned long value;
} ptrAndLongRep;
} Tcl_ObjIntRep;
/*
* One of the following structures exists for each object in the Tcl system.
* An object stores a value as either a string, some internal representation,
@@ -825,26 +848,7 @@ typedef struct Tcl_Obj {
* corresponds to the type of the object's
* internal rep. NULL indicates the object has
* no internal rep (has no type). */
union { /* The internal representation: */
long longValue; /* - an long integer value. */
double doubleValue; /* - a double-precision floating value. */
void *otherValuePtr; /* - another, type-specific value,
not used internally any more. */
Tcl_WideInt wideValue; /* - a long long value. */
struct { /* - internal rep as two pointers.
* the main use of which is a bignum's
* tightly packed fields, where the alloc,
* used and signum flags are packed into
* ptr2 with everything else hung off ptr1. */
void *ptr1;
void *ptr2;
} twoPtrValue;
struct { /* - internal rep as a pointer and a long,
not used internally any more. */
void *ptr;
unsigned long value;
} ptrAndLongRep;
} internalRep;
Tcl_ObjIntRep internalRep; /* The internal representation: */
} Tcl_Obj;
/*
+95 -79
View File
@@ -15,6 +15,7 @@
#include "tommath.h"
#include <math.h>
#include <assert.h>
/*
* The following constants are used by GetFormatSpec to indicate various
@@ -195,9 +196,9 @@ const Tcl_ObjType tclByteArrayType = {
*/
typedef struct ByteArray {
int used; /* The number of bytes used in the byte
unsigned int used; /* The number of bytes used in the byte
* array. */
int allocated; /* The amount of space actually allocated
unsigned int allocated; /* The amount of space actually allocated
* minus 1 byte. */
unsigned char bytes[1]; /* The array of bytes. The actual size of this
* field depends on the 'allocated' field
@@ -206,10 +207,9 @@ typedef struct ByteArray {
#define BYTEARRAY_SIZE(len) \
((unsigned) (TclOffset(ByteArray, bytes) + (len)))
#define GET_BYTEARRAY(objPtr) \
((ByteArray *) (objPtr)->internalRep.twoPtrValue.ptr1)
#define SET_BYTEARRAY(objPtr, baPtr) \
(objPtr)->internalRep.twoPtrValue.ptr1 = (void *) (baPtr)
#define GET_BYTEARRAY(irPtr) ((ByteArray *) (irPtr)->twoPtrValue.ptr1)
#define SET_BYTEARRAY(irPtr, baPtr) \
(irPtr)->twoPtrValue.ptr1 = (void *) (baPtr)
/*
@@ -324,11 +324,11 @@ Tcl_SetByteArrayObj(
be >= 0. */
{
ByteArray *byteArrayPtr;
Tcl_ObjIntRep ir;
if (Tcl_IsShared(objPtr)) {
Tcl_Panic("%s called with shared object", "Tcl_SetByteArrayObj");
}
TclFreeIntRep(objPtr);
TclInvalidateStringRep(objPtr);
if (length < 0) {
@@ -341,8 +341,9 @@ Tcl_SetByteArrayObj(
if ((bytes != NULL) && (length > 0)) {
memcpy(byteArrayPtr->bytes, bytes, (size_t) length);
}
objPtr->typePtr = &tclByteArrayType;
SET_BYTEARRAY(objPtr, byteArrayPtr);
SET_BYTEARRAY(&ir, byteArrayPtr);
Tcl_StoreIntRep(objPtr, &tclByteArrayType, &ir);
}
/*
@@ -370,16 +371,18 @@ Tcl_GetByteArrayFromObj(
* array of bytes in the ByteArray object. */
{
ByteArray *baPtr;
const Tcl_ObjIntRep *irPtr = Tcl_FetchIntRep(objPtr, &tclByteArrayType);
if (objPtr->typePtr != &tclByteArrayType) {
if (irPtr == NULL) {
SetByteArrayFromAny(NULL, objPtr);
irPtr = Tcl_FetchIntRep(objPtr, &tclByteArrayType);
}
baPtr = GET_BYTEARRAY(objPtr);
baPtr = GET_BYTEARRAY(irPtr);
if (lengthPtr != NULL) {
*lengthPtr = baPtr->used;
}
return (unsigned char *) baPtr->bytes;
return baPtr->bytes;
}
/*
@@ -410,22 +413,34 @@ Tcl_SetByteArrayLength(
int length) /* New length for internal byte array. */
{
ByteArray *byteArrayPtr;
unsigned newLength;
const Tcl_ObjIntRep *irPtr;
assert(length >= 0);
newLength = (unsigned int)length;
if (Tcl_IsShared(objPtr)) {
Tcl_Panic("%s called with shared object", "Tcl_SetByteArrayLength");
}
if (objPtr->typePtr != &tclByteArrayType) {
irPtr = Tcl_FetchIntRep(objPtr, &tclByteArrayType);
if (irPtr == NULL) {
SetByteArrayFromAny(NULL, objPtr);
irPtr = Tcl_FetchIntRep(objPtr, &tclByteArrayType);
}
byteArrayPtr = GET_BYTEARRAY(objPtr);
if (length > byteArrayPtr->allocated) {
byteArrayPtr = ckrealloc(byteArrayPtr, BYTEARRAY_SIZE(length));
byteArrayPtr->allocated = length;
SET_BYTEARRAY(objPtr, byteArrayPtr);
byteArrayPtr = GET_BYTEARRAY(irPtr);
if (newLength > byteArrayPtr->allocated) {
Tcl_ObjIntRep ir;
/* UGLY UGLY UGLY */
objPtr->typePtr = NULL;
byteArrayPtr = ckrealloc(byteArrayPtr, BYTEARRAY_SIZE(newLength));
byteArrayPtr->allocated = newLength;
SET_BYTEARRAY(&ir, byteArrayPtr);
Tcl_StoreIntRep(objPtr, &tclByteArrayType, &ir);
}
TclInvalidateStringRep(objPtr);
byteArrayPtr->used = length;
byteArrayPtr->used = newLength;
return byteArrayPtr->bytes;
}
@@ -454,25 +469,26 @@ SetByteArrayFromAny(
const char *src, *srcEnd;
unsigned char *dst;
ByteArray *byteArrayPtr;
Tcl_UniChar ch;
Tcl_ObjIntRep ir;
if (objPtr->typePtr != &tclByteArrayType) {
src = TclGetStringFromObj(objPtr, &length);
srcEnd = src + length;
assert (NULL == Tcl_FetchIntRep(objPtr, &tclByteArrayType));
byteArrayPtr = ckalloc(BYTEARRAY_SIZE(length));
for (dst = byteArrayPtr->bytes; src < srcEnd; ) {
src += Tcl_UtfToUniChar(src, &ch);
*dst++ = UCHAR(ch);
}
src = TclGetStringFromObj(objPtr, &length);
srcEnd = src + length;
byteArrayPtr->used = dst - byteArrayPtr->bytes;
byteArrayPtr->allocated = length;
byteArrayPtr = ckalloc(BYTEARRAY_SIZE(length));
for (dst = byteArrayPtr->bytes; src < srcEnd; ) {
Tcl_UniChar ch;
TclFreeIntRep(objPtr);
objPtr->typePtr = &tclByteArrayType;
SET_BYTEARRAY(objPtr, byteArrayPtr);
src += Tcl_UtfToUniChar(src, &ch);
*dst++ = UCHAR(ch);
}
byteArrayPtr->used = dst - byteArrayPtr->bytes;
byteArrayPtr->allocated = length;
SET_BYTEARRAY(&ir, byteArrayPtr);
Tcl_StoreIntRep(objPtr, &tclByteArrayType, &ir);
return TCL_OK;
}
@@ -497,8 +513,7 @@ static void
FreeByteArrayInternalRep(
Tcl_Obj *objPtr) /* Object with internal rep to free. */
{
ckfree(GET_BYTEARRAY(objPtr));
objPtr->typePtr = NULL;
ckfree(GET_BYTEARRAY(Tcl_FetchIntRep(objPtr, &tclByteArrayType)));
}
/*
@@ -523,19 +538,20 @@ DupByteArrayInternalRep(
Tcl_Obj *srcPtr, /* Object with internal rep to copy. */
Tcl_Obj *copyPtr) /* Object with internal rep to set. */
{
int length;
unsigned int length;
ByteArray *srcArrayPtr, *copyArrayPtr;
Tcl_ObjIntRep ir;
srcArrayPtr = GET_BYTEARRAY(srcPtr);
srcArrayPtr = GET_BYTEARRAY(Tcl_FetchIntRep(srcPtr, &tclByteArrayType));
length = srcArrayPtr->used;
copyArrayPtr = ckalloc(BYTEARRAY_SIZE(length));
copyArrayPtr->used = length;
copyArrayPtr->allocated = length;
memcpy(copyArrayPtr->bytes, srcArrayPtr->bytes, (size_t) length);
SET_BYTEARRAY(copyPtr, copyArrayPtr);
copyPtr->typePtr = &tclByteArrayType;
SET_BYTEARRAY(&ir, copyArrayPtr);
Tcl_StoreIntRep(copyPtr, &tclByteArrayType, &ir);
}
/*
@@ -543,9 +559,7 @@ DupByteArrayInternalRep(
*
* UpdateStringOfByteArray --
*
* Update the string representation for a ByteArray data object. Note:
* This procedure does not invalidate an existing old string rep so
* storage will be lost if this has not already been done.
* Update the string representation for a ByteArray data object.
*
* Results:
* None.
@@ -554,9 +568,6 @@ DupByteArrayInternalRep(
* The object's string is set to a valid string that results from the
* ByteArray-to-string conversion.
*
* The object becomes a string object -- the internal rep is discarded
* and the typePtr becomes NULL.
*
*----------------------------------------------------------------------
*/
@@ -565,41 +576,35 @@ UpdateStringOfByteArray(
Tcl_Obj *objPtr) /* ByteArray object whose string rep to
* update. */
{
int i, length, size;
unsigned char *src;
char *dst;
ByteArray *byteArrayPtr;
byteArrayPtr = GET_BYTEARRAY(objPtr);
src = byteArrayPtr->bytes;
length = byteArrayPtr->used;
const Tcl_ObjIntRep *irPtr = Tcl_FetchIntRep(objPtr, &tclByteArrayType);
ByteArray *byteArrayPtr = GET_BYTEARRAY(irPtr);
unsigned char *src = byteArrayPtr->bytes;
unsigned int i, length = byteArrayPtr->used;
unsigned int size = length;
/*
* How much space will string rep need?
*/
size = length;
for (i = 0; i < length && size >= 0; i++) {
for (i = 0; i < length && size <= INT_MAX; i++) {
if ((src[i] == 0) || (src[i] > 127)) {
size++;
}
}
if (size < 0) {
if (size > INT_MAX) {
Tcl_Panic("max size for a Tcl value (%d bytes) exceeded", INT_MAX);
}
dst = ckalloc(size + 1);
objPtr->bytes = dst;
objPtr->length = size;
if (size == length) {
memcpy(dst, src, (size_t) size);
dst[size] = '\0';
char *dst = Tcl_InitStringRep(objPtr, (char *)src, size);
TclOOM(dst, size);
} else {
char *dst = Tcl_InitStringRep(objPtr, NULL, size);
TclOOM(dst, size);
for (i = 0; i < length; i++) {
dst += Tcl_UniCharToUtf(src[i], dst);
}
*dst = '\0';
(void)Tcl_InitStringRep(objPtr, NULL, size);
}
}
@@ -629,7 +634,8 @@ TclAppendBytesToByteArray(
int len)
{
ByteArray *byteArrayPtr;
int needed;
unsigned int length, needed;
const Tcl_ObjIntRep *irPtr;
if (Tcl_IsShared(objPtr)) {
Tcl_Panic("%s called with shared object","TclAppendBytesToByteArray");
@@ -642,24 +648,31 @@ TclAppendBytesToByteArray(
/* Append zero bytes is a no-op. */
return;
}
if (objPtr->typePtr != &tclByteArrayType) {
SetByteArrayFromAny(NULL, objPtr);
}
byteArrayPtr = GET_BYTEARRAY(objPtr);
length = (unsigned int)len;
if (len > INT_MAX - byteArrayPtr->used) {
irPtr = Tcl_FetchIntRep(objPtr, &tclByteArrayType);
if (irPtr == NULL) {
SetByteArrayFromAny(NULL, objPtr);
irPtr = Tcl_FetchIntRep(objPtr, &tclByteArrayType);
}
byteArrayPtr = GET_BYTEARRAY(irPtr);
if (length > INT_MAX - byteArrayPtr->used) {
Tcl_Panic("max size for a Tcl value (%d bytes) exceeded", INT_MAX);
}
needed = byteArrayPtr->used + len;
needed = byteArrayPtr->used + length;
/*
* If we need to, resize the allocated space in the byte array.
*/
if (needed > byteArrayPtr->allocated) {
ByteArray *ptr = NULL;
int attempt;
unsigned int attempt;
Tcl_ObjIntRep ir;
/* UGLY UGLY UGLY */
objPtr->typePtr = NULL;
if (needed <= INT_MAX/2) {
/* Try to allocate double the total space that is needed. */
attempt = 2 * needed;
@@ -668,7 +681,7 @@ TclAppendBytesToByteArray(
if (ptr == NULL) {
/* Try to allocate double the increment that is needed (plus). */
unsigned int limit = INT_MAX - needed;
unsigned int extra = len + TCL_MIN_GROWTH;
unsigned int extra = length + TCL_MIN_GROWTH;
int growth = (int) ((extra > limit) ? limit : extra);
attempt = needed + growth;
@@ -681,13 +694,14 @@ TclAppendBytesToByteArray(
}
byteArrayPtr = ptr;
byteArrayPtr->allocated = attempt;
SET_BYTEARRAY(objPtr, byteArrayPtr);
SET_BYTEARRAY(&ir, byteArrayPtr);
Tcl_StoreIntRep(objPtr, &tclByteArrayType, &ir);
}
if (bytes) {
memcpy(byteArrayPtr->bytes + byteArrayPtr->used, bytes, len);
memcpy(byteArrayPtr->bytes + byteArrayPtr->used, bytes, length);
}
byteArrayPtr->used += len;
byteArrayPtr->used += length;
TclInvalidateStringRep(objPtr);
}
@@ -1881,10 +1895,11 @@ FormatNumber(
*/
if (Tcl_GetDoubleFromObj(interp, src, &dvalue) != TCL_OK) {
if (src->typePtr != &tclDoubleType) {
const Tcl_ObjIntRep *irPtr = Tcl_FetchIntRep(src, &tclDoubleType);
if (irPtr == NULL) {
return TCL_ERROR;
}
dvalue = src->internalRep.doubleValue;
dvalue = irPtr->doubleValue;
}
CopyNumber(&dvalue, *cursorPtr, sizeof(double), type);
*cursorPtr += sizeof(double);
@@ -1900,10 +1915,11 @@ FormatNumber(
*/
if (Tcl_GetDoubleFromObj(interp, src, &dvalue) != TCL_OK) {
if (src->typePtr != &tclDoubleType) {
const Tcl_ObjIntRep *irPtr = Tcl_FetchIntRep(src, &tclDoubleType);
if (irPtr == NULL) {
return TCL_ERROR;
}
dvalue = src->internalRep.doubleValue;
dvalue = irPtr->doubleValue;
}
/*
+4 -14
View File
@@ -544,9 +544,9 @@ InfoBodyCmd(
Tcl_Obj *const objv[]) /* Argument objects. */
{
register Interp *iPtr = (Interp *) interp;
const char *name;
const char *name, *bytes;
Proc *procPtr;
Tcl_Obj *bodyPtr, *resultPtr;
int numBytes;
if (objc != 2) {
Tcl_WrongNumArgs(interp, 1, objv, "procname");
@@ -571,18 +571,8 @@ InfoBodyCmd(
* the object do not invalidate the internal rep.
*/
bodyPtr = procPtr->bodyPtr;
if (bodyPtr->bytes == NULL) {
/*
* The string rep might not be valid if the procedure has never been
* run before. [Bug #545644]
*/
TclGetString(bodyPtr);
}
resultPtr = Tcl_NewStringObj(bodyPtr->bytes, bodyPtr->length);
Tcl_SetObjResult(interp, resultPtr);
bytes = Tcl_GetStringFromObj(procPtr->bodyPtr, &numBytes);
Tcl_SetObjResult(interp, Tcl_NewStringObj(bytes, numBytes));
return TCL_OK;
}
+5 -16
View File
@@ -2275,11 +2275,9 @@ StringReptCmd(
}
length2 = length1 * count;
/*
* Include space for the NUL.
*/
string2 = attemptckalloc((unsigned) length2 + 1);
TclNewObj(resultPtr);
Tcl_InvalidateStringRep(resultPtr);
string2 = Tcl_InitStringRep(resultPtr, NULL, length2);
if (string2 == NULL) {
/*
* Alloc failed. Note that in this case we try to do an error message
@@ -2292,22 +2290,13 @@ StringReptCmd(
"string size overflow, out of memory allocating %u bytes",
length2 + 1));
Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL);
Tcl_DecrRefCount(resultPtr);
return TCL_ERROR;
}
for (index = 0; index < count; index++) {
memcpy(string2 + (length1 * index), string1, (size_t) length1);
}
string2[length2] = '\0';
/*
* We have to directly assign this instead of using Tcl_SetStringObj (and
* indirectly TclInitStringRep) because that makes another copy of the
* data.
*/
TclNewObj(resultPtr);
resultPtr->bytes = string2;
resultPtr->length = length2;
(void) Tcl_InitStringRep(resultPtr, NULL, length2);
Tcl_SetObjResult(interp, resultPtr);
done:
+24
View File
@@ -1816,6 +1816,18 @@ EXTERN int Tcl_FSUnloadFile(Tcl_Interp *interp,
EXTERN void Tcl_ZlibStreamSetCompressionDictionary(
Tcl_ZlibStream zhandle,
Tcl_Obj *compressionDictionaryObj);
/* 631 */
EXTERN void Tcl_FreeIntRep(Tcl_Obj *objPtr);
/* 632 */
EXTERN char * Tcl_InitStringRep(Tcl_Obj *objPtr, const char *bytes,
unsigned int numBytes);
/* 633 */
EXTERN const Tcl_ObjIntRep * Tcl_FetchIntRep(Tcl_Obj *objPtr,
const Tcl_ObjType *typePtr);
/* 634 */
EXTERN void Tcl_StoreIntRep(Tcl_Obj *objPtr,
const Tcl_ObjType *typePtr,
const Tcl_ObjIntRep *irPtr);
typedef struct {
const struct TclPlatStubs *tclPlatStubs;
@@ -2482,6 +2494,10 @@ typedef struct TclStubs {
void * (*tcl_FindSymbol) (Tcl_Interp *interp, Tcl_LoadHandle handle, const char *symbol); /* 628 */
int (*tcl_FSUnloadFile) (Tcl_Interp *interp, Tcl_LoadHandle handlePtr); /* 629 */
void (*tcl_ZlibStreamSetCompressionDictionary) (Tcl_ZlibStream zhandle, Tcl_Obj *compressionDictionaryObj); /* 630 */
void (*tcl_FreeIntRep) (Tcl_Obj *objPtr); /* 631 */
char * (*tcl_InitStringRep) (Tcl_Obj *objPtr, const char *bytes, unsigned int numBytes); /* 632 */
const Tcl_ObjIntRep * (*tcl_FetchIntRep) (Tcl_Obj *objPtr, const Tcl_ObjType *typePtr); /* 633 */
void (*tcl_StoreIntRep) (Tcl_Obj *objPtr, const Tcl_ObjType *typePtr, const Tcl_ObjIntRep *irPtr); /* 634 */
} TclStubs;
extern const TclStubs *tclStubsPtr;
@@ -3774,6 +3790,14 @@ extern const TclStubs *tclStubsPtr;
(tclStubsPtr->tcl_FSUnloadFile) /* 629 */
#define Tcl_ZlibStreamSetCompressionDictionary \
(tclStubsPtr->tcl_ZlibStreamSetCompressionDictionary) /* 630 */
#define Tcl_FreeIntRep \
(tclStubsPtr->tcl_FreeIntRep) /* 631 */
#define Tcl_InitStringRep \
(tclStubsPtr->tcl_InitStringRep) /* 632 */
#define Tcl_FetchIntRep \
(tclStubsPtr->tcl_FetchIntRep) /* 633 */
#define Tcl_StoreIntRep \
(tclStubsPtr->tcl_StoreIntRep) /* 634 */
#endif /* defined(USE_TCL_STUBS) */
+18 -12
View File
@@ -513,8 +513,7 @@ UpdateStringOfDict(
/* Handle empty list case first, simplifies what follows */
if (numElems == 0) {
dictPtr->bytes = tclEmptyStringRep;
dictPtr->length = 0;
Tcl_InitStringRep(dictPtr, NULL, 0);
return;
}
@@ -560,9 +559,8 @@ UpdateStringOfDict(
* Pass 2: copy into string rep buffer.
*/
dictPtr->length = bytesNeeded - 1;
dictPtr->bytes = ckalloc(bytesNeeded);
dst = dictPtr->bytes;
dst = Tcl_InitStringRep(dictPtr, NULL, bytesNeeded - 1);
TclOOM(dst, bytesNeeded);
for (i=0,cPtr=dict->entryChainHead; i<numElems; i+=2,cPtr=cPtr->nextPtr) {
flagPtr[i] |= ( i ? TCL_DONT_QUOTE_HASH : 0 );
keyPtr = Tcl_GetHashKey(&dict->table, &cPtr->entry);
@@ -576,7 +574,7 @@ UpdateStringOfDict(
dst += TclConvertElement(elem, length, dst, flagPtr[i+1]);
*dst++ = ' ';
}
dictPtr->bytes[dictPtr->length] = '\0';
(void)Tcl_InitStringRep(dictPtr, NULL, bytesNeeded - 1);
if (flagPtr != localFlags) {
ckfree(flagPtr);
@@ -675,10 +673,14 @@ SetDictFromAny(
TclNewStringObj(keyPtr, elemStart, elemSize);
} else {
/* Avoid double copy */
char *dst;
TclNewObj(keyPtr);
keyPtr->bytes = ckalloc((unsigned) elemSize + 1);
keyPtr->length = TclCopyAndCollapse(elemSize, elemStart,
keyPtr->bytes);
Tcl_InvalidateStringRep(keyPtr);
dst = Tcl_InitStringRep(keyPtr, NULL, elemSize);
TclOOM(dst, elemSize); /* Consider error */
(void)Tcl_InitStringRep(keyPtr, NULL,
TclCopyAndCollapse(elemSize, elemStart, dst));
}
if (TclFindDictElement(interp, nextElem, (limit - nextElem),
@@ -691,10 +693,14 @@ SetDictFromAny(
TclNewStringObj(valuePtr, elemStart, elemSize);
} else {
/* Avoid double copy */
char *dst;
TclNewObj(valuePtr);
valuePtr->bytes = ckalloc((unsigned) elemSize + 1);
valuePtr->length = TclCopyAndCollapse(elemSize, elemStart,
valuePtr->bytes);
Tcl_InvalidateStringRep(valuePtr);
dst = Tcl_InitStringRep(valuePtr, NULL, elemSize);
TclOOM(dst, elemSize); /* Consider error */
(void)Tcl_InitStringRep(valuePtr, NULL,
TclCopyAndCollapse(elemSize, elemStart, dst));
}
/* Store key and value in the hash table we're building. */
+10 -9
View File
@@ -804,6 +804,7 @@ TclNewInstNameObj(
objPtr->typePtr = &tclInstNameType;
objPtr->internalRep.longValue = (long) inst;
/* Optimized Tcl_InvalidateStringRep */
objPtr->bytes = NULL;
return objPtr;
@@ -824,19 +825,19 @@ UpdateStringOfInstName(
Tcl_Obj *objPtr)
{
int inst = objPtr->internalRep.longValue;
char *s, buf[20];
int len;
char *dst;
if ((inst < 0) || (inst > LAST_INST_OPCODE)) {
sprintf(buf, "inst_%d", inst);
s = buf;
dst = Tcl_InitStringRep(objPtr, NULL, TCL_INTEGER_SPACE + 4);
TclOOM(dst, TCL_INTEGER_SPACE + 4);
sprintf(dst, "inst_%d", inst);
(void) Tcl_InitStringRep(objPtr, NULL, strlen(dst));
} else {
s = (char *) tclInstructionTable[objPtr->internalRep.longValue].name;
const char *s = tclInstructionTable[objPtr->internalRep.longValue].name;
int len = strlen(s);
dst = Tcl_InitStringRep(objPtr, s, len);
TclOOM(dst, len);
}
len = strlen(s);
objPtr->bytes = ckalloc(len + 1);
memcpy(objPtr->bytes, s, len + 1);
objPtr->length = len;
}
/*
+3 -4
View File
@@ -2703,11 +2703,10 @@ StringOfEnsembleCmdRep(
Tcl_Obj *objPtr)
{
EnsembleCmdRep *ensembleCmd = objPtr->internalRep.twoPtrValue.ptr1;
int length = strlen(ensembleCmd->fullSubcmdName);
unsigned int size = strlen(ensembleCmd->fullSubcmdName);
char *dst = Tcl_InitStringRep(objPtr, ensembleCmd->fullSubcmdName, size);
objPtr->length = length;
objPtr->bytes = ckalloc(length + 1);
memcpy(objPtr->bytes, ensembleCmd->fullSubcmdName, (unsigned) length+1);
TclOOM(dst, size);
}
/*
+35 -34
View File
@@ -114,15 +114,16 @@ Tcl_GetIndexFromObj(
int flags, /* 0 or TCL_EXACT */
int *indexPtr) /* Place to store resulting integer index. */
{
/*
* See if there is a valid cached result from a previous lookup (doing the
* check here saves the overhead of calling Tcl_GetIndexFromObjStruct in
* the common case where the result is cached).
*/
if (objPtr->typePtr == &indexType) {
IndexRep *indexRep = objPtr->internalRep.twoPtrValue.ptr1;
const Tcl_ObjIntRep *irPtr = Tcl_FetchIntRep(objPtr, &indexType);
if (irPtr) {
IndexRep *indexRep = irPtr->twoPtrValue.ptr1;
/*
* Here's hoping we don't get hit by unfortunate packing constraints
@@ -270,6 +271,7 @@ Tcl_GetIndexFromObjStruct(
const char *const *entryPtr;
Tcl_Obj *resultPtr;
IndexRep *indexRep;
const Tcl_ObjIntRep *irPtr;
/* Protect against invalid values, like -1 or 0. */
if (offset < (int)sizeof(char *)) {
@@ -279,8 +281,9 @@ Tcl_GetIndexFromObjStruct(
* See if there is a valid cached result from a previous lookup.
*/
if (objPtr->typePtr == &indexType) {
indexRep = objPtr->internalRep.twoPtrValue.ptr1;
irPtr = Tcl_FetchIntRep(objPtr, &indexType);
if (irPtr) {
indexRep = irPtr->twoPtrValue.ptr1;
if (indexRep->tablePtr==tablePtr && indexRep->offset==offset) {
*indexPtr = indexRep->index;
return TCL_OK;
@@ -340,13 +343,15 @@ Tcl_GetIndexFromObjStruct(
* operation.
*/
if (objPtr->typePtr == &indexType) {
indexRep = objPtr->internalRep.twoPtrValue.ptr1;
irPtr = Tcl_FetchIntRep(objPtr, &indexType);
if (irPtr) {
indexRep = irPtr->twoPtrValue.ptr1;
} else {
TclFreeIntRep(objPtr);
Tcl_ObjIntRep ir;
indexRep = ckalloc(sizeof(IndexRep));
objPtr->internalRep.twoPtrValue.ptr1 = indexRep;
objPtr->typePtr = &indexType;
ir.twoPtrValue.ptr1 = indexRep;
Tcl_StoreIntRep(objPtr, &indexType, &ir);
}
indexRep->tablePtr = (void *) tablePtr;
indexRep->offset = offset;
@@ -448,16 +453,10 @@ static void
UpdateStringOfIndex(
Tcl_Obj *objPtr)
{
IndexRep *indexRep = objPtr->internalRep.twoPtrValue.ptr1;
register char *buf;
register unsigned len;
IndexRep *indexRep = Tcl_FetchIntRep(objPtr, &indexType)->twoPtrValue.ptr1;
register const char *indexStr = EXPAND_OF(indexRep);
len = strlen(indexStr);
buf = ckalloc(len + 1);
memcpy(buf, indexStr, len+1);
objPtr->bytes = buf;
objPtr->length = len;
Tcl_InitStringRep(objPtr, indexStr, strlen(indexStr));
}
/*
@@ -483,12 +482,14 @@ DupIndex(
Tcl_Obj *srcPtr,
Tcl_Obj *dupPtr)
{
IndexRep *srcIndexRep = srcPtr->internalRep.twoPtrValue.ptr1;
Tcl_ObjIntRep ir;
IndexRep *dupIndexRep = ckalloc(sizeof(IndexRep));
memcpy(dupIndexRep, srcIndexRep, sizeof(IndexRep));
dupPtr->internalRep.twoPtrValue.ptr1 = dupIndexRep;
dupPtr->typePtr = &indexType;
memcpy(dupIndexRep, Tcl_FetchIntRep(srcPtr, &indexType)->twoPtrValue.ptr1,
sizeof(IndexRep));
ir.twoPtrValue.ptr1 = dupIndexRep;
Tcl_StoreIntRep(dupPtr, &indexType, &ir);
}
/*
@@ -512,7 +513,7 @@ static void
FreeIndex(
Tcl_Obj *objPtr)
{
ckfree(objPtr->internalRep.twoPtrValue.ptr1);
ckfree(Tcl_FetchIntRep(objPtr, &indexType)->twoPtrValue.ptr1);
objPtr->typePtr = NULL;
}
@@ -950,16 +951,16 @@ Tcl_WrongNumArgs(
/*
* Add the element, quoting it if necessary.
*/
const Tcl_ObjIntRep *irPtr;
if (origObjv[i]->typePtr == &indexType) {
register IndexRep *indexRep =
origObjv[i]->internalRep.twoPtrValue.ptr1;
if ((irPtr = Tcl_FetchIntRep(origObjv[i], &indexType))) {
register IndexRep *indexRep = irPtr->twoPtrValue.ptr1;
elementStr = EXPAND_OF(indexRep);
elemLen = strlen(elementStr);
} else if (origObjv[i]->typePtr == &tclEnsembleCmdType) {
register EnsembleCmdRep *ecrPtr =
origObjv[i]->internalRep.twoPtrValue.ptr1;
} else if ((irPtr =
Tcl_FetchIntRep(origObjv[i], &tclEnsembleCmdType))) {
register EnsembleCmdRep *ecrPtr = irPtr->twoPtrValue.ptr1;
elementStr = ecrPtr->fullSubcmdName;
elemLen = strlen(elementStr);
@@ -1006,14 +1007,14 @@ Tcl_WrongNumArgs(
* the correct error message even if the subcommand was abbreviated.
* Otherwise, just use the string rep.
*/
const Tcl_ObjIntRep *irPtr;
if (objv[i]->typePtr == &indexType) {
register IndexRep *indexRep = objv[i]->internalRep.twoPtrValue.ptr1;
if ((irPtr = Tcl_FetchIntRep(objv[i], &indexType))) {
register IndexRep *indexRep = irPtr->twoPtrValue.ptr1;
Tcl_AppendStringsToObj(objPtr, EXPAND_OF(indexRep), NULL);
} else if (objv[i]->typePtr == &tclEnsembleCmdType) {
register EnsembleCmdRep *ecrPtr =
objv[i]->internalRep.twoPtrValue.ptr1;
} else if ((irPtr = Tcl_FetchIntRep(objv[i], &tclEnsembleCmdType))) {
register EnsembleCmdRep *ecrPtr = irPtr->twoPtrValue.ptr1;
Tcl_AppendStringsToObj(objPtr, ecrPtr->fullSubcmdName, NULL);
} else {
+8 -1
View File
@@ -2313,6 +2313,13 @@ typedef struct Interp {
#define TCL_ALIGN(x) (((int)(x) + 7) & ~7)
/*
* A common panic alert when memory allocation fails.
*/
#define TclOOM(ptr, size) \
((size) && ((ptr)||(Tcl_Panic("unable to alloc %u bytes", (size)),1)))
/*
* The following enum values are used to specify the runtime platform setting
* of the tclPlatform variable.
@@ -4206,7 +4213,7 @@ MODULE_SCOPE void TclDbInitNewObj(Tcl_Obj *objPtr, const char *file,
(objPtr)->length = 0; \
} else { \
(objPtr)->bytes = (char *) ckalloc((unsigned) ((len) + 1)); \
memcpy((objPtr)->bytes, (bytePtr), (unsigned) (len)); \
memcpy((objPtr)->bytes, (bytePtr) ? (bytePtr) : tclEmptyStringRep, (unsigned) (len)); \
(objPtr)->bytes[len] = '\0'; \
(objPtr)->length = (len); \
}
+1 -3
View File
@@ -1540,9 +1540,7 @@ TclOOGetMethodBody(
if (mPtr->typePtr == &procMethodType) {
ProcedureMethod *pmPtr = mPtr->clientData;
if (pmPtr->procPtr->bodyPtr->bytes == NULL) {
(void) Tcl_GetString(pmPtr->procPtr->bodyPtr);
}
(void) TclGetString(pmPtr->procPtr->bodyPtr);
return pmPtr->procPtr->bodyPtr;
}
return NULL;
+217 -33
View File
@@ -17,6 +17,7 @@
#include "tclInt.h"
#include "tommath.h"
#include <math.h>
#include <assert.h>
/*
* Table of all object types.
@@ -1061,9 +1062,8 @@ TclDbInitNewObj(
* debugging. */
{
objPtr->refCount = 0;
objPtr->bytes = tclEmptyStringRep;
objPtr->length = 0;
objPtr->typePtr = NULL;
TclInitStringRep(objPtr, NULL, 0);
#ifdef TCL_THREADS
/*
@@ -1697,6 +1697,92 @@ Tcl_GetStringFromObj(
return objPtr->bytes;
}
/*
*----------------------------------------------------------------------
*
* Tcl_InitStringRep --
*
* This function is called in several configurations to provide all
* the tools needed to set an object's string representation. The
* function is determined by the arguments.
*
* (objPtr->bytes != NULL && bytes != NULL) || (numBytes < 0)
* Invalid call -- panic!
*
* objPtr->bytes == NULL && bytes == NULL && numBytes >= 0
* Allocation only - allocate space for (numBytes+1) chars.
* store in objPtr->bytes and return. Also sets
* objPtr->length to 0 and objPtr->bytes[0] to NUL.
*
* objPtr->bytes == NULL && bytes != NULL && numBytes >= 0
* Allocate and copy. bytes is assumed to point to chars to
* copy into the string rep. objPtr->length = numBytes. Allocate
* array of (numBytes + 1) chars. store in objPtr->bytes. Copy
* numBytes chars from bytes to objPtr->bytes; Set
* objPtr->bytes[numBytes] to NUL and return objPtr->bytes.
* Caller must guarantee there are numBytes chars at bytes to
* be copied.
*
* objPtr->bytes != NULL && bytes == NULL && numBytes >= 0
* Truncate. Set objPtr->length to numBytes and
* objPr->bytes[numBytes] to NUL. Caller has to guarantee
* that a prior allocating call allocated enough bytes for
* this to be valid. Return objPtr->bytes.
*
* Caller is expected to ascertain that the bytes copied into
* the string rep make up complete valid UTF-8 characters.
*
* Results:
* A pointer to the string rep of objPtr.
*
* Side effects:
* As described above.
*
*----------------------------------------------------------------------
*/
char *
Tcl_InitStringRep(
Tcl_Obj *objPtr, /* Object whose string rep is to be set */
const char *bytes,
unsigned int numBytes)
{
assert(objPtr->bytes == NULL || bytes == NULL);
if (numBytes > INT_MAX) {
Tcl_Panic("max size for a Tcl value (%d bytes) exceeded", INT_MAX);
}
/* Allocate */
if (objPtr->bytes == NULL) {
/* Allocate only as empty - extend later if bytes copied */
objPtr->length = 0;
if (numBytes) {
objPtr->bytes = attemptckalloc(numBytes + 1);
if (objPtr->bytes == NULL) {
return NULL;
}
if (bytes) {
/* Copy */
memcpy(objPtr->bytes, bytes, numBytes);
objPtr->length = (int) numBytes;
}
} else {
objPtr->bytes = tclEmptyStringRep;
return NULL;
}
} else {
/* objPtr->bytes != NULL bytes == NULL - Truncate */
objPtr->bytes = ckrealloc(objPtr->bytes, numBytes + 1);
objPtr->length = (int)numBytes;
}
/* Terminate */
objPtr->bytes[objPtr->length] = '\0';
return objPtr->bytes;
}
/*
*----------------------------------------------------------------------
*
@@ -1723,6 +1809,104 @@ Tcl_InvalidateStringRep(
TclInvalidateStringRep(objPtr);
}
/*
*----------------------------------------------------------------------
*
* Tcl_StoreIntRep --
*
* This function is called to set the object's internal
* representation to match a particular type.
*
* It is the caller's responsibility to guarantee that
* the value of the submitted IntRep is in agreement with
* the value of any existing string rep.
*
* Results:
* None.
*
* Side effects:
* Calls the freeIntRepProc of the current Tcl_ObjType, if any.
* Sets the internalRep and typePtr fields to the submitted values.
*
*----------------------------------------------------------------------
*/
void
Tcl_StoreIntRep(
Tcl_Obj *objPtr, /* Object whose internal rep should be set. */
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);
/* When irPtr == NULL, just leave objPtr with no IntRep for typePtr */
if (irPtr) {
/* Copy the new IntRep into place */
objPtr->internalRep = *irPtr;
/* Set the type to match */
objPtr->typePtr = typePtr;
}
}
/*
*----------------------------------------------------------------------
*
* Tcl_FetchIntRep --
*
* This function is called to retrieve the object's internal
* representation matching a requested type, if any.
*
* Results:
* A read-only pointer to the associated Tcl_ObjIntRep, or
* 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.
*
*----------------------------------------------------------------------
*/
const Tcl_ObjIntRep *
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;
}
/* Type match! objPtr IntRep is the one sought. */
return &(objPtr->internalRep);
}
/*
*----------------------------------------------------------------------
*
* Tcl_FreeIntRep --
*
* This function is called to free an object's internal representation.
*
* Results:
* None.
*
* Side effects:
* Calls the freeIntRepProc of the current Tcl_ObjType, if any.
* Sets typePtr field to NULL.
*
*----------------------------------------------------------------------
*/
void
Tcl_FreeIntRep(
Tcl_Obj *objPtr) /* Object whose internal rep should be freed. */
{
TclFreeIntRep(objPtr);
}
/*
*----------------------------------------------------------------------
*
@@ -1809,6 +1993,7 @@ Tcl_DbNewBooleanObj(
register Tcl_Obj *objPtr;
TclDbNewObj(objPtr, file, line);
/* Optimized TclInvalidateStringRep() */
objPtr->bytes = NULL;
objPtr->internalRep.longValue = (boolValue? 1 : 0);
@@ -2201,6 +2386,7 @@ Tcl_DbNewDoubleObj(
register Tcl_Obj *objPtr;
TclDbNewObj(objPtr, file, line);
/* Optimized TclInvalidateStringRep() */
objPtr->bytes = NULL;
objPtr->internalRep.doubleValue = dblValue;
@@ -2367,15 +2553,12 @@ static void
UpdateStringOfDouble(
register Tcl_Obj *objPtr) /* Double obj with string rep to update. */
{
char buffer[TCL_DOUBLE_SPACE];
register int len;
char *dst = Tcl_InitStringRep(objPtr, NULL, TCL_DOUBLE_SPACE);
Tcl_PrintDouble(NULL, objPtr->internalRep.doubleValue, buffer);
len = strlen(buffer);
TclOOM(dst, TCL_DOUBLE_SPACE + 1);
objPtr->bytes = ckalloc(len + 1);
memcpy(objPtr->bytes, buffer, (unsigned) len + 1);
objPtr->length = len;
Tcl_PrintDouble(NULL, objPtr->internalRep.doubleValue, dst);
(void) Tcl_InitStringRep(objPtr, NULL, strlen(dst));
}
/*
@@ -2565,14 +2748,11 @@ static void
UpdateStringOfInt(
register Tcl_Obj *objPtr) /* Int object whose string rep to update. */
{
char buffer[TCL_INTEGER_SPACE];
register int len;
char *dst = Tcl_InitStringRep( objPtr, NULL, TCL_INTEGER_SPACE);
len = TclFormatInt(buffer, objPtr->internalRep.longValue);
objPtr->bytes = ckalloc(len + 1);
memcpy(objPtr->bytes, buffer, (unsigned) len + 1);
objPtr->length = len;
TclOOM(dst, TCL_INTEGER_SPACE + 1);
(void) Tcl_InitStringRep(objPtr, NULL,
TclFormatInt(dst, objPtr->internalRep.longValue));
}
/*
@@ -2676,6 +2856,7 @@ Tcl_DbNewLongObj(
register Tcl_Obj *objPtr;
TclDbNewObj(objPtr, file, line);
/* Optimized TclInvalidateStringRep */
objPtr->bytes = NULL;
objPtr->internalRep.longValue = longValue;
@@ -2860,9 +3041,9 @@ static void
UpdateStringOfWideInt(
register Tcl_Obj *objPtr) /* Int object whose string rep to update. */
{
char buffer[TCL_INTEGER_SPACE+2];
register unsigned len;
register Tcl_WideInt wideVal = objPtr->internalRep.wideValue;
char *dst = Tcl_InitStringRep(objPtr, NULL, TCL_INTEGER_SPACE + 2);
TclOOM(dst, TCL_INTEGER_SPACE + 3);
/*
* Note that sprintf will generate a compiler warning under Mingw claiming
@@ -2871,11 +3052,9 @@ UpdateStringOfWideInt(
* value.
*/
sprintf(buffer, "%" TCL_LL_MODIFIER "d", wideVal);
len = strlen(buffer);
objPtr->bytes = ckalloc(len + 1);
memcpy(objPtr->bytes, buffer, len + 1);
objPtr->length = len;
sprintf(dst, "%" TCL_LL_MODIFIER "d", objPtr->internalRep.wideValue);
(void) Tcl_InitStringRep(objPtr, NULL, strlen(dst));
}
#endif /* !TCL_WIDE_INT_IS_LONG */
@@ -3245,12 +3424,10 @@ UpdateStringOfBignum(
{
mp_int bignumVal;
int size;
int status;
char *stringVal;
UNPACK_BIGNUM(objPtr, bignumVal);
status = mp_radix_size(&bignumVal, 10, &size);
if (status != MP_OKAY) {
if (MP_OKAY != mp_radix_size(&bignumVal, 10, &size)) {
Tcl_Panic("radix size failure in UpdateStringOfBignum");
}
if (size == 3) {
@@ -3267,13 +3444,14 @@ UpdateStringOfBignum(
Tcl_Panic("UpdateStringOfBignum: string length limit exceeded");
}
stringVal = ckalloc(size);
status = mp_toradix_n(&bignumVal, stringVal, 10, size);
if (status != MP_OKAY) {
stringVal = Tcl_InitStringRep(objPtr, NULL, size - 1);
TclOOM(stringVal, size);
if (MP_OKAY != mp_toradix_n(&bignumVal, stringVal, 10, size)) {
Tcl_Panic("conversion failure in UpdateStringOfBignum");
}
objPtr->bytes = stringVal;
objPtr->length = size - 1; /* size includes a trailing NUL byte. */
(void) Tcl_InitStringRep(objPtr, NULL, size - 1);
}
/*
@@ -3393,11 +3571,17 @@ GetBignumFromObj(
mp_init_copy(bignumValue, &temp);
} else {
UNPACK_BIGNUM(objPtr, *bignumValue);
/* Optimized TclFreeIntRep */
objPtr->internalRep.twoPtrValue.ptr1 = NULL;
objPtr->internalRep.twoPtrValue.ptr2 = NULL;
objPtr->typePtr = NULL;
/*
* TODO: If objPtr has a string rep, this leaves
* it undisturbed. Not clear that's proper. Pure
* bignum values are converted to empty string.
*/
if (objPtr->bytes == NULL) {
TclInitStringRep(objPtr, tclEmptyStringRep, 0);
TclInitStringRep(objPtr, NULL, 0);
}
}
return TCL_OK;
+1 -1
View File
@@ -2949,7 +2949,7 @@ UpdateStringOfString(
String *stringPtr = GET_STRING(objPtr);
if (stringPtr->numChars == 0) {
TclInitStringRep(objPtr, tclEmptyStringRep, 0);
TclInitStringRep(objPtr, NULL, 0);
} else {
(void) ExtendStringRepWithUnicode(objPtr, stringPtr->unicode,
stringPtr->numChars);
+4
View File
@@ -1415,6 +1415,10 @@ const TclStubs tclStubs = {
Tcl_FindSymbol, /* 628 */
Tcl_FSUnloadFile, /* 629 */
Tcl_ZlibStreamSetCompressionDictionary, /* 630 */
Tcl_FreeIntRep, /* 631 */
Tcl_InitStringRep, /* 632 */
Tcl_FetchIntRep, /* 633 */
Tcl_StoreIntRep, /* 634 */
};
/* !END!: Do not edit above this line. */
+2 -8
View File
@@ -7012,17 +7012,11 @@ TestconcatobjCmd(
list1Ptr = Tcl_NewStringObj("foo bar sum", -1);
Tcl_ListObjLength(NULL, list1Ptr, &len);
if (list1Ptr->bytes != NULL) {
ckfree(list1Ptr->bytes);
list1Ptr->bytes = NULL;
}
Tcl_InvalidateStringRep(list1Ptr);
list2Ptr = Tcl_NewStringObj("eeny meeny", -1);
Tcl_ListObjLength(NULL, list2Ptr, &len);
if (list2Ptr->bytes != NULL) {
ckfree(list2Ptr->bytes);
list2Ptr->bytes = NULL;
}
Tcl_InvalidateStringRep(list2Ptr);
/*
* Verify that concat'ing a list obj with one or more empty strings does
+9 -8
View File
@@ -3653,17 +3653,18 @@ static void
UpdateStringOfEndOffset(
register Tcl_Obj *objPtr)
{
char buffer[TCL_INTEGER_SPACE + 5];
register int len = 3;
char *dst = Tcl_InitStringRep(objPtr, NULL, TCL_INTEGER_SPACE + 5);
int len = 3;
memcpy(buffer, "end", 4);
TclOOM(dst, TCL_INTEGER_SPACE + 6);
memcpy(dst, "end", len);
if (objPtr->internalRep.longValue != 0) {
buffer[len++] = '-';
len += TclFormatInt(buffer+len, -(objPtr->internalRep.longValue));
dst[len++] = '-';
len += TclFormatInt(dst+len, -(objPtr->internalRep.longValue));
}
objPtr->bytes = ckalloc((unsigned) len+1);
memcpy(objPtr->bytes, buffer, (unsigned) len+1);
objPtr->length = len;
(void) Tcl_InitStringRep(objPtr, NULL, len);
}
/*
+19 -15
View File
@@ -692,24 +692,28 @@ UpdateStringOfOSType(
register Tcl_Obj *objPtr) /* OSType object whose string rep to
* update. */
{
char string[5];
const int size = TCL_UTF_MAX * 4;
char *dst = Tcl_InitStringRep(objPtr, NULL, size);
OSType osType = (OSType) objPtr->internalRep.longValue;
Tcl_DString ds;
Tcl_Encoding encoding = Tcl_GetEncoding(NULL, "macRoman");
unsigned len;
int written = 0;
Tcl_Encoding encoding;
char src[5];
string[0] = (char) (osType >> 24);
string[1] = (char) (osType >> 16);
string[2] = (char) (osType >> 8);
string[3] = (char) (osType);
string[4] = '\0';
Tcl_ExternalToUtfDString(encoding, string, -1, &ds);
len = (unsigned) Tcl_DStringLength(&ds) + 1;
objPtr->bytes = ckalloc(len);
memcpy(objPtr->bytes, Tcl_DStringValue(&ds), len);
objPtr->length = Tcl_DStringLength(&ds);
Tcl_DStringFree(&ds);
TclOOM(dst, size);
src[0] = (char) (osType >> 24);
src[1] = (char) (osType >> 16);
src[2] = (char) (osType >> 8);
src[3] = (char) (osType);
src[4] = '\0';
encoding = Tcl_GetEncoding(NULL, "macRoman");
Tcl_ExternalToUtf(NULL, encoding, src, -1, /* flags */ 0,
/* statePtr */ NULL, dst, size, /* srcReadPtr */ NULL,
/* dstWrotePtr */ &written, /* dstCharsPtr */ NULL);
Tcl_FreeEncoding(encoding);
(void)Tcl_InitStringRep(objPtr, NULL, written);
}
/*