summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog7
-rw-r--r--generic/tclListObj.c162
2 files changed, 63 insertions, 106 deletions
diff --git a/ChangeLog b/ChangeLog
index 2137717..fc3670e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2007-04-24 Miguel Sofer <msofer@users.sf.net>
+
+ * generic/tclListObj.c: reverting [Patch 738900] (committed on
+ 2007-04-20). Causes some Tk test breakage of unknown importance,
+ but the impact of the patch itself is likely to be so small that
+ it does not warrant investigation at this time.
+
2007-04-24 Donal K. Fellows <dkf@users.sf.net>
* generic/tclDictObj.c (DictKeysCmd): Rewrote so that the lock on the
diff --git a/generic/tclListObj.c b/generic/tclListObj.c
index 4332492..170831f 100644
--- a/generic/tclListObj.c
+++ b/generic/tclListObj.c
@@ -10,7 +10,7 @@
* See the file "license.terms" for information on usage and redistribution of
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tclListObj.c,v 1.45 2007/04/24 22:07:53 kennykb Exp $
+ * RCS: @(#) $Id: tclListObj.c,v 1.46 2007/04/24 22:31:39 msofer Exp $
*/
#include "tclInt.h"
@@ -1634,65 +1634,34 @@ SetListFromAny(
Tcl_Interp *interp, /* Used for error reporting if not NULL. */
Tcl_Obj *objPtr) /* The object to convert. */
{
- char *string = NULL, *s;
+ char *string, *s;
const char *elemStart, *nextElem;
int lenRemain, length, estCount, elemSize, hasBrace, i, j, result;
- const char *limit = NULL; /* Points just after string's last byte. */
+ const char *limit; /* Points just after string's last byte. */
register const char *p;
register Tcl_Obj **elemPtrs;
register Tcl_Obj *elemPtr;
List *listRepPtr;
- Tcl_ObjType *typePtr = objPtr->typePtr;
- int avoidParse;
- estCount = 1;
- avoidParse = 1;
- i = 1;
- if (objPtr->bytes && (objPtr->length == 0)) {
- i = 0;
- } else if ((typePtr != &tclIntType)
-#ifndef NO_WIDE_TYPE
- && (typePtr != &tclWideIntType)
-#endif
- && (typePtr != &tclDoubleType)
- && (typePtr != &tclBignumType)) {
-
- /*
- * Get the string representation. Make it up-to-date if necessary.
- */
+ /*
+ * Get the string representation. Make it up-to-date if necessary.
+ */
- string = Tcl_GetStringFromObj(objPtr, &length);
-
- /*
- * Get an overestimate of the number of elements by counting
- * whitespaces; force a thorough parsing of the list if the string
- * contains whitespaces or backslashes.
- */
-
- limit = string + length;
- for (p = string; p < limit; p++) {
- if (isspace(UCHAR(*p))) { /* INTL: ISO space. */
- estCount++;
- avoidParse = 0;
- }
- if (*p == '\\') {
- avoidParse = 0;
- }
- }
+ string = Tcl_GetStringFromObj(objPtr, &length);
- if (avoidParse) {
- /*
- * It is a single element without braces or spaces: check
- * that is a valid one-element list, and force full parsing if it
- * contains braces.
- */
-
- result = TclFindElement(interp, string, length, &elemStart,
- &nextElem, &elemSize, &hasBrace);
- if (result != TCL_OK) {
- return result;
- }
- avoidParse = !hasBrace;
+ /*
+ * Parse the string into separate string objects, and create a List
+ * structure that points to the element string objects. We use a modified
+ * version of Tcl_SplitList's implementation to avoid one malloc and a
+ * string copy for each list element. First, estimate the number of
+ * elements by counting the number of space characters in the list.
+ */
+
+ limit = string + length;
+ estCount = 1;
+ for (p = string; p < limit; p++) {
+ if (isspace(UCHAR(*p))) { /* INTL: ISO space. */
+ estCount++;
}
}
@@ -1711,73 +1680,54 @@ SetListFromAny(
}
elemPtrs = &listRepPtr->elements;
-
- if (avoidParse) {
- if (i) {
- /*
- * Single element list containing a duplicate of objPtr.
- */
-
- elemPtr = Tcl_DuplicateObj(objPtr);
- elemPtrs[0] = elemPtr;
- Tcl_IncrRefCount(elemPtr);
+ for (p=string, lenRemain=length, i=0;
+ lenRemain > 0;
+ p=nextElem, lenRemain=limit-nextElem, i++) {
+ result = TclFindElement(interp, p, lenRemain, &elemStart, &nextElem,
+ &elemSize, &hasBrace);
+ if (result != TCL_OK) {
+ for (j = 0; j < i; j++) {
+ elemPtr = elemPtrs[j];
+ Tcl_DecrRefCount(elemPtr);
+ }
+ ckfree((char *) listRepPtr);
+ return result;
}
- } else {
+ if (elemStart >= limit) {
+ break;
+ }
+ if (i > estCount) {
+ Tcl_Panic("SetListFromAny: bad size estimate for list");
+ }
+
/*
- * Parse the string into separate string objects, create a string
- * object for each element, and insert it into the List structure. We
- * use a modified version of Tcl_SplitList's implementation to avoid
- * one malloc and a string copy for each list element.
+ * Allocate a Tcl object for the element and initialize it from the
+ * "elemSize" bytes starting at "elemStart".
*/
- for (p=string, lenRemain=length, i=0;
- lenRemain > 0;
- p=nextElem, lenRemain=limit-nextElem, i++) {
- result = TclFindElement(interp, p, lenRemain, &elemStart, &nextElem,
- &elemSize, &hasBrace);
- if (result != TCL_OK) {
- for (j = 0; j < i; j++) {
- elemPtr = elemPtrs[j];
- Tcl_DecrRefCount(elemPtr);
- }
- ckfree((char *) listRepPtr);
- return result;
- }
- if (elemStart >= limit) {
- break;
- }
- if (i > estCount) {
- Tcl_Panic("SetListFromAny: bad size estimate for list");
- }
-
- /*
- * Allocate a Tcl object for the element and initialize it from
- * the "elemSize" bytes starting at "elemStart".
- */
-
- s = ckalloc((unsigned) elemSize + 1);
- if (hasBrace) {
- memcpy(s, elemStart, (size_t) elemSize);
- s[elemSize] = 0;
- } else {
- elemSize = TclCopyAndCollapse(elemSize, elemStart, s);
- }
-
- TclNewObj(elemPtr);
- elemPtr->bytes = s;
- elemPtr->length = elemSize;
- elemPtrs[i] = elemPtr;
- Tcl_IncrRefCount(elemPtr); /* Since list now holds ref to it. */
+ s = ckalloc((unsigned) elemSize + 1);
+ if (hasBrace) {
+ memcpy(s, elemStart, (size_t) elemSize);
+ s[elemSize] = 0;
+ } else {
+ elemSize = TclCopyAndCollapse(elemSize, elemStart, s);
}
+
+ TclNewObj(elemPtr);
+ elemPtr->bytes = s;
+ elemPtr->length = elemSize;
+ elemPtrs[i] = elemPtr;
+ Tcl_IncrRefCount(elemPtr); /* Since list now holds ref to it. */
}
+ listRepPtr->elemCount = i;
+
/*
* Free the old internalRep before setting the new one. 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 that old internalRep.
*/
- listRepPtr->elemCount = i;
listRepPtr->refCount++;
TclFreeIntRep(objPtr);
objPtr->internalRep.twoPtrValue.ptr1 = (void *) listRepPtr;