diff options
-rw-r--r-- | ChangeLog | 7 | ||||
-rw-r--r-- | generic/tclListObj.c | 162 |
2 files changed, 63 insertions, 106 deletions
@@ -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; |