Compare commits
46
Commits
tip-503
...
tip-445-fork
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
99b30a2b32 | ||
|
|
cf086db3f2 | ||
|
|
90bb5bf23c | ||
|
|
cbfce81f38 | ||
|
|
68e9e6b533 | ||
|
|
6661778d6e | ||
|
|
aec00dd13c | ||
|
|
e51db8046c | ||
|
|
f28ed288b8 | ||
|
|
1dc5de0179 | ||
|
|
0a4081dc57 | ||
|
|
7721fe8b51 | ||
|
|
f324e94785 | ||
|
|
30d0cf44cb | ||
|
|
4a7725e917 | ||
|
|
dcb52d2ea8 | ||
|
|
e29e96a9e1 | ||
|
|
25fa1a3a8c | ||
|
|
6fd2ed3f11 | ||
|
|
0276b6e644 | ||
|
|
3bd8840931 | ||
|
|
36cf99464d | ||
|
|
f19cbcbff5 | ||
|
|
c7039276a0 | ||
|
|
1f136d8cb6 | ||
|
|
a5e1e1f33e | ||
|
|
1bebb796bb | ||
|
|
a19375e928 | ||
|
|
413706af15 | ||
|
|
8370f3e275 | ||
|
|
959413c95a | ||
|
|
325b2f4ade | ||
|
|
83ac8470a0 | ||
|
|
f6b543ae94 | ||
|
|
e9a10d7cda | ||
|
|
dc0adeafb4 | ||
|
|
80bc5b30c2 | ||
|
|
0412f3af19 | ||
|
|
c79a28077f | ||
|
|
6bd1189ac2 | ||
|
|
422d353b0a | ||
|
|
847f2ba0d5 | ||
|
|
cae0944eda | ||
|
|
37f5c2af03 | ||
|
|
95de12dbb4 | ||
|
|
de712c24fb |
@@ -2326,6 +2326,24 @@ 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 {
|
||||
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
@@ -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;
|
||||
|
||||
/*
|
||||
|
||||
+54
-25
@@ -3513,9 +3513,14 @@ OldMathFuncProc(
|
||||
valuePtr = objv[j];
|
||||
result = Tcl_GetDoubleFromObj(NULL, valuePtr, &d);
|
||||
#ifdef ACCEPT_NAN
|
||||
if ((result != TCL_OK) && (valuePtr->typePtr == &tclDoubleType)) {
|
||||
d = valuePtr->internalRep.doubleValue;
|
||||
result = TCL_OK;
|
||||
if (result != TCL_OK) {
|
||||
const Tcl_ObjIntRep *irPtr
|
||||
= Tcl_FetchIntRep(valuePtr, &tclDoubleType);
|
||||
|
||||
if (irPtr) {
|
||||
d = irPtr->doubleValue;
|
||||
result = TCL_OK;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (result != TCL_OK) {
|
||||
@@ -7061,9 +7066,13 @@ ExprCeilFunc(
|
||||
}
|
||||
code = Tcl_GetDoubleFromObj(interp, objv[1], &d);
|
||||
#ifdef ACCEPT_NAN
|
||||
if ((code != TCL_OK) && (objv[1]->typePtr == &tclDoubleType)) {
|
||||
Tcl_SetObjResult(interp, objv[1]);
|
||||
return TCL_OK;
|
||||
if (code != TCL_OK) {
|
||||
const Tcl_ObjIntRep *irPtr = Tcl_FetchIntRep(objv[1], &tclDoubleType);
|
||||
|
||||
if (irPtr) {
|
||||
Tcl_SetObjResult(interp, objv[1]);
|
||||
return TCL_OK;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (code != TCL_OK) {
|
||||
@@ -7097,9 +7106,13 @@ ExprFloorFunc(
|
||||
}
|
||||
code = Tcl_GetDoubleFromObj(interp, objv[1], &d);
|
||||
#ifdef ACCEPT_NAN
|
||||
if ((code != TCL_OK) && (objv[1]->typePtr == &tclDoubleType)) {
|
||||
Tcl_SetObjResult(interp, objv[1]);
|
||||
return TCL_OK;
|
||||
if (code != TCL_OK) {
|
||||
const Tcl_ObjIntRep *irPtr = Tcl_FetchIntRep(objv[1], &tclDoubleType);
|
||||
|
||||
if (irPtr) {
|
||||
Tcl_SetObjResult(interp, objv[1]);
|
||||
return TCL_OK;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (code != TCL_OK) {
|
||||
@@ -7233,9 +7246,13 @@ ExprSqrtFunc(
|
||||
}
|
||||
code = Tcl_GetDoubleFromObj(interp, objv[1], &d);
|
||||
#ifdef ACCEPT_NAN
|
||||
if ((code != TCL_OK) && (objv[1]->typePtr == &tclDoubleType)) {
|
||||
Tcl_SetObjResult(interp, objv[1]);
|
||||
return TCL_OK;
|
||||
if (code != TCL_OK) {
|
||||
const Tcl_ObjIntRep *irPtr = Tcl_FetchIntRep(objv[1], &tclDoubleType);
|
||||
|
||||
if (irPtr) {
|
||||
Tcl_SetObjResult(interp, objv[1]);
|
||||
return TCL_OK;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (code != TCL_OK) {
|
||||
@@ -7276,10 +7293,14 @@ ExprUnaryFunc(
|
||||
}
|
||||
code = Tcl_GetDoubleFromObj(interp, objv[1], &d);
|
||||
#ifdef ACCEPT_NAN
|
||||
if ((code != TCL_OK) && (objv[1]->typePtr == &tclDoubleType)) {
|
||||
d = objv[1]->internalRep.doubleValue;
|
||||
Tcl_ResetResult(interp);
|
||||
code = TCL_OK;
|
||||
if (code != TCL_OK) {
|
||||
const Tcl_ObjIntRep *irPtr = Tcl_FetchIntRep(objv[1], &tclDoubleType);
|
||||
|
||||
if (irPtr) {
|
||||
d = irPtr->doubleValue;
|
||||
Tcl_ResetResult(interp);
|
||||
code = TCL_OK;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (code != TCL_OK) {
|
||||
@@ -7336,10 +7357,14 @@ ExprBinaryFunc(
|
||||
}
|
||||
code = Tcl_GetDoubleFromObj(interp, objv[1], &d1);
|
||||
#ifdef ACCEPT_NAN
|
||||
if ((code != TCL_OK) && (objv[1]->typePtr == &tclDoubleType)) {
|
||||
d1 = objv[1]->internalRep.doubleValue;
|
||||
Tcl_ResetResult(interp);
|
||||
code = TCL_OK;
|
||||
if (code != TCL_OK) {
|
||||
const Tcl_ObjIntRep *irPtr = Tcl_FetchIntRep(objv[1], &tclDoubleType);
|
||||
|
||||
if (irPtr) {
|
||||
d1 = irPtr->doubleValue;
|
||||
Tcl_ResetResult(interp);
|
||||
code = TCL_OK;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (code != TCL_OK) {
|
||||
@@ -7347,10 +7372,14 @@ ExprBinaryFunc(
|
||||
}
|
||||
code = Tcl_GetDoubleFromObj(interp, objv[2], &d2);
|
||||
#ifdef ACCEPT_NAN
|
||||
if ((code != TCL_OK) && (objv[2]->typePtr == &tclDoubleType)) {
|
||||
d2 = objv[2]->internalRep.doubleValue;
|
||||
Tcl_ResetResult(interp);
|
||||
code = TCL_OK;
|
||||
if (code != TCL_OK) {
|
||||
const Tcl_ObjIntRep *irPtr = Tcl_FetchIntRep(objv[1], &tclDoubleType);
|
||||
|
||||
if (irPtr) {
|
||||
d2 = irPtr->doubleValue;
|
||||
Tcl_ResetResult(interp);
|
||||
code = TCL_OK;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (code != TCL_OK) {
|
||||
@@ -7506,7 +7535,7 @@ ExprDoubleFunc(
|
||||
}
|
||||
if (Tcl_GetDoubleFromObj(interp, objv[1], &dResult) != TCL_OK) {
|
||||
#ifdef ACCEPT_NAN
|
||||
if (objv[1]->typePtr == &tclDoubleType) {
|
||||
if (Tcl_FetchIntRep(objv[1], &tclDoubleType)) {
|
||||
Tcl_SetObjResult(interp, objv[1]);
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
+86
-79
@@ -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,29 @@ Tcl_SetByteArrayLength(
|
||||
int length) /* New length for internal byte array. */
|
||||
{
|
||||
ByteArray *byteArrayPtr;
|
||||
unsigned newLength;
|
||||
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) {
|
||||
byteArrayPtr = ckrealloc(byteArrayPtr, BYTEARRAY_SIZE(newLength));
|
||||
byteArrayPtr->allocated = newLength;
|
||||
SET_BYTEARRAY(irPtr, byteArrayPtr);
|
||||
}
|
||||
TclInvalidateStringRep(objPtr);
|
||||
byteArrayPtr->used = length;
|
||||
byteArrayPtr->used = newLength;
|
||||
return byteArrayPtr->bytes;
|
||||
}
|
||||
|
||||
@@ -454,25 +464,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 +508,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 +533,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 +554,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 +563,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 +571,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 +629,8 @@ TclAppendBytesToByteArray(
|
||||
int len)
|
||||
{
|
||||
ByteArray *byteArrayPtr;
|
||||
int needed;
|
||||
unsigned int length, needed;
|
||||
Tcl_ObjIntRep *irPtr;
|
||||
|
||||
if (Tcl_IsShared(objPtr)) {
|
||||
Tcl_Panic("%s called with shared object","TclAppendBytesToByteArray");
|
||||
@@ -642,23 +643,27 @@ 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;
|
||||
|
||||
if (needed <= INT_MAX/2) {
|
||||
/* Try to allocate double the total space that is needed. */
|
||||
@@ -668,7 +673,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 +686,13 @@ TclAppendBytesToByteArray(
|
||||
}
|
||||
byteArrayPtr = ptr;
|
||||
byteArrayPtr->allocated = attempt;
|
||||
SET_BYTEARRAY(objPtr, byteArrayPtr);
|
||||
SET_BYTEARRAY(irPtr, byteArrayPtr);
|
||||
}
|
||||
|
||||
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 +1886,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 +1906,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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
+1
-1
@@ -438,7 +438,7 @@ ClockGetdatefieldsObjCmd(
|
||||
* that it isn't.
|
||||
*/
|
||||
|
||||
if (objv[1]->typePtr == &tclBignumType) {
|
||||
if (Tcl_FetchIntRep(objv[1], &tclBignumType)) {
|
||||
Tcl_SetObjResult(interp, literals[LIT_INTEGER_VALUE_TOO_LARGE]);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
+4
-14
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
+17
-28
@@ -1567,12 +1567,12 @@ StringIsCmd(
|
||||
break;
|
||||
case STR_IS_DOUBLE: {
|
||||
/* TODO */
|
||||
if ((objPtr->typePtr == &tclDoubleType) ||
|
||||
(objPtr->typePtr == &tclIntType) ||
|
||||
if (Tcl_FetchIntRep(objPtr, &tclDoubleType) ||
|
||||
Tcl_FetchIntRep(objPtr, &tclIntType) ||
|
||||
#ifndef TCL_WIDE_INT_IS_LONG
|
||||
(objPtr->typePtr == &tclWideIntType) ||
|
||||
Tcl_FetchIntRep(objPtr, &tclWideIntType) ||
|
||||
#endif
|
||||
(objPtr->typePtr == &tclBignumType)) {
|
||||
Tcl_FetchIntRep(objPtr, &tclBignumType)) {
|
||||
break;
|
||||
}
|
||||
string1 = TclGetStringFromObj(objPtr, &length1);
|
||||
@@ -1605,11 +1605,11 @@ StringIsCmd(
|
||||
}
|
||||
goto failedIntParse;
|
||||
case STR_IS_ENTIER:
|
||||
if ((objPtr->typePtr == &tclIntType) ||
|
||||
if (Tcl_FetchIntRep(objPtr, &tclIntType) ||
|
||||
#ifndef TCL_WIDE_INT_IS_LONG
|
||||
(objPtr->typePtr == &tclWideIntType) ||
|
||||
Tcl_FetchIntRep(objPtr, &tclWideIntType) ||
|
||||
#endif
|
||||
(objPtr->typePtr == &tclBignumType)) {
|
||||
Tcl_FetchIntRep(objPtr, &tclBignumType)) {
|
||||
break;
|
||||
}
|
||||
string1 = TclGetStringFromObj(objPtr, &length1);
|
||||
@@ -1880,7 +1880,7 @@ StringMapCmd(
|
||||
* inconsistencies (see test string-10.20 for illustration why!)
|
||||
*/
|
||||
|
||||
if (objv[objc-2]->typePtr == &tclDictType && objv[objc-2]->bytes == NULL){
|
||||
if (Tcl_FetchIntRep(objv[objc-2], &tclDictType) && objv[objc-2]->bytes == NULL){
|
||||
int i, done;
|
||||
Tcl_DictSearch search;
|
||||
|
||||
@@ -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:
|
||||
@@ -2632,8 +2621,8 @@ StringEqualCmd(
|
||||
string1 = (char *) Tcl_GetByteArrayFromObj(objv[0], &length1);
|
||||
string2 = (char *) Tcl_GetByteArrayFromObj(objv[1], &length2);
|
||||
strCmpFn = (strCmpFn_t) memcmp;
|
||||
} else if ((objv[0]->typePtr == &tclStringType)
|
||||
&& (objv[1]->typePtr == &tclStringType)) {
|
||||
} else if (Tcl_FetchIntRep(objv[0], &tclStringType)
|
||||
&& Tcl_FetchIntRep(objv[1], &tclStringType)) {
|
||||
/*
|
||||
* Do a unicode-specific comparison if both of the args are of String
|
||||
* type. In benchmark testing this proved the most efficient check
|
||||
@@ -2782,8 +2771,8 @@ StringCmpCmd(
|
||||
string1 = (char *) Tcl_GetByteArrayFromObj(objv[0], &length1);
|
||||
string2 = (char *) Tcl_GetByteArrayFromObj(objv[1], &length2);
|
||||
strCmpFn = (strCmpFn_t) memcmp;
|
||||
} else if ((objv[0]->typePtr == &tclStringType)
|
||||
&& (objv[1]->typePtr == &tclStringType)) {
|
||||
} else if (Tcl_FetchIntRep(objv[0], &tclStringType)
|
||||
&& Tcl_FetchIntRep(objv[1], &tclStringType)) {
|
||||
/*
|
||||
* Do a unicode-specific comparison if both of the args are of String
|
||||
* type. In benchmark testing this proved the most efficient check
|
||||
|
||||
@@ -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 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 */
|
||||
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) */
|
||||
|
||||
|
||||
+118
-97
@@ -12,6 +12,7 @@
|
||||
|
||||
#include "tclInt.h"
|
||||
#include "tommath.h"
|
||||
#include <assert.h>
|
||||
|
||||
/*
|
||||
* Forward declaration.
|
||||
@@ -154,13 +155,6 @@ typedef struct Dict {
|
||||
* dictionaries. */
|
||||
} Dict;
|
||||
|
||||
/*
|
||||
* Accessor macro for converting between a Tcl_Obj* and a Dict. Note that this
|
||||
* must be assignable as well as readable.
|
||||
*/
|
||||
|
||||
#define DICT(dictObj) (*((Dict **)&(dictObj)->internalRep.twoPtrValue.ptr1))
|
||||
|
||||
/*
|
||||
* The structure below defines the dictionary object type by means of
|
||||
* functions that can be invoked by generic object code.
|
||||
@@ -174,6 +168,21 @@ const Tcl_ObjType tclDictType = {
|
||||
SetDictFromAny /* setFromAnyProc */
|
||||
};
|
||||
|
||||
#define DictSetIntRep(objPtr, dictRepPtr) \
|
||||
do { \
|
||||
Tcl_ObjIntRep ir; \
|
||||
ir.twoPtrValue.ptr1 = (dictRepPtr); \
|
||||
ir.twoPtrValue.ptr2 = NULL; \
|
||||
Tcl_StoreIntRep((objPtr), &tclDictType, &ir); \
|
||||
} while (0)
|
||||
|
||||
#define DictGetIntRep(objPtr, dictRepPtr) \
|
||||
do { \
|
||||
const Tcl_ObjIntRep *irPtr; \
|
||||
irPtr = Tcl_FetchIntRep((objPtr), &tclDictType); \
|
||||
(dictRepPtr) = irPtr ? irPtr->twoPtrValue.ptr1 : NULL; \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* The type of the specially adapted version of the Tcl_Obj*-containing hash
|
||||
* table defined in the tclObj.c code. This version differs in that it
|
||||
@@ -369,10 +378,11 @@ DupDictInternalRep(
|
||||
Tcl_Obj *srcPtr,
|
||||
Tcl_Obj *copyPtr)
|
||||
{
|
||||
Dict *oldDict = DICT(srcPtr);
|
||||
Dict *newDict = ckalloc(sizeof(Dict));
|
||||
Dict *oldDict, *newDict = ckalloc(sizeof(Dict));
|
||||
ChainEntry *cPtr;
|
||||
|
||||
DictGetIntRep(srcPtr, oldDict);
|
||||
|
||||
/*
|
||||
* Copy values across from the old hash table.
|
||||
*/
|
||||
@@ -404,9 +414,7 @@ DupDictInternalRep(
|
||||
* Store in the object.
|
||||
*/
|
||||
|
||||
DICT(copyPtr) = newDict;
|
||||
copyPtr->internalRep.twoPtrValue.ptr2 = NULL;
|
||||
copyPtr->typePtr = &tclDictType;
|
||||
DictSetIntRep(copyPtr, newDict);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -431,13 +439,14 @@ static void
|
||||
FreeDictInternalRep(
|
||||
Tcl_Obj *dictPtr)
|
||||
{
|
||||
Dict *dict = DICT(dictPtr);
|
||||
Dict *dict;
|
||||
|
||||
DictGetIntRep(dictPtr, dict);
|
||||
|
||||
dict->refcount--;
|
||||
if (dict->refcount <= 0) {
|
||||
DeleteDict(dict);
|
||||
}
|
||||
dictPtr->typePtr = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -496,7 +505,7 @@ UpdateStringOfDict(
|
||||
{
|
||||
#define LOCAL_SIZE 20
|
||||
int localFlags[LOCAL_SIZE], *flagPtr = NULL;
|
||||
Dict *dict = DICT(dictPtr);
|
||||
Dict *dict;
|
||||
ChainEntry *cPtr;
|
||||
Tcl_Obj *keyPtr, *valuePtr;
|
||||
int i, length, bytesNeeded = 0;
|
||||
@@ -509,12 +518,17 @@ UpdateStringOfDict(
|
||||
* is not exposed by any API function...
|
||||
*/
|
||||
|
||||
int numElems = dict->table.numEntries * 2;
|
||||
int numElems;
|
||||
|
||||
DictGetIntRep(dictPtr, dict);
|
||||
|
||||
assert (dict != NULL);
|
||||
|
||||
numElems = dict->table.numEntries * 2;
|
||||
|
||||
/* 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 +574,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 +589,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);
|
||||
@@ -620,7 +633,7 @@ SetDictFromAny(
|
||||
* the conversion from lists to dictionaries.
|
||||
*/
|
||||
|
||||
if (objPtr->typePtr == &tclListType) {
|
||||
if (Tcl_FetchIntRep(objPtr, &tclListType)) {
|
||||
int objc, i;
|
||||
Tcl_Obj **objv;
|
||||
|
||||
@@ -675,10 +688,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 +708,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. */
|
||||
@@ -716,13 +737,10 @@ SetDictFromAny(
|
||||
* Tcl_GetStringFromObj, to use that old internalRep.
|
||||
*/
|
||||
|
||||
TclFreeIntRep(objPtr);
|
||||
dict->epoch = 0;
|
||||
dict->chain = NULL;
|
||||
dict->refcount = 1;
|
||||
DICT(objPtr) = dict;
|
||||
objPtr->internalRep.twoPtrValue.ptr2 = NULL;
|
||||
objPtr->typePtr = &tclDictType;
|
||||
DictSetIntRep(objPtr, dict);
|
||||
return TCL_OK;
|
||||
|
||||
missingValue:
|
||||
@@ -736,6 +754,23 @@ SetDictFromAny(
|
||||
ckfree(dict);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
static Dict *
|
||||
GetDictFromObj(
|
||||
Tcl_Interp *interp,
|
||||
Tcl_Obj *dictPtr)
|
||||
{
|
||||
Dict *dict;
|
||||
|
||||
DictGetIntRep(dictPtr, dict);
|
||||
if (dict == NULL) {
|
||||
if (SetDictFromAny(interp, dictPtr) != TCL_OK) {
|
||||
return NULL;
|
||||
}
|
||||
DictGetIntRep(dictPtr, dict);
|
||||
}
|
||||
return dict;
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
@@ -780,11 +815,13 @@ TclTraceDictPath(
|
||||
Dict *dict, *newDict;
|
||||
int i;
|
||||
|
||||
if (dictPtr->typePtr != &tclDictType
|
||||
&& SetDictFromAny(interp, dictPtr) != TCL_OK) {
|
||||
return NULL;
|
||||
DictGetIntRep(dictPtr, dict);
|
||||
if (dict == NULL) {
|
||||
if (SetDictFromAny(interp, dictPtr) != TCL_OK) {
|
||||
return NULL;
|
||||
}
|
||||
DictGetIntRep(dictPtr, dict);
|
||||
}
|
||||
dict = DICT(dictPtr);
|
||||
if (flags & DICT_PATH_UPDATE) {
|
||||
dict->chain = NULL;
|
||||
}
|
||||
@@ -820,13 +857,17 @@ TclTraceDictPath(
|
||||
Tcl_SetHashValue(hPtr, tmpObj);
|
||||
} else {
|
||||
tmpObj = Tcl_GetHashValue(hPtr);
|
||||
if (tmpObj->typePtr != &tclDictType
|
||||
&& SetDictFromAny(interp, tmpObj) != TCL_OK) {
|
||||
return NULL;
|
||||
|
||||
DictGetIntRep(tmpObj, newDict);
|
||||
|
||||
if (newDict == NULL) {
|
||||
if (SetDictFromAny(interp, tmpObj) != TCL_OK) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
newDict = DICT(tmpObj);
|
||||
DictGetIntRep(tmpObj, newDict);
|
||||
if (flags & DICT_PATH_UPDATE) {
|
||||
if (Tcl_IsShared(tmpObj)) {
|
||||
TclDecrRefCount(tmpObj);
|
||||
@@ -834,7 +875,7 @@ TclTraceDictPath(
|
||||
Tcl_IncrRefCount(tmpObj);
|
||||
Tcl_SetHashValue(hPtr, tmpObj);
|
||||
dict->epoch++;
|
||||
newDict = DICT(tmpObj);
|
||||
DictGetIntRep(tmpObj, newDict);
|
||||
}
|
||||
|
||||
newDict->chain = dictPtr;
|
||||
@@ -869,7 +910,10 @@ static void
|
||||
InvalidateDictChain(
|
||||
Tcl_Obj *dictObj)
|
||||
{
|
||||
Dict *dict = DICT(dictObj);
|
||||
Dict *dict;
|
||||
|
||||
DictGetIntRep(dictObj, dict);
|
||||
assert( dict != NULL);
|
||||
|
||||
do {
|
||||
TclInvalidateStringRep(dictObj);
|
||||
@@ -879,7 +923,7 @@ InvalidateDictChain(
|
||||
break;
|
||||
}
|
||||
dict->chain = NULL;
|
||||
dict = DICT(dictObj);
|
||||
DictGetIntRep(dictObj, dict);
|
||||
} while (dict != NULL);
|
||||
}
|
||||
|
||||
@@ -917,15 +961,12 @@ Tcl_DictObjPut(
|
||||
Tcl_Panic("%s called with shared object", "Tcl_DictObjPut");
|
||||
}
|
||||
|
||||
if (dictPtr->typePtr != &tclDictType
|
||||
&& SetDictFromAny(interp, dictPtr) != TCL_OK) {
|
||||
dict = GetDictFromObj(interp, dictPtr);
|
||||
if (dict == NULL) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
if (dictPtr->bytes != NULL) {
|
||||
TclInvalidateStringRep(dictPtr);
|
||||
}
|
||||
dict = DICT(dictPtr);
|
||||
TclInvalidateStringRep(dictPtr);
|
||||
hPtr = CreateChainEntry(dict, keyPtr, &isNew);
|
||||
Tcl_IncrRefCount(valuePtr);
|
||||
if (!isNew) {
|
||||
@@ -968,13 +1009,12 @@ Tcl_DictObjGet(
|
||||
Dict *dict;
|
||||
Tcl_HashEntry *hPtr;
|
||||
|
||||
if (dictPtr->typePtr != &tclDictType
|
||||
&& SetDictFromAny(interp, dictPtr) != TCL_OK) {
|
||||
dict = GetDictFromObj(interp, dictPtr);
|
||||
if (dict == NULL) {
|
||||
*valuePtrPtr = NULL;
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
dict = DICT(dictPtr);
|
||||
hPtr = Tcl_FindHashEntry(&dict->table, keyPtr);
|
||||
if (hPtr == NULL) {
|
||||
*valuePtrPtr = NULL;
|
||||
@@ -1015,16 +1055,13 @@ Tcl_DictObjRemove(
|
||||
Tcl_Panic("%s called with shared object", "Tcl_DictObjRemove");
|
||||
}
|
||||
|
||||
if (dictPtr->typePtr != &tclDictType
|
||||
&& SetDictFromAny(interp, dictPtr) != TCL_OK) {
|
||||
dict = GetDictFromObj(interp, dictPtr);
|
||||
if (dict == NULL) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
dict = DICT(dictPtr);
|
||||
if (DeleteChainEntry(dict, keyPtr)) {
|
||||
if (dictPtr->bytes != NULL) {
|
||||
TclInvalidateStringRep(dictPtr);
|
||||
}
|
||||
TclInvalidateStringRep(dictPtr);
|
||||
dict->epoch++;
|
||||
}
|
||||
return TCL_OK;
|
||||
@@ -1056,12 +1093,11 @@ Tcl_DictObjSize(
|
||||
{
|
||||
Dict *dict;
|
||||
|
||||
if (dictPtr->typePtr != &tclDictType
|
||||
&& SetDictFromAny(interp, dictPtr) != TCL_OK) {
|
||||
dict = GetDictFromObj(interp, dictPtr);
|
||||
if (dict == NULL) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
dict = DICT(dictPtr);
|
||||
*sizePtr = dict->table.numEntries;
|
||||
return TCL_OK;
|
||||
}
|
||||
@@ -1108,12 +1144,11 @@ Tcl_DictObjFirst(
|
||||
Dict *dict;
|
||||
ChainEntry *cPtr;
|
||||
|
||||
if (dictPtr->typePtr != &tclDictType
|
||||
&& SetDictFromAny(interp, dictPtr) != TCL_OK) {
|
||||
dict = GetDictFromObj(interp, dictPtr);
|
||||
if (dict == NULL) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
dict = DICT(dictPtr);
|
||||
cPtr = dict->entryChainHead;
|
||||
if (cPtr == NULL) {
|
||||
searchPtr->epoch = -1;
|
||||
@@ -1288,7 +1323,8 @@ Tcl_DictObjPutKeyList(
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
dict = DICT(dictPtr);
|
||||
DictGetIntRep(dictPtr, dict);
|
||||
assert(dict != NULL);
|
||||
hPtr = CreateChainEntry(dict, keyv[keyc-1], &isNew);
|
||||
Tcl_IncrRefCount(valuePtr);
|
||||
if (!isNew) {
|
||||
@@ -1345,7 +1381,8 @@ Tcl_DictObjRemoveKeyList(
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
dict = DICT(dictPtr);
|
||||
DictGetIntRep(dictPtr, dict);
|
||||
assert(dict != NULL);
|
||||
DeleteChainEntry(dict, keyv[keyc-1]);
|
||||
InvalidateDictChain(dictPtr);
|
||||
return TCL_OK;
|
||||
@@ -1391,9 +1428,7 @@ Tcl_NewDictObj(void)
|
||||
dict->epoch = 0;
|
||||
dict->chain = NULL;
|
||||
dict->refcount = 1;
|
||||
DICT(dictPtr) = dict;
|
||||
dictPtr->internalRep.twoPtrValue.ptr2 = NULL;
|
||||
dictPtr->typePtr = &tclDictType;
|
||||
DictSetIntRep(dictPtr, dict);
|
||||
return dictPtr;
|
||||
#endif
|
||||
}
|
||||
@@ -1441,9 +1476,7 @@ Tcl_DbNewDictObj(
|
||||
dict->epoch = 0;
|
||||
dict->chain = NULL;
|
||||
dict->refcount = 1;
|
||||
DICT(dictPtr) = dict;
|
||||
dictPtr->internalRep.twoPtrValue.ptr2 = NULL;
|
||||
dictPtr->typePtr = &tclDictType;
|
||||
DictSetIntRep(dictPtr, dict);
|
||||
return dictPtr;
|
||||
#else /* !TCL_MEM_DEBUG */
|
||||
return Tcl_NewDictObj();
|
||||
@@ -1629,16 +1662,13 @@ DictReplaceCmd(
|
||||
}
|
||||
|
||||
dictPtr = objv[1];
|
||||
if (dictPtr->typePtr != &tclDictType
|
||||
&& SetDictFromAny(interp, dictPtr) != TCL_OK) {
|
||||
if (GetDictFromObj(interp, dictPtr) == NULL) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if (Tcl_IsShared(dictPtr)) {
|
||||
dictPtr = Tcl_DuplicateObj(dictPtr);
|
||||
}
|
||||
if (dictPtr->bytes != NULL) {
|
||||
TclInvalidateStringRep(dictPtr);
|
||||
}
|
||||
TclInvalidateStringRep(dictPtr);
|
||||
for (i=2 ; i<objc ; i+=2) {
|
||||
Tcl_DictObjPut(NULL, dictPtr, objv[i], objv[i+1]);
|
||||
}
|
||||
@@ -1680,16 +1710,13 @@ DictRemoveCmd(
|
||||
}
|
||||
|
||||
dictPtr = objv[1];
|
||||
if (dictPtr->typePtr != &tclDictType
|
||||
&& SetDictFromAny(interp, dictPtr) != TCL_OK) {
|
||||
if (GetDictFromObj(interp, dictPtr) == NULL) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if (Tcl_IsShared(dictPtr)) {
|
||||
dictPtr = Tcl_DuplicateObj(dictPtr);
|
||||
}
|
||||
if (dictPtr->bytes != NULL) {
|
||||
TclInvalidateStringRep(dictPtr);
|
||||
}
|
||||
TclInvalidateStringRep(dictPtr);
|
||||
for (i=2 ; i<objc ; i++) {
|
||||
Tcl_DictObjRemove(NULL, dictPtr, objv[i]);
|
||||
}
|
||||
@@ -1740,8 +1767,7 @@ DictMergeCmd(
|
||||
*/
|
||||
|
||||
targetObj = objv[1];
|
||||
if (targetObj->typePtr != &tclDictType
|
||||
&& SetDictFromAny(interp, targetObj) != TCL_OK) {
|
||||
if (GetDictFromObj(interp, targetObj) == NULL) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
@@ -1824,8 +1850,7 @@ DictKeysCmd(
|
||||
* need. [Bug 1705778, leak K04]
|
||||
*/
|
||||
|
||||
if (objv[1]->typePtr != &tclDictType
|
||||
&& SetDictFromAny(interp, objv[1]) != TCL_OK) {
|
||||
if (GetDictFromObj(interp, objv[1]) == NULL) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
@@ -2032,7 +2057,6 @@ DictInfoCmd(
|
||||
int objc,
|
||||
Tcl_Obj *const *objv)
|
||||
{
|
||||
Tcl_Obj *dictPtr;
|
||||
Dict *dict;
|
||||
char *statsStr;
|
||||
|
||||
@@ -2041,12 +2065,10 @@ DictInfoCmd(
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
dictPtr = objv[1];
|
||||
if (dictPtr->typePtr != &tclDictType
|
||||
&& SetDictFromAny(interp, dictPtr) != TCL_OK) {
|
||||
dict = GetDictFromObj(interp, objv[1]);
|
||||
if (dict == NULL) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
dict = DICT(dictPtr);
|
||||
|
||||
statsStr = Tcl_HashStats(&dict->table);
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(statsStr, -1));
|
||||
@@ -2107,12 +2129,11 @@ DictIncrCmd(
|
||||
* soon be no good.
|
||||
*/
|
||||
|
||||
char *saved = dictPtr->bytes;
|
||||
Tcl_Obj *oldPtr = dictPtr;
|
||||
|
||||
dictPtr->bytes = NULL;
|
||||
dictPtr = Tcl_DuplicateObj(dictPtr);
|
||||
oldPtr->bytes = saved;
|
||||
TclNewObj(dictPtr);
|
||||
TclInvalidateStringRep(dictPtr);
|
||||
DupDictInternalRep(oldPtr, dictPtr);
|
||||
}
|
||||
if (valuePtr == NULL) {
|
||||
/*
|
||||
@@ -2249,7 +2270,7 @@ DictLappendCmd(
|
||||
|
||||
if (allocatedValue) {
|
||||
Tcl_DictObjPut(NULL, dictPtr, objv[2], valuePtr);
|
||||
} else if (dictPtr->bytes != NULL) {
|
||||
} else {
|
||||
TclInvalidateStringRep(dictPtr);
|
||||
}
|
||||
|
||||
|
||||
+35
-25
@@ -39,7 +39,7 @@ static void UpdateStringOfInstName(Tcl_Obj *objPtr);
|
||||
* reporting of inner contexts in errorstack without string allocation.
|
||||
*/
|
||||
|
||||
static const Tcl_ObjType tclInstNameType = {
|
||||
static const Tcl_ObjType instNameType = {
|
||||
"instname", /* name */
|
||||
NULL, /* freeIntRepProc */
|
||||
NULL, /* dupIntRepProc */
|
||||
@@ -47,6 +47,21 @@ static const Tcl_ObjType tclInstNameType = {
|
||||
NULL, /* setFromAnyProc */
|
||||
};
|
||||
|
||||
#define InstNameSetIntRep(objPtr, inst) \
|
||||
do { \
|
||||
Tcl_ObjIntRep ir; \
|
||||
ir.longValue = (inst); \
|
||||
Tcl_StoreIntRep((objPtr), &instNameType, &ir); \
|
||||
} while (0)
|
||||
|
||||
#define InstNameGetIntRep(objPtr, inst) \
|
||||
do { \
|
||||
const Tcl_ObjIntRep *irPtr; \
|
||||
irPtr = Tcl_FetchIntRep((objPtr), &instNameType); \
|
||||
assert(irPtr != NULL); \
|
||||
(inst) = irPtr->longValue; \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* How to get the bytecode out of a Tcl_Obj.
|
||||
*/
|
||||
@@ -802,10 +817,11 @@ TclNewInstNameObj(
|
||||
{
|
||||
Tcl_Obj *objPtr = Tcl_NewObj();
|
||||
|
||||
objPtr->typePtr = &tclInstNameType;
|
||||
objPtr->internalRep.longValue = (long) inst;
|
||||
/* Optimized Tcl_InvalidateStringRep */
|
||||
objPtr->bytes = NULL;
|
||||
|
||||
InstNameSetIntRep(objPtr, (long) inst);
|
||||
|
||||
return objPtr;
|
||||
}
|
||||
|
||||
@@ -823,20 +839,22 @@ static void
|
||||
UpdateStringOfInstName(
|
||||
Tcl_Obj *objPtr)
|
||||
{
|
||||
int inst = objPtr->internalRep.longValue;
|
||||
char *s, buf[20];
|
||||
int len;
|
||||
int inst;
|
||||
char *dst;
|
||||
|
||||
InstNameGetIntRep(objPtr, inst);
|
||||
|
||||
if ((inst < 0) || (inst > LAST_INST_OPCODE)) {
|
||||
sprintf(buf, "inst_%d", inst);
|
||||
s = buf;
|
||||
dst = Tcl_InitStringRep(objPtr, NULL, TCL_INTEGER_SPACE + 5);
|
||||
TclOOM(dst, TCL_INTEGER_SPACE + 5);
|
||||
sprintf(dst, "inst_%d", inst);
|
||||
(void) Tcl_InitStringRep(objPtr, NULL, strlen(dst));
|
||||
} else {
|
||||
s = (char *) tclInstructionTable[objPtr->internalRep.longValue].name;
|
||||
const char *s = tclInstructionTable[inst].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;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1307,27 +1325,19 @@ Tcl_DisassembleObjCmd(
|
||||
|
||||
/*
|
||||
* Compile (if uncompiled) and disassemble a lambda term.
|
||||
*
|
||||
* WARNING! Pokes inside the lambda objtype.
|
||||
*/
|
||||
|
||||
if (objc != 3) {
|
||||
Tcl_WrongNumArgs(interp, 2, objv, "lambdaTerm");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
if (objv[2]->typePtr == &tclLambdaType) {
|
||||
procPtr = objv[2]->internalRep.twoPtrValue.ptr1;
|
||||
}
|
||||
if (procPtr == NULL || procPtr->iPtr != (Interp *) interp) {
|
||||
result = tclLambdaType.setFromAnyProc(interp, objv[2]);
|
||||
if (result != TCL_OK) {
|
||||
return result;
|
||||
}
|
||||
procPtr = objv[2]->internalRep.twoPtrValue.ptr1;
|
||||
|
||||
procPtr = TclGetLambdaFromObj(interp, objv[2], &nsObjPtr);
|
||||
if (procPtr == NULL) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
memset(&cmd, 0, sizeof(Command));
|
||||
nsObjPtr = objv[2]->internalRep.twoPtrValue.ptr2;
|
||||
result = TclGetNamespaceFromObj(interp, nsObjPtr, &nsPtr);
|
||||
if (result != TCL_OK) {
|
||||
return result;
|
||||
|
||||
@@ -2703,11 +2703,12 @@ 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);
|
||||
fprintf(stdout, "COVERED\n"); fflush(stdout);
|
||||
|
||||
TclOOM(dst, size);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -5050,7 +5050,7 @@ TEBCresume(
|
||||
*/
|
||||
|
||||
if ((TclListObjGetElements(interp, valuePtr, &objc, &objv) == TCL_OK)
|
||||
&& (value2Ptr->typePtr != &tclListType)
|
||||
&& (NULL == Tcl_FetchIntRep(value2Ptr, &tclListType))
|
||||
&& (TclGetIntForIndexM(NULL , value2Ptr, objc-1,
|
||||
&index) == TCL_OK)) {
|
||||
TclDecrRefCount(value2Ptr);
|
||||
|
||||
+35
-34
@@ -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 {
|
||||
|
||||
+14
-11
@@ -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.
|
||||
@@ -2387,12 +2394,6 @@ typedef struct List {
|
||||
#define ListRepPtr(listPtr) \
|
||||
((List *) (listPtr)->internalRep.twoPtrValue.ptr1)
|
||||
|
||||
#define ListSetIntRep(objPtr, listRepPtr) \
|
||||
(objPtr)->internalRep.twoPtrValue.ptr1 = (void *)(listRepPtr), \
|
||||
(objPtr)->internalRep.twoPtrValue.ptr2 = NULL, \
|
||||
(listRepPtr)->refCount++, \
|
||||
(objPtr)->typePtr = &tclListType
|
||||
|
||||
#define ListObjGetElements(listPtr, objc, objv) \
|
||||
((objv) = &(ListRepPtr(listPtr)->elements), \
|
||||
(objc) = ListRepPtr(listPtr)->elemCount)
|
||||
@@ -2943,6 +2944,8 @@ MODULE_SCOPE int TclGetChannelFromObj(Tcl_Interp *interp,
|
||||
int *modePtr, int flags);
|
||||
MODULE_SCOPE int TclGetCompletionCodeFromObj(Tcl_Interp *interp,
|
||||
Tcl_Obj *value, int *code);
|
||||
MODULE_SCOPE Proc * TclGetLambdaFromObj(Tcl_Interp *interp,
|
||||
Tcl_Obj *objPtr, Tcl_Obj **nsObjPtrPtr);
|
||||
MODULE_SCOPE int TclGetNumberFromObj(Tcl_Interp *interp,
|
||||
Tcl_Obj *objPtr, ClientData *clientDataPtr,
|
||||
int *typePtr);
|
||||
@@ -4208,7 +4211,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); \
|
||||
}
|
||||
@@ -4261,11 +4264,11 @@ MODULE_SCOPE void TclDbInitNewObj(Tcl_Obj *objPtr, const char *file,
|
||||
*/
|
||||
|
||||
#define TclInvalidateStringRep(objPtr) \
|
||||
if (objPtr->bytes != NULL) { \
|
||||
if (objPtr->bytes != tclEmptyStringRep) { \
|
||||
ckfree((char *) objPtr->bytes); \
|
||||
if ((objPtr)->bytes != NULL) { \
|
||||
if ((objPtr)->bytes != tclEmptyStringRep) { \
|
||||
ckfree((char *) (objPtr)->bytes); \
|
||||
} \
|
||||
objPtr->bytes = NULL; \
|
||||
(objPtr)->bytes = NULL; \
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
+3
-2
@@ -401,14 +401,15 @@ LinkTraceProc(
|
||||
if (Tcl_GetDoubleFromObj(NULL, valueObj, &linkPtr->lastValue.d)
|
||||
!= TCL_OK) {
|
||||
#ifdef ACCEPT_NAN
|
||||
if (valueObj->typePtr != &tclDoubleType) {
|
||||
Tcl_ObjIntRep *irPtr = Tcl_FetchIntRep(valueObj, &tclDoubleType);
|
||||
if (irPtr == NULL) {
|
||||
#endif
|
||||
Tcl_ObjSetVar2(interp, linkPtr->varName, NULL,
|
||||
ObjValue(linkPtr), TCL_GLOBAL_ONLY);
|
||||
return (char *) "variable must have real value";
|
||||
#ifdef ACCEPT_NAN
|
||||
}
|
||||
linkPtr->lastValue.d = valueObj->internalRep.doubleValue;
|
||||
linkPtr->lastValue.d = irPtr->doubleValue;
|
||||
#endif
|
||||
}
|
||||
LinkedVar(double) = linkPtr->lastValue.d;
|
||||
|
||||
+131
-76
@@ -12,6 +12,7 @@
|
||||
*/
|
||||
|
||||
#include "tclInt.h"
|
||||
#include <assert.h>
|
||||
|
||||
/*
|
||||
* Prototypes for functions defined later in this file:
|
||||
@@ -46,6 +47,27 @@ const Tcl_ObjType tclListType = {
|
||||
SetListFromAny /* setFromAnyProc */
|
||||
};
|
||||
|
||||
/* Macros to manipulate the List internal rep */
|
||||
|
||||
#define ListSetIntRep(objPtr, listRepPtr) \
|
||||
do { \
|
||||
Tcl_ObjIntRep ir; \
|
||||
ir.twoPtrValue.ptr1 = (listRepPtr); \
|
||||
ir.twoPtrValue.ptr2 = NULL; \
|
||||
(listRepPtr)->refCount++; \
|
||||
Tcl_StoreIntRep((objPtr), &tclListType, &ir); \
|
||||
} while (0)
|
||||
|
||||
#define ListGetIntRep(objPtr, listRepPtr) \
|
||||
do { \
|
||||
const Tcl_ObjIntRep *irPtr; \
|
||||
irPtr = Tcl_FetchIntRep((objPtr), &tclListType); \
|
||||
(listRepPtr) = irPtr ? irPtr->twoPtrValue.ptr1 : NULL; \
|
||||
} while (0)
|
||||
|
||||
#define ListResetIntRep(objPtr, listRepPtr) \
|
||||
Tcl_FetchIntRep((objPtr), &tclListType)->twoPtrValue.ptr1 = (listRepPtr)
|
||||
|
||||
#ifndef TCL_MIN_ELEMENT_GROWTH
|
||||
#define TCL_MIN_ELEMENT_GROWTH TCL_MIN_GROWTH/sizeof(Tcl_Obj *)
|
||||
#endif
|
||||
@@ -374,8 +396,7 @@ Tcl_SetListObj(
|
||||
listRepPtr = NewListIntRep(objc, objv, 1);
|
||||
ListSetIntRep(objPtr, listRepPtr);
|
||||
} else {
|
||||
objPtr->bytes = tclEmptyStringRep;
|
||||
objPtr->length = 0;
|
||||
Tcl_InitStringRep(objPtr, NULL, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -407,8 +428,10 @@ TclListObjCopy(
|
||||
* to be returned. */
|
||||
{
|
||||
Tcl_Obj *copyPtr;
|
||||
List *listRepPtr;
|
||||
|
||||
if (listPtr->typePtr != &tclListType) {
|
||||
ListGetIntRep(listPtr, listRepPtr);
|
||||
if (NULL == listRepPtr) {
|
||||
if (SetListFromAny(interp, listPtr) != TCL_OK) {
|
||||
return NULL;
|
||||
}
|
||||
@@ -462,10 +485,13 @@ Tcl_ListObjGetElements(
|
||||
{
|
||||
register List *listRepPtr;
|
||||
|
||||
if (listPtr->typePtr != &tclListType) {
|
||||
int result;
|
||||
ListGetIntRep(listPtr, listRepPtr);
|
||||
|
||||
if (listPtr->bytes == tclEmptyStringRep) {
|
||||
if (listRepPtr == NULL) {
|
||||
int result, length;
|
||||
|
||||
(void) Tcl_GetStringFromObj(listPtr, &length);
|
||||
if (length == 0) {
|
||||
*objcPtr = 0;
|
||||
*objvPtr = NULL;
|
||||
return TCL_OK;
|
||||
@@ -474,8 +500,8 @@ Tcl_ListObjGetElements(
|
||||
if (result != TCL_OK) {
|
||||
return result;
|
||||
}
|
||||
ListGetIntRep(listPtr, listRepPtr);
|
||||
}
|
||||
listRepPtr = ListRepPtr(listPtr);
|
||||
*objcPtr = listRepPtr->elemCount;
|
||||
*objvPtr = &listRepPtr->elements;
|
||||
return TCL_OK;
|
||||
@@ -572,10 +598,13 @@ Tcl_ListObjAppendElement(
|
||||
if (Tcl_IsShared(listPtr)) {
|
||||
Tcl_Panic("%s called with shared object", "Tcl_ListObjAppendElement");
|
||||
}
|
||||
if (listPtr->typePtr != &tclListType) {
|
||||
int result;
|
||||
|
||||
if (listPtr->bytes == tclEmptyStringRep) {
|
||||
ListGetIntRep(listPtr, listRepPtr);
|
||||
if (listRepPtr == NULL) {
|
||||
int result, length;
|
||||
|
||||
(void) Tcl_GetStringFromObj(listPtr, &length);
|
||||
if (length == 0) {
|
||||
Tcl_SetListObj(listPtr, 1, &objPtr);
|
||||
return TCL_OK;
|
||||
}
|
||||
@@ -583,9 +612,9 @@ Tcl_ListObjAppendElement(
|
||||
if (result != TCL_OK) {
|
||||
return result;
|
||||
}
|
||||
ListGetIntRep(listPtr, listRepPtr);
|
||||
}
|
||||
|
||||
listRepPtr = ListRepPtr(listPtr);
|
||||
numElems = listRepPtr->elemCount;
|
||||
numRequired = numElems + 1 ;
|
||||
needGrow = (numRequired > listRepPtr->maxElemCount);
|
||||
@@ -681,7 +710,7 @@ Tcl_ListObjAppendElement(
|
||||
}
|
||||
listRepPtr = newPtr;
|
||||
}
|
||||
listPtr->internalRep.twoPtrValue.ptr1 = listRepPtr;
|
||||
ListResetIntRep(listPtr, listRepPtr);
|
||||
|
||||
/*
|
||||
* Add objPtr to the end of listPtr's array of element pointers. Increment
|
||||
@@ -736,10 +765,12 @@ Tcl_ListObjIndex(
|
||||
{
|
||||
register List *listRepPtr;
|
||||
|
||||
if (listPtr->typePtr != &tclListType) {
|
||||
int result;
|
||||
ListGetIntRep(listPtr, listRepPtr);
|
||||
if (listRepPtr == NULL) {
|
||||
int result, length;
|
||||
|
||||
if (listPtr->bytes == tclEmptyStringRep) {
|
||||
(void) Tcl_GetStringFromObj(listPtr, &length);
|
||||
if (length == 0) {
|
||||
*objPtrPtr = NULL;
|
||||
return TCL_OK;
|
||||
}
|
||||
@@ -747,9 +778,9 @@ Tcl_ListObjIndex(
|
||||
if (result != TCL_OK) {
|
||||
return result;
|
||||
}
|
||||
ListGetIntRep(listPtr, listRepPtr);
|
||||
}
|
||||
|
||||
listRepPtr = ListRepPtr(listPtr);
|
||||
if ((index < 0) || (index >= listRepPtr->elemCount)) {
|
||||
*objPtrPtr = NULL;
|
||||
} else {
|
||||
@@ -789,10 +820,12 @@ Tcl_ListObjLength(
|
||||
{
|
||||
register List *listRepPtr;
|
||||
|
||||
if (listPtr->typePtr != &tclListType) {
|
||||
int result;
|
||||
ListGetIntRep(listPtr, listRepPtr);
|
||||
if (listRepPtr == NULL) {
|
||||
int result, length;
|
||||
|
||||
if (listPtr->bytes == tclEmptyStringRep) {
|
||||
(void) Tcl_GetStringFromObj(listPtr, &length);
|
||||
if (length == 0) {
|
||||
*intPtr = 0;
|
||||
return TCL_OK;
|
||||
}
|
||||
@@ -800,9 +833,9 @@ Tcl_ListObjLength(
|
||||
if (result != TCL_OK) {
|
||||
return result;
|
||||
}
|
||||
ListGetIntRep(listPtr, listRepPtr);
|
||||
}
|
||||
|
||||
listRepPtr = ListRepPtr(listPtr);
|
||||
*intPtr = listRepPtr->elemCount;
|
||||
return TCL_OK;
|
||||
}
|
||||
@@ -862,9 +895,14 @@ Tcl_ListObjReplace(
|
||||
if (Tcl_IsShared(listPtr)) {
|
||||
Tcl_Panic("%s called with shared object", "Tcl_ListObjReplace");
|
||||
}
|
||||
if (listPtr->typePtr != &tclListType) {
|
||||
if (listPtr->bytes == tclEmptyStringRep) {
|
||||
if (!objc) {
|
||||
|
||||
ListGetIntRep(listPtr, listRepPtr);
|
||||
if (listRepPtr == NULL) {
|
||||
int length;
|
||||
|
||||
(void) Tcl_GetStringFromObj(listPtr, &length);
|
||||
if (length == 0) {
|
||||
if (objc == 0) {
|
||||
return TCL_OK;
|
||||
}
|
||||
Tcl_SetListObj(listPtr, objc, NULL);
|
||||
@@ -875,6 +913,7 @@ Tcl_ListObjReplace(
|
||||
return result;
|
||||
}
|
||||
}
|
||||
ListGetIntRep(listPtr, listRepPtr);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -885,7 +924,6 @@ Tcl_ListObjReplace(
|
||||
* Resist any temptation to optimize this case.
|
||||
*/
|
||||
|
||||
listRepPtr = ListRepPtr(listPtr);
|
||||
elemPtrs = &listRepPtr->elements;
|
||||
numElems = listRepPtr->elemCount;
|
||||
|
||||
@@ -939,7 +977,7 @@ Tcl_ListObjReplace(
|
||||
}
|
||||
if (newPtr) {
|
||||
listRepPtr = newPtr;
|
||||
listPtr->internalRep.twoPtrValue.ptr1 = listRepPtr;
|
||||
ListResetIntRep(listPtr, listRepPtr);
|
||||
elemPtrs = &listRepPtr->elements;
|
||||
listRepPtr->maxElemCount = attempt;
|
||||
needGrow = numRequired > listRepPtr->maxElemCount;
|
||||
@@ -1012,7 +1050,7 @@ Tcl_ListObjReplace(
|
||||
}
|
||||
}
|
||||
|
||||
listPtr->internalRep.twoPtrValue.ptr1 = listRepPtr;
|
||||
ListResetIntRep(listPtr, listRepPtr);
|
||||
listRepPtr->refCount++;
|
||||
|
||||
elemPtrs = &listRepPtr->elements;
|
||||
@@ -1127,6 +1165,7 @@ TclLindexList(
|
||||
|
||||
int index; /* Index into the list. */
|
||||
Tcl_Obj *indexListCopy;
|
||||
List *listRepPtr;
|
||||
|
||||
/*
|
||||
* Determine whether argPtr designates a list or a single index. We have
|
||||
@@ -1134,7 +1173,8 @@ TclLindexList(
|
||||
* shimmering; see TIP#22 and TIP#33 for the details.
|
||||
*/
|
||||
|
||||
if (argPtr->typePtr != &tclListType
|
||||
ListGetIntRep(argPtr, listRepPtr);
|
||||
if ((listRepPtr == NULL)
|
||||
&& TclGetIntForIndexM(NULL , argPtr, 0, &index) == TCL_OK) {
|
||||
/*
|
||||
* argPtr designates a single index.
|
||||
@@ -1165,19 +1205,12 @@ TclLindexList(
|
||||
return TclLindexFlat(interp, listPtr, 1, &argPtr);
|
||||
}
|
||||
|
||||
if (indexListCopy->typePtr == &tclListType) {
|
||||
List *listRepPtr = ListRepPtr(indexListCopy);
|
||||
ListGetIntRep(indexListCopy, listRepPtr);
|
||||
|
||||
listPtr = TclLindexFlat(interp, listPtr, listRepPtr->elemCount,
|
||||
assert(listRepPtr != NULL);
|
||||
|
||||
listPtr = TclLindexFlat(interp, listPtr, listRepPtr->elemCount,
|
||||
&listRepPtr->elements);
|
||||
} else {
|
||||
int indexCount = -1; /* Size of the array of list indices. */
|
||||
Tcl_Obj **indices = NULL;
|
||||
/* Array of list indices. */
|
||||
|
||||
Tcl_ListObjGetElements(NULL, indexListCopy, &indexCount, &indices);
|
||||
listPtr = TclLindexFlat(interp, listPtr, indexCount, indices);
|
||||
}
|
||||
Tcl_DecrRefCount(indexListCopy);
|
||||
return listPtr;
|
||||
}
|
||||
@@ -1312,6 +1345,7 @@ TclLsetList(
|
||||
Tcl_Obj *retValuePtr; /* Pointer to the list to be returned. */
|
||||
int index; /* Current index in the list - discarded. */
|
||||
Tcl_Obj *indexListCopy;
|
||||
List *listRepPtr;
|
||||
|
||||
/*
|
||||
* Determine whether the index arg designates a list or a single index.
|
||||
@@ -1319,7 +1353,8 @@ TclLsetList(
|
||||
* shimmering; see TIP #22 and #23 for details.
|
||||
*/
|
||||
|
||||
if (indexArgPtr->typePtr != &tclListType
|
||||
ListGetIntRep(indexArgPtr, listRepPtr);
|
||||
if (listRepPtr == NULL
|
||||
&& TclGetIntForIndexM(NULL, indexArgPtr, 0, &index) == TCL_OK) {
|
||||
/*
|
||||
* indexArgPtr designates a single index.
|
||||
@@ -1404,6 +1439,7 @@ TclLsetFlat(
|
||||
{
|
||||
int index, result, len;
|
||||
Tcl_Obj *subListPtr, *retValuePtr, *chainPtr;
|
||||
Tcl_ObjIntRep *irPtr;
|
||||
|
||||
/*
|
||||
* If there are no indices, simply return the new value. (Without
|
||||
@@ -1534,7 +1570,8 @@ TclLsetFlat(
|
||||
* them at that time.
|
||||
*/
|
||||
|
||||
parentList->internalRep.twoPtrValue.ptr2 = chainPtr;
|
||||
irPtr = Tcl_FetchIntRep(parentList, &tclListType);
|
||||
irPtr->twoPtrValue.ptr2 = chainPtr;
|
||||
chainPtr = parentList;
|
||||
}
|
||||
} while (indexCount > 0);
|
||||
@@ -1562,8 +1599,9 @@ TclLsetFlat(
|
||||
* Clear away our intrep surgery mess.
|
||||
*/
|
||||
|
||||
chainPtr = objPtr->internalRep.twoPtrValue.ptr2;
|
||||
objPtr->internalRep.twoPtrValue.ptr2 = NULL;
|
||||
irPtr = Tcl_FetchIntRep(objPtr, &tclListType);
|
||||
chainPtr = irPtr->twoPtrValue.ptr2;
|
||||
irPtr->twoPtrValue.ptr2 = NULL;
|
||||
}
|
||||
|
||||
if (result != TCL_OK) {
|
||||
@@ -1647,10 +1685,13 @@ TclListObjSetElement(
|
||||
if (Tcl_IsShared(listPtr)) {
|
||||
Tcl_Panic("%s called with shared object", "TclListObjSetElement");
|
||||
}
|
||||
if (listPtr->typePtr != &tclListType) {
|
||||
int result;
|
||||
|
||||
if (listPtr->bytes == tclEmptyStringRep) {
|
||||
ListGetIntRep(listPtr, listRepPtr);
|
||||
if (listRepPtr == NULL) {
|
||||
int result, length;
|
||||
|
||||
(void) Tcl_GetStringFromObj(listPtr, &length);
|
||||
if (length == 0) {
|
||||
if (interp != NULL) {
|
||||
Tcl_SetObjResult(interp,
|
||||
Tcl_NewStringObj("list index out of range", -1));
|
||||
@@ -1663,9 +1704,9 @@ TclListObjSetElement(
|
||||
if (result != TCL_OK) {
|
||||
return result;
|
||||
}
|
||||
ListGetIntRep(listPtr, listRepPtr);
|
||||
}
|
||||
|
||||
listRepPtr = ListRepPtr(listPtr);
|
||||
elemCount = listRepPtr->elemCount;
|
||||
|
||||
/*
|
||||
@@ -1708,7 +1749,8 @@ TclListObjSetElement(
|
||||
|
||||
listRepPtr->refCount--;
|
||||
|
||||
listPtr->internalRep.twoPtrValue.ptr1 = listRepPtr = newPtr;
|
||||
listRepPtr = newPtr;
|
||||
ListResetIntRep(listPtr, listRepPtr);
|
||||
}
|
||||
elemPtrs = &listRepPtr->elements;
|
||||
|
||||
@@ -1745,9 +1787,8 @@ TclListObjSetElement(
|
||||
* None.
|
||||
*
|
||||
* Side effects:
|
||||
* Frees listPtr's List* internal representation and sets listPtr's
|
||||
* internalRep.twoPtrValue.ptr1 to NULL. Decrements the ref counts of all
|
||||
* element objects, which may free them.
|
||||
* Frees listPtr's List* internal representation, if no longer shared.
|
||||
* May decrement the ref counts of element objects, which may free them.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
@@ -1756,7 +1797,10 @@ static void
|
||||
FreeListInternalRep(
|
||||
Tcl_Obj *listPtr) /* List object with internal rep to free. */
|
||||
{
|
||||
List *listRepPtr = ListRepPtr(listPtr);
|
||||
List *listRepPtr;
|
||||
|
||||
ListGetIntRep(listPtr, listRepPtr);
|
||||
assert(listRepPtr != NULL);
|
||||
|
||||
if (listRepPtr->refCount-- <= 1) {
|
||||
Tcl_Obj **elemPtrs = &listRepPtr->elements;
|
||||
@@ -1767,8 +1811,6 @@ FreeListInternalRep(
|
||||
}
|
||||
ckfree(listRepPtr);
|
||||
}
|
||||
|
||||
listPtr->typePtr = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1793,8 +1835,10 @@ DupListInternalRep(
|
||||
Tcl_Obj *srcPtr, /* Object with internal rep to copy. */
|
||||
Tcl_Obj *copyPtr) /* Object with internal rep to set. */
|
||||
{
|
||||
List *listRepPtr = ListRepPtr(srcPtr);
|
||||
List *listRepPtr;
|
||||
|
||||
ListGetIntRep(srcPtr, listRepPtr);
|
||||
assert(listRepPtr != NULL);
|
||||
ListSetIntRep(copyPtr, listRepPtr);
|
||||
}
|
||||
|
||||
@@ -1833,7 +1877,7 @@ SetListFromAny(
|
||||
* describe duplicate keys).
|
||||
*/
|
||||
|
||||
if (objPtr->typePtr == &tclDictType && !objPtr->bytes) {
|
||||
if (Tcl_FetchIntRep(objPtr, &tclDictType) && !objPtr->bytes) {
|
||||
Tcl_Obj *keyPtr, *valuePtr;
|
||||
Tcl_DictSearch search;
|
||||
int done, size;
|
||||
@@ -1891,10 +1935,12 @@ SetListFromAny(
|
||||
|
||||
while (nextElem < limit) {
|
||||
const char *elemStart;
|
||||
char *check;
|
||||
int elemSize, literal;
|
||||
|
||||
if (TCL_OK != TclFindElement(interp, nextElem, limit - nextElem,
|
||||
&elemStart, &nextElem, &elemSize, &literal)) {
|
||||
fail:
|
||||
while (--elemPtrs >= &listRepPtr->elements) {
|
||||
Tcl_DecrRefCount(*elemPtrs);
|
||||
}
|
||||
@@ -1905,14 +1951,21 @@ SetListFromAny(
|
||||
break;
|
||||
}
|
||||
|
||||
/* TODO: replace panic with error on alloc failure? */
|
||||
if (literal) {
|
||||
TclNewStringObj(*elemPtrs, elemStart, elemSize);
|
||||
} else {
|
||||
TclNewObj(*elemPtrs);
|
||||
(*elemPtrs)->bytes = ckalloc((unsigned) elemSize + 1);
|
||||
(*elemPtrs)->length = TclCopyAndCollapse(elemSize, elemStart,
|
||||
(*elemPtrs)->bytes);
|
||||
TclNewObj(*elemPtrs);
|
||||
TclInvalidateStringRep(*elemPtrs);
|
||||
check = Tcl_InitStringRep(*elemPtrs, literal ? elemStart : NULL,
|
||||
elemSize);
|
||||
if (elemSize && check == NULL) {
|
||||
if (interp) {
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(
|
||||
"cannot construct list, out of memory", -1));
|
||||
Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL);
|
||||
}
|
||||
goto fail;
|
||||
}
|
||||
if (!literal) {
|
||||
Tcl_InitStringRep(*elemPtrs, NULL,
|
||||
TclCopyAndCollapse(elemSize, elemStart, check));
|
||||
}
|
||||
|
||||
Tcl_IncrRefCount(*elemPtrs++);/* Since list now holds ref to it. */
|
||||
@@ -1922,12 +1975,11 @@ SetListFromAny(
|
||||
}
|
||||
|
||||
/*
|
||||
* Free the old internalRep before setting the new one. We do this as late
|
||||
* Store the new internalRep. We do this as late
|
||||
* as possible to allow the conversion code, in particular
|
||||
* Tcl_GetStringFromObj, to use that old internalRep.
|
||||
* Tcl_GetStringFromObj, to use the old internalRep.
|
||||
*/
|
||||
|
||||
TclFreeIntRep(objPtr);
|
||||
ListSetIntRep(objPtr, listRepPtr);
|
||||
return TCL_OK;
|
||||
}
|
||||
@@ -1959,12 +2011,17 @@ UpdateStringOfList(
|
||||
{
|
||||
# define LOCAL_SIZE 20
|
||||
int localFlags[LOCAL_SIZE], *flagPtr = NULL;
|
||||
List *listRepPtr = ListRepPtr(listPtr);
|
||||
int numElems = listRepPtr->elemCount;
|
||||
int i, length, bytesNeeded = 0;
|
||||
int numElems, i, length, bytesNeeded = 0;
|
||||
const char *elem;
|
||||
char *dst;
|
||||
Tcl_Obj **elemPtrs;
|
||||
List *listRepPtr;
|
||||
|
||||
ListGetIntRep(listPtr, listRepPtr);
|
||||
|
||||
assert(listRepPtr != NULL);
|
||||
|
||||
numElems = listRepPtr->elemCount;
|
||||
|
||||
/*
|
||||
* Mark the list as being canonical; although it will now have a string
|
||||
@@ -1979,8 +2036,7 @@ UpdateStringOfList(
|
||||
*/
|
||||
|
||||
if (numElems == 0) {
|
||||
listPtr->bytes = tclEmptyStringRep;
|
||||
listPtr->length = 0;
|
||||
Tcl_InitStringRep(listPtr, NULL, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2009,22 +2065,21 @@ UpdateStringOfList(
|
||||
if (bytesNeeded > INT_MAX - numElems + 1) {
|
||||
Tcl_Panic("max size for a Tcl value (%d bytes) exceeded", INT_MAX);
|
||||
}
|
||||
bytesNeeded += numElems;
|
||||
bytesNeeded += numElems - 1;
|
||||
|
||||
/*
|
||||
* Pass 2: copy into string rep buffer.
|
||||
*/
|
||||
|
||||
listPtr->length = bytesNeeded - 1;
|
||||
listPtr->bytes = ckalloc(bytesNeeded);
|
||||
dst = listPtr->bytes;
|
||||
dst = Tcl_InitStringRep(listPtr, NULL, bytesNeeded);
|
||||
TclOOM(dst, bytesNeeded);
|
||||
for (i = 0; i < numElems; i++) {
|
||||
flagPtr[i] |= (i ? TCL_DONT_QUOTE_HASH : 0);
|
||||
elem = TclGetStringFromObj(elemPtrs[i], &length);
|
||||
dst += TclConvertElement(elem, length, dst, flagPtr[i]);
|
||||
*dst++ = ' ';
|
||||
}
|
||||
listPtr->bytes[listPtr->length] = '\0';
|
||||
(void) Tcl_InitStringRep(listPtr, NULL, bytesNeeded);
|
||||
|
||||
if (flagPtr != localFlags) {
|
||||
ckfree(flagPtr);
|
||||
|
||||
+38
-27
@@ -25,6 +25,7 @@
|
||||
|
||||
#include "tclInt.h"
|
||||
#include "tclCompile.h" /* for TclLogCommandInfo visibility */
|
||||
#include <assert.h>
|
||||
|
||||
/*
|
||||
* Thread-local storage used to avoid having a global lock on data that is not
|
||||
@@ -154,6 +155,22 @@ static const Tcl_ObjType nsNameType = {
|
||||
SetNsNameFromAny /* setFromAnyProc */
|
||||
};
|
||||
|
||||
#define NsNameSetIntRep(objPtr, nnPtr) \
|
||||
do { \
|
||||
Tcl_ObjIntRep ir; \
|
||||
(nnPtr)->refCount++; \
|
||||
ir.twoPtrValue.ptr1 = (nnPtr); \
|
||||
ir.twoPtrValue.ptr2 = NULL; \
|
||||
Tcl_StoreIntRep((objPtr), &nsNameType, &ir); \
|
||||
} while (0)
|
||||
|
||||
#define NsNameGetIntRep(objPtr, nnPtr) \
|
||||
do { \
|
||||
const Tcl_ObjIntRep *irPtr; \
|
||||
irPtr = Tcl_FetchIntRep((objPtr), &nsNameType); \
|
||||
(nnPtr) = irPtr ? irPtr->twoPtrValue.ptr1 : NULL; \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Array of values describing how to implement each standard subcommand of the
|
||||
* "namespace" command.
|
||||
@@ -2830,15 +2847,16 @@ GetNamespaceFromObj(
|
||||
Tcl_Namespace **nsPtrPtr) /* Result namespace pointer goes here. */
|
||||
{
|
||||
ResolvedNsName *resNamePtr;
|
||||
Namespace *nsPtr, *refNsPtr;
|
||||
|
||||
if (objPtr->typePtr == &nsNameType) {
|
||||
NsNameGetIntRep(objPtr, resNamePtr);
|
||||
if (resNamePtr) {
|
||||
Namespace *nsPtr, *refNsPtr;
|
||||
|
||||
/*
|
||||
* Check that the ResolvedNsName is still valid; avoid letting the ref
|
||||
* cross interps.
|
||||
*/
|
||||
|
||||
resNamePtr = objPtr->internalRep.twoPtrValue.ptr1;
|
||||
nsPtr = resNamePtr->nsPtr;
|
||||
refNsPtr = resNamePtr->refNsPtr;
|
||||
if (!(nsPtr->flags & NS_DYING) && (interp == nsPtr->interp) &&
|
||||
@@ -2847,9 +2865,11 @@ GetNamespaceFromObj(
|
||||
*nsPtrPtr = (Tcl_Namespace *) nsPtr;
|
||||
return TCL_OK;
|
||||
}
|
||||
TclFreeIntRep(objPtr);
|
||||
}
|
||||
if (SetNsNameFromAny(interp, objPtr) == TCL_OK) {
|
||||
resNamePtr = objPtr->internalRep.twoPtrValue.ptr1;
|
||||
NsNameGetIntRep(objPtr, resNamePtr);
|
||||
assert(resNamePtr != NULL);
|
||||
*nsPtrPtr = (Tcl_Namespace *) resNamePtr->nsPtr;
|
||||
return TCL_OK;
|
||||
}
|
||||
@@ -4634,8 +4654,11 @@ FreeNsNameInternalRep(
|
||||
register Tcl_Obj *objPtr) /* nsName object with internal representation
|
||||
* to free. */
|
||||
{
|
||||
ResolvedNsName *resNamePtr = objPtr->internalRep.twoPtrValue.ptr1;
|
||||
ResolvedNsName *resNamePtr;
|
||||
|
||||
NsNameGetIntRep(objPtr, resNamePtr);
|
||||
assert(resNamePtr != NULL);
|
||||
|
||||
/*
|
||||
* Decrement the reference count of the namespace. If there are no more
|
||||
* references, free it up.
|
||||
@@ -4652,7 +4675,6 @@ FreeNsNameInternalRep(
|
||||
TclNsDecrRefCount(resNamePtr->nsPtr);
|
||||
ckfree(resNamePtr);
|
||||
}
|
||||
objPtr->typePtr = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -4679,11 +4701,11 @@ DupNsNameInternalRep(
|
||||
Tcl_Obj *srcPtr, /* Object with internal rep to copy. */
|
||||
register Tcl_Obj *copyPtr) /* Object with internal rep to set. */
|
||||
{
|
||||
ResolvedNsName *resNamePtr = srcPtr->internalRep.twoPtrValue.ptr1;
|
||||
ResolvedNsName *resNamePtr;
|
||||
|
||||
copyPtr->internalRep.twoPtrValue.ptr1 = resNamePtr;
|
||||
resNamePtr->refCount++;
|
||||
copyPtr->typePtr = &nsNameType;
|
||||
NsNameGetIntRep(srcPtr, resNamePtr);
|
||||
assert(resNamePtr != NULL);
|
||||
NsNameSetIntRep(copyPtr, resNamePtr);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -4728,24 +4750,15 @@ SetNsNameFromAny(
|
||||
TclGetNamespaceForQualName(interp, name, NULL, TCL_FIND_ONLY_NS,
|
||||
&nsPtr, &dummy1Ptr, &dummy2Ptr, &dummy);
|
||||
|
||||
if ((nsPtr == NULL) || (nsPtr->flags & NS_DYING)) {
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we found a namespace, then create a new ResolvedNsName structure
|
||||
* that holds a reference to it.
|
||||
*/
|
||||
|
||||
if ((nsPtr == NULL) || (nsPtr->flags & NS_DYING)) {
|
||||
/*
|
||||
* Our failed lookup proves any previously cached nsName intrep is no
|
||||
* longer valid. Get rid of it so we no longer waste memory storing
|
||||
* it, nor time determining its invalidity again and again.
|
||||
*/
|
||||
|
||||
if (objPtr->typePtr == &nsNameType) {
|
||||
TclFreeIntRep(objPtr);
|
||||
}
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
nsPtr->refCount++;
|
||||
resNamePtr = ckalloc(sizeof(ResolvedNsName));
|
||||
resNamePtr->nsPtr = nsPtr;
|
||||
@@ -4754,10 +4767,8 @@ SetNsNameFromAny(
|
||||
} else {
|
||||
resNamePtr->refNsPtr = (Namespace *) Tcl_GetCurrentNamespace(interp);
|
||||
}
|
||||
resNamePtr->refCount = 1;
|
||||
TclFreeIntRep(objPtr);
|
||||
objPtr->internalRep.twoPtrValue.ptr1 = resNamePtr;
|
||||
objPtr->typePtr = &nsNameType;
|
||||
resNamePtr->refCount = 0;
|
||||
NsNameSetIntRep(objPtr, resNamePtr);
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
@@ -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.
|
||||
*
|
||||
*----------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
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;
|
||||
|
||||
+66
-34
@@ -15,6 +15,7 @@
|
||||
|
||||
#include "tclInt.h"
|
||||
#include "tclCompile.h"
|
||||
#include <assert.h>
|
||||
|
||||
/*
|
||||
* Variables that are part of the [apply] command implementation and which
|
||||
@@ -91,13 +92,31 @@ static const Tcl_ObjType levelReferenceType = {
|
||||
* will execute within. IF YOU CHANGE THIS, CHECK IN tclDisassemble.c TOO.
|
||||
*/
|
||||
|
||||
const Tcl_ObjType tclLambdaType = {
|
||||
static const Tcl_ObjType lambdaType = {
|
||||
"lambdaExpr", /* name */
|
||||
FreeLambdaInternalRep, /* freeIntRepProc */
|
||||
DupLambdaInternalRep, /* dupIntRepProc */
|
||||
NULL, /* updateStringProc */
|
||||
SetLambdaFromAny /* setFromAnyProc */
|
||||
};
|
||||
|
||||
#define LambdaSetIntRep(objPtr, procPtr, nsObjPtr) \
|
||||
do { \
|
||||
Tcl_ObjIntRep ir; \
|
||||
ir.twoPtrValue.ptr1 = (procPtr); \
|
||||
ir.twoPtrValue.ptr2 = (nsObjPtr); \
|
||||
Tcl_IncrRefCount((nsObjPtr)); \
|
||||
Tcl_StoreIntRep((objPtr), &lambdaType, &ir); \
|
||||
} while (0)
|
||||
|
||||
#define LambdaGetIntRep(objPtr, procPtr, nsObjPtr) \
|
||||
do { \
|
||||
const Tcl_ObjIntRep *irPtr; \
|
||||
irPtr = Tcl_FetchIntRep((objPtr), &lambdaType); \
|
||||
(procPtr) = irPtr ? irPtr->twoPtrValue.ptr1 : NULL; \
|
||||
(nsObjPtr) = irPtr ? irPtr->twoPtrValue.ptr2 : NULL; \
|
||||
} while (0)
|
||||
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
@@ -2423,15 +2442,15 @@ DupLambdaInternalRep(
|
||||
Tcl_Obj *srcPtr, /* Object with internal rep to copy. */
|
||||
register Tcl_Obj *copyPtr) /* Object with internal rep to set. */
|
||||
{
|
||||
Proc *procPtr = srcPtr->internalRep.twoPtrValue.ptr1;
|
||||
Tcl_Obj *nsObjPtr = srcPtr->internalRep.twoPtrValue.ptr2;
|
||||
Proc *procPtr;
|
||||
Tcl_Obj *nsObjPtr;
|
||||
|
||||
copyPtr->internalRep.twoPtrValue.ptr1 = procPtr;
|
||||
copyPtr->internalRep.twoPtrValue.ptr2 = nsObjPtr;
|
||||
LambdaGetIntRep(srcPtr, procPtr, nsObjPtr);
|
||||
assert(procPtr != NULL);
|
||||
|
||||
procPtr->refCount++;
|
||||
Tcl_IncrRefCount(nsObjPtr);
|
||||
copyPtr->typePtr = &tclLambdaType;
|
||||
|
||||
LambdaSetIntRep(copyPtr, procPtr, nsObjPtr);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -2439,14 +2458,16 @@ FreeLambdaInternalRep(
|
||||
register Tcl_Obj *objPtr) /* CmdName object with internal representation
|
||||
* to free. */
|
||||
{
|
||||
Proc *procPtr = objPtr->internalRep.twoPtrValue.ptr1;
|
||||
Tcl_Obj *nsObjPtr = objPtr->internalRep.twoPtrValue.ptr2;
|
||||
Proc *procPtr;
|
||||
Tcl_Obj *nsObjPtr;
|
||||
|
||||
LambdaGetIntRep(objPtr, procPtr, nsObjPtr);
|
||||
assert(procPtr != NULL);
|
||||
|
||||
if (procPtr->refCount-- == 1) {
|
||||
TclProcCleanupProc(procPtr);
|
||||
}
|
||||
TclDecrRefCount(nsObjPtr);
|
||||
objPtr->typePtr = NULL;
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -2467,7 +2488,7 @@ SetLambdaFromAny(
|
||||
|
||||
/*
|
||||
* Convert objPtr to list type first; if it cannot be converted, or if its
|
||||
* length is not 2, then it cannot be converted to tclLambdaType.
|
||||
* length is not 2, then it cannot be converted to lambdaType.
|
||||
*/
|
||||
|
||||
result = TclListObjGetElements(NULL, objPtr, &objc, &objv);
|
||||
@@ -2608,21 +2629,42 @@ SetLambdaFromAny(
|
||||
}
|
||||
}
|
||||
|
||||
Tcl_IncrRefCount(nsObjPtr);
|
||||
|
||||
/*
|
||||
* Free the list internalrep of objPtr - this will free argsPtr, but
|
||||
* bodyPtr retains a reference from the Proc structure. Then finish the
|
||||
* conversion to tclLambdaType.
|
||||
* conversion to lambdaType.
|
||||
*/
|
||||
|
||||
TclFreeIntRep(objPtr);
|
||||
|
||||
objPtr->internalRep.twoPtrValue.ptr1 = procPtr;
|
||||
objPtr->internalRep.twoPtrValue.ptr2 = nsObjPtr;
|
||||
objPtr->typePtr = &tclLambdaType;
|
||||
LambdaSetIntRep(objPtr, procPtr, nsObjPtr);
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
Proc *
|
||||
TclGetLambdaFromObj(
|
||||
Tcl_Interp *interp,
|
||||
Tcl_Obj *objPtr,
|
||||
Tcl_Obj **nsObjPtrPtr)
|
||||
{
|
||||
Proc *procPtr;
|
||||
Tcl_Obj *nsObjPtr;
|
||||
|
||||
LambdaGetIntRep(objPtr, procPtr, nsObjPtr);
|
||||
|
||||
if (procPtr == NULL) {
|
||||
if (SetLambdaFromAny(interp, objPtr) != TCL_OK) {
|
||||
return NULL;
|
||||
}
|
||||
LambdaGetIntRep(objPtr, procPtr, nsObjPtr);
|
||||
}
|
||||
|
||||
assert(procPtr != NULL);
|
||||
if (procPtr->iPtr != (Interp *)interp) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
*nsObjPtrPtr = nsObjPtr;
|
||||
return procPtr;
|
||||
}
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
@@ -2676,10 +2718,9 @@ TclNRApplyObjCmd(
|
||||
*/
|
||||
|
||||
lambdaPtr = objv[1];
|
||||
if (lambdaPtr->typePtr == &tclLambdaType) {
|
||||
procPtr = lambdaPtr->internalRep.twoPtrValue.ptr1;
|
||||
}
|
||||
procPtr = TclGetLambdaFromObj(interp, lambdaPtr, &nsObjPtr);
|
||||
|
||||
if (procPtr == NULL) {
|
||||
#define JOE_EXTENSION 0
|
||||
/*
|
||||
* Note: this code is NOT FUNCTIONAL due to the NR implementation; DO NOT
|
||||
@@ -2688,7 +2729,6 @@ TclNRApplyObjCmd(
|
||||
*/
|
||||
|
||||
#if JOE_EXTENSION
|
||||
else {
|
||||
/*
|
||||
* Joe English's suggestion to allow cmdNames to function as lambdas.
|
||||
*/
|
||||
@@ -2701,23 +2741,15 @@ TclNRApplyObjCmd(
|
||||
&elemPtr) == TCL_OK && numElem == 1)) {
|
||||
return Tcl_EvalObjv(interp, objc-1, objv+1, 0);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((procPtr == NULL) || (procPtr->iPtr != iPtr)) {
|
||||
result = SetLambdaFromAny(interp, lambdaPtr);
|
||||
if (result != TCL_OK) {
|
||||
return result;
|
||||
}
|
||||
procPtr = lambdaPtr->internalRep.twoPtrValue.ptr1;
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the namespace where this lambda should run, and push a call frame
|
||||
* for that namespace. Note that TclObjInterpProc() will pop it.
|
||||
* Push a call frame for the lambda namespace.
|
||||
* Note that TclObjInterpProc() will pop it.
|
||||
*/
|
||||
|
||||
nsObjPtr = lambdaPtr->internalRep.twoPtrValue.ptr2;
|
||||
result = TclGetNamespaceFromObj(interp, nsObjPtr, &nsPtr);
|
||||
if (result != TCL_OK) {
|
||||
return TCL_ERROR;
|
||||
|
||||
+32
-28
@@ -13,6 +13,7 @@
|
||||
|
||||
#include "tclInt.h"
|
||||
#include "tclRegexp.h"
|
||||
#include <assert.h>
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
@@ -107,6 +108,23 @@ const Tcl_ObjType tclRegexpType = {
|
||||
NULL, /* updateStringProc */
|
||||
SetRegexpFromAny /* setFromAnyProc */
|
||||
};
|
||||
|
||||
#define RegexpSetIntRep(objPtr, rePtr) \
|
||||
do { \
|
||||
Tcl_ObjIntRep ir; \
|
||||
(rePtr)->refCount++; \
|
||||
ir.twoPtrValue.ptr1 = (rePtr); \
|
||||
ir.twoPtrValue.ptr2 = NULL; \
|
||||
Tcl_StoreIntRep((objPtr), &tclRegexpType, &ir); \
|
||||
} while (0)
|
||||
|
||||
#define RegexpGetIntRep(objPtr, rePtr) \
|
||||
do { \
|
||||
const Tcl_ObjIntRep *irPtr; \
|
||||
irPtr = Tcl_FetchIntRep((objPtr), &tclRegexpType); \
|
||||
(rePtr) = irPtr ? irPtr->twoPtrValue.ptr1 : NULL; \
|
||||
} while (0)
|
||||
|
||||
|
||||
/*
|
||||
*----------------------------------------------------------------------
|
||||
@@ -573,14 +591,9 @@ Tcl_GetRegExpFromObj(
|
||||
TclRegexp *regexpPtr;
|
||||
const char *pattern;
|
||||
|
||||
/*
|
||||
* This is OK because we only actually interpret this value properly as a
|
||||
* TclRegexp* when the type is tclRegexpType.
|
||||
*/
|
||||
RegexpGetIntRep(objPtr, regexpPtr);
|
||||
|
||||
regexpPtr = objPtr->internalRep.twoPtrValue.ptr1;
|
||||
|
||||
if ((objPtr->typePtr != &tclRegexpType) || (regexpPtr->flags != flags)) {
|
||||
if ((regexpPtr == NULL) || (regexpPtr->flags != flags)) {
|
||||
pattern = TclGetStringFromObj(objPtr, &length);
|
||||
|
||||
regexpPtr = CompileRegexp(interp, pattern, length, flags);
|
||||
@@ -588,21 +601,7 @@ Tcl_GetRegExpFromObj(
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a reference to the regexp so it will persist even if it is
|
||||
* pushed out of the current thread's regexp cache. This reference
|
||||
* will be removed when the object's internal rep is freed.
|
||||
*/
|
||||
|
||||
regexpPtr->refCount++;
|
||||
|
||||
/*
|
||||
* Free the old representation and set our type.
|
||||
*/
|
||||
|
||||
TclFreeIntRep(objPtr);
|
||||
objPtr->internalRep.twoPtrValue.ptr1 = regexpPtr;
|
||||
objPtr->typePtr = &tclRegexpType;
|
||||
RegexpSetIntRep(objPtr, regexpPtr);
|
||||
}
|
||||
return (Tcl_RegExp) regexpPtr;
|
||||
}
|
||||
@@ -749,7 +748,11 @@ static void
|
||||
FreeRegexpInternalRep(
|
||||
Tcl_Obj *objPtr) /* Regexp object with internal rep to free. */
|
||||
{
|
||||
TclRegexp *regexpRepPtr = objPtr->internalRep.twoPtrValue.ptr1;
|
||||
TclRegexp *regexpRepPtr;
|
||||
|
||||
RegexpGetIntRep(objPtr, regexpRepPtr);
|
||||
|
||||
assert(regexpRepPtr != NULL);
|
||||
|
||||
/*
|
||||
* If this is the last reference to the regexp, free it.
|
||||
@@ -758,7 +761,6 @@ FreeRegexpInternalRep(
|
||||
if (regexpRepPtr->refCount-- <= 1) {
|
||||
FreeRegexp(regexpRepPtr);
|
||||
}
|
||||
objPtr->typePtr = NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -783,11 +785,13 @@ DupRegexpInternalRep(
|
||||
Tcl_Obj *srcPtr, /* Object with internal rep to copy. */
|
||||
Tcl_Obj *copyPtr) /* Object with internal rep to set. */
|
||||
{
|
||||
TclRegexp *regexpPtr = srcPtr->internalRep.twoPtrValue.ptr1;
|
||||
TclRegexp *regexpPtr;
|
||||
|
||||
regexpPtr->refCount++;
|
||||
copyPtr->internalRep.twoPtrValue.ptr1 = srcPtr->internalRep.twoPtrValue.ptr1;
|
||||
copyPtr->typePtr = &tclRegexpType;
|
||||
RegexpGetIntRep(srcPtr, regexpPtr);
|
||||
|
||||
assert(regexpPtr != NULL);
|
||||
|
||||
RegexpSetIntRep(copyPtr, regexpPtr);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
+4
-2
@@ -984,8 +984,10 @@ Tcl_ScanObjCmd(
|
||||
double dvalue;
|
||||
if (Tcl_GetDoubleFromObj(NULL, objPtr, &dvalue) != TCL_OK) {
|
||||
#ifdef ACCEPT_NAN
|
||||
if (objPtr->typePtr == &tclDoubleType) {
|
||||
dvalue = objPtr->internalRep.doubleValue;
|
||||
const Tcl_ObjIntRep *irPtr
|
||||
= Tcl_FetchIntRep(objPtr, &tclDoubleType);
|
||||
if (irPtr) {
|
||||
dvalue = irPtr->doubleValue;
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
+4
-10
@@ -789,7 +789,7 @@ Tcl_AfterObjCmd(
|
||||
AfterInfo *afterPtr;
|
||||
AfterAssocData *assocPtr;
|
||||
int length;
|
||||
int index;
|
||||
int index = -1;
|
||||
static const char *const afterSubCmds[] = {
|
||||
"cancel", "idle", "info", NULL
|
||||
};
|
||||
@@ -818,15 +818,9 @@ Tcl_AfterObjCmd(
|
||||
* First lets see if the command was passed a number as the first argument.
|
||||
*/
|
||||
|
||||
if (objv[1]->typePtr == &tclIntType
|
||||
#ifndef TCL_WIDE_INT_IS_LONG
|
||||
|| objv[1]->typePtr == &tclWideIntType
|
||||
#endif
|
||||
|| objv[1]->typePtr == &tclBignumType
|
||||
|| (Tcl_GetIndexFromObj(NULL, objv[1], afterSubCmds, "", 0,
|
||||
&index) != TCL_OK)) {
|
||||
index = -1;
|
||||
if (Tcl_GetWideIntFromObj(NULL, objv[1], &ms) != TCL_OK) {
|
||||
if (Tcl_GetWideIntFromObj(NULL, objv[1], &ms) != TCL_OK) {
|
||||
if (Tcl_GetIndexFromObj(NULL, objv[1], afterSubCmds, "", 0, &index)
|
||||
!= TCL_OK) {
|
||||
const char *arg = Tcl_GetString(objv[1]);
|
||||
|
||||
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
|
||||
|
||||
+9
-8
@@ -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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
+8
-12
@@ -218,10 +218,6 @@ static Tcl_SetFromAnyProc PanicOnSetVarName;
|
||||
* or NULL if it is this same obj
|
||||
* twoPtrValue.ptr2: index into locals table
|
||||
*
|
||||
* nsVarName - INTERNALREP DEFINITION:
|
||||
* twoPtrValue.ptr1: pointer to the namespace containing the reference
|
||||
* twoPtrValue.ptr2: pointer to the corresponding Var
|
||||
*
|
||||
* parsedVarName - INTERNALREP DEFINITION:
|
||||
* twoPtrValue.ptr1: pointer to the array name Tcl_Obj, or NULL if it is a
|
||||
* scalar variable
|
||||
@@ -234,7 +230,7 @@ static const Tcl_ObjType localVarNameType = {
|
||||
FreeLocalVarName, DupLocalVarName, PanicOnUpdateVarName, PanicOnSetVarName
|
||||
};
|
||||
|
||||
static const Tcl_ObjType tclParsedVarNameType = {
|
||||
static const Tcl_ObjType parsedVarNameType = {
|
||||
"parsedVarName",
|
||||
FreeParsedVarName, DupParsedVarName, PanicOnUpdateVarName, PanicOnSetVarName
|
||||
};
|
||||
@@ -442,7 +438,7 @@ TclLookupVar(
|
||||
* Side effects:
|
||||
* New hashtable entries may be created if createPart1 or createPart2
|
||||
* are 1. The object part1Ptr is converted to one of localVarNameType,
|
||||
* tclNsVarNameType or tclParsedVarNameType and caches as much of the
|
||||
* tclNsVarNameType or parsedVarNameType and caches as much of the
|
||||
* lookup as it can.
|
||||
* When createPart1 is 1, callers must IncrRefCount part1Ptr if they
|
||||
* plan to DecrRefCount it.
|
||||
@@ -562,11 +558,11 @@ TclObjLookupVarEx(
|
||||
}
|
||||
|
||||
/*
|
||||
* If part1Ptr is a tclParsedVarNameType, separate it into the pre-parsed
|
||||
* If part1Ptr is a parsedVarNameType, separate it into the pre-parsed
|
||||
* parts.
|
||||
*/
|
||||
|
||||
if (typePtr == &tclParsedVarNameType) {
|
||||
if (typePtr == &parsedVarNameType) {
|
||||
if (part1Ptr->internalRep.twoPtrValue.ptr1 != NULL) {
|
||||
if (part2Ptr != NULL) {
|
||||
/*
|
||||
@@ -632,12 +628,12 @@ TclObjLookupVarEx(
|
||||
|
||||
/*
|
||||
* Free the internal rep of the original part1Ptr, now renamed
|
||||
* objPtr, and set it to tclParsedVarNameType.
|
||||
* objPtr, and set it to parsedVarNameType.
|
||||
*/
|
||||
|
||||
objPtr = part1Ptr;
|
||||
TclFreeIntRep(objPtr);
|
||||
objPtr->typePtr = &tclParsedVarNameType;
|
||||
objPtr->typePtr = &parsedVarNameType;
|
||||
|
||||
/*
|
||||
* Define a new string object to hold the new part1Ptr, i.e.,
|
||||
@@ -706,7 +702,7 @@ TclObjLookupVarEx(
|
||||
* At least mark part1Ptr as already parsed.
|
||||
*/
|
||||
|
||||
part1Ptr->typePtr = &tclParsedVarNameType;
|
||||
part1Ptr->typePtr = &parsedVarNameType;
|
||||
part1Ptr->internalRep.twoPtrValue.ptr1 = NULL;
|
||||
part1Ptr->internalRep.twoPtrValue.ptr2 = NULL;
|
||||
}
|
||||
@@ -5603,7 +5599,7 @@ DupParsedVarName(
|
||||
|
||||
dupPtr->internalRep.twoPtrValue.ptr1 = arrayPtr;
|
||||
dupPtr->internalRep.twoPtrValue.ptr2 = elem;
|
||||
dupPtr->typePtr = &tclParsedVarNameType;
|
||||
dupPtr->typePtr = &parsedVarNameType;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
+19
-15
@@ -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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
Reference in New Issue
Block a user