diff options
Diffstat (limited to 'generic/tclListObj.c')
-rw-r--r-- | generic/tclListObj.c | 457 |
1 files changed, 169 insertions, 288 deletions
diff --git a/generic/tclListObj.c b/generic/tclListObj.c index fa67ee6..289cf2d 100644 --- a/generic/tclListObj.c +++ b/generic/tclListObj.c @@ -18,8 +18,8 @@ */ static List * AttemptNewList(Tcl_Interp *interp, int objc, - Tcl_Obj *const objv[]); -static List * NewListIntRep(int objc, Tcl_Obj *const objv[], int p); + Tcl_Obj *CONST objv[]); +static List * NewListIntRep(int objc, Tcl_Obj *CONST objv[], int p); static void DupListInternalRep(Tcl_Obj *srcPtr, Tcl_Obj *copyPtr); static void FreeListInternalRep(Tcl_Obj *listPtr); static int SetListFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr); @@ -38,17 +38,13 @@ static void UpdateStringOfList(Tcl_Obj *listPtr); * storage to avoid an auxiliary stack. */ -const Tcl_ObjType tclListType = { +Tcl_ObjType tclListType = { "list", /* name */ FreeListInternalRep, /* freeIntRepProc */ DupListInternalRep, /* dupIntRepProc */ UpdateStringOfList, /* updateStringProc */ SetListFromAny /* setFromAnyProc */ }; - -#ifndef TCL_MIN_ELEMENT_GROWTH -#define TCL_MIN_ELEMENT_GROWTH TCL_MIN_GROWTH/sizeof(Tcl_Obj *) -#endif /* *---------------------------------------------------------------------- @@ -76,7 +72,7 @@ const Tcl_ObjType tclListType = { static List * NewListIntRep( int objc, - Tcl_Obj *const objv[], + Tcl_Obj *CONST objv[], int p) { List *listRepPtr; @@ -100,11 +96,12 @@ NewListIntRep( return NULL; } - listRepPtr = attemptckalloc(LIST_SIZE(objc)); + listRepPtr = (List *) + attemptckalloc(sizeof(List) + ((objc-1) * sizeof(Tcl_Obj *))); if (listRepPtr == NULL) { if (p) { Tcl_Panic("list creation failed: unable to alloc %u bytes", - LIST_SIZE(objc)); + (unsigned)(sizeof(List) + ((objc-1) * sizeof(Tcl_Obj *)))); } return NULL; } @@ -137,7 +134,7 @@ NewListIntRep( * Creates a list internal rep with space for objc elements. objc * must be > 0. If objv!=NULL, initializes with the first objc values * in that array. If objv==NULL, initalize list internal rep to have - * 0 elements, with space to add objc more. + * 0 elements, with space to add objc more. * * Results: * A new List struct with refCount 0 is returned. If some failure @@ -155,7 +152,7 @@ static List * AttemptNewList( Tcl_Interp *interp, int objc, - Tcl_Obj *const objv[]) + Tcl_Obj *CONST objv[]) { List *listRepPtr = NewListIntRep(objc, objv, 0); @@ -167,9 +164,8 @@ AttemptNewList( } else { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "list creation failed: unable to alloc %u bytes", - LIST_SIZE(objc))); + (unsigned)(sizeof(List) + ((objc-1) * sizeof(Tcl_Obj *))))); } - Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL); } return listRepPtr; } @@ -206,7 +202,7 @@ AttemptNewList( Tcl_Obj * Tcl_NewListObj( int objc, /* Count of objects referenced by objv. */ - Tcl_Obj *const objv[]) /* An array of pointers to Tcl objects. */ + Tcl_Obj *CONST objv[]) /* An array of pointers to Tcl objects. */ { return Tcl_DbNewListObj(objc, objv, "unknown", 0); } @@ -216,7 +212,7 @@ Tcl_NewListObj( Tcl_Obj * Tcl_NewListObj( int objc, /* Count of objects referenced by objv. */ - Tcl_Obj *const objv[]) /* An array of pointers to Tcl objects. */ + Tcl_Obj *CONST objv[]) /* An array of pointers to Tcl objects. */ { List *listRepPtr; Tcl_Obj *listPtr; @@ -277,8 +273,8 @@ Tcl_NewListObj( Tcl_Obj * Tcl_DbNewListObj( int objc, /* Count of objects referenced by objv. */ - Tcl_Obj *const objv[], /* An array of pointers to Tcl objects. */ - const char *file, /* The name of the source file calling this + Tcl_Obj *CONST objv[], /* An array of pointers to Tcl objects. */ + CONST char *file, /* The name of the source file calling this * function; used for debugging. */ int line) /* Line number in the source file; used for * debugging. */ @@ -313,8 +309,8 @@ Tcl_DbNewListObj( Tcl_Obj * Tcl_DbNewListObj( int objc, /* Count of objects referenced by objv. */ - Tcl_Obj *const objv[], /* An array of pointers to Tcl objects. */ - const char *file, /* The name of the source file calling this + Tcl_Obj *CONST objv[], /* An array of pointers to Tcl objects. */ + CONST char *file, /* The name of the source file calling this * function; used for debugging. */ int line) /* Line number in the source file; used for * debugging. */ @@ -349,7 +345,7 @@ void Tcl_SetListObj( Tcl_Obj *objPtr, /* Object whose internal rep to init. */ int objc, /* Count of objects referenced by objv. */ - Tcl_Obj *const objv[]) /* An array of pointers to Tcl objects. */ + Tcl_Obj *CONST objv[]) /* An array of pointers to Tcl objects. */ { List *listRepPtr; @@ -362,6 +358,7 @@ Tcl_SetListObj( */ TclFreeIntRep(objPtr); + objPtr->typePtr = NULL; TclInvalidateStringRep(objPtr); /* @@ -486,13 +483,16 @@ Tcl_ListObjGetElements( * * Tcl_ListObjAppendList -- * - * This function appends the elements in the list value referenced by - * elemListPtr to the list value referenced by listPtr. + * This function appends the objects in the list referenced by + * elemListPtr to the list object referenced by listPtr. If listPtr is + * not already a list object, an attempt will be made to convert it to + * one. * * Results: * The return value is normally TCL_OK. If listPtr or elemListPtr do not - * refer to list values, TCL_ERROR is returned and an error message is - * left in the interpreter's result if interp is not NULL. + * refer to list objects and they can not be converted to one, TCL_ERROR + * is returned and an error message is left in the interpreter's result + * if interp is not NULL. * * Side effects: * The reference counts of the elements in elemListPtr are incremented @@ -510,27 +510,29 @@ Tcl_ListObjAppendList( register Tcl_Obj *listPtr, /* List object to append elements to. */ Tcl_Obj *elemListPtr) /* List obj with elements to append. */ { - int objc; + int listLen, objc, result; Tcl_Obj **objv; if (Tcl_IsShared(listPtr)) { Tcl_Panic("%s called with shared object", "Tcl_ListObjAppendList"); } - /* - * Pull the elements to append from elemListPtr. - */ + result = TclListObjLength(interp, listPtr, &listLen); + if (result != TCL_OK) { + return result; + } - if (TCL_OK != TclListObjGetElements(interp, elemListPtr, &objc, &objv)) { - return TCL_ERROR; + result = TclListObjGetElements(interp, elemListPtr, &objc, &objv); + if (result != TCL_OK) { + return result; } /* - * Insert the new elements starting after the lists's last element. + * Insert objc new elements starting after the lists's last element. * Delete zero existing elements. */ - return Tcl_ListObjReplace(interp, listPtr, LIST_MAX, 0, objc, objv); + return Tcl_ListObjReplace(interp, listPtr, listLen, 0, objc, objv); } /* @@ -566,8 +568,9 @@ Tcl_ListObjAppendElement( Tcl_Obj *listPtr, /* List object to append objPtr to. */ Tcl_Obj *objPtr) /* Object to append to listPtr's list. */ { - register List *listRepPtr, *newPtr = NULL; - int numElems, numRequired, needGrow, isShared, attempt; + register List *listRepPtr; + register Tcl_Obj **elemPtrs; + int numElems, numRequired, newMax, newSize, i; if (Tcl_IsShared(listPtr)) { Tcl_Panic("%s called with shared object", "Tcl_ListObjAppendElement"); @@ -588,107 +591,52 @@ Tcl_ListObjAppendElement( listRepPtr = ListRepPtr(listPtr); numElems = listRepPtr->elemCount; numRequired = numElems + 1 ; - needGrow = (numRequired > listRepPtr->maxElemCount); - isShared = (listRepPtr->refCount > 1); - if (numRequired > LIST_MAX) { - if (interp != NULL) { - Tcl_SetObjResult(interp, Tcl_ObjPrintf( - "max length of a Tcl list (%d elements) exceeded", - LIST_MAX)); - Tcl_SetErrorCode(interp, "TCL", "MEMORY", NULL); - } - return TCL_ERROR; - } - - if (needGrow && !isShared) { - /* - * Need to grow + unshared intrep => try to realloc - */ + /* + * If there is no room in the current array of element pointers, allocate + * a new, larger array and copy the pointers to it. If the List struct is + * shared, allocate a new one. + */ - attempt = 2 * numRequired; - if (attempt <= LIST_MAX) { - newPtr = attemptckrealloc(listRepPtr, LIST_SIZE(attempt)); - } - if (newPtr == NULL) { - attempt = numRequired + 1 + TCL_MIN_ELEMENT_GROWTH; - if (attempt > LIST_MAX) { - attempt = LIST_MAX; - } - newPtr = attemptckrealloc(listRepPtr, LIST_SIZE(attempt)); - } - if (newPtr == NULL) { - attempt = numRequired; - newPtr = attemptckrealloc(listRepPtr, LIST_SIZE(attempt)); - } - if (newPtr) { - listRepPtr = newPtr; - listRepPtr->maxElemCount = attempt; - needGrow = 0; - } + if (numRequired > listRepPtr->maxElemCount){ + newMax = 2 * numRequired; + newSize = sizeof(List) + ((newMax-1) * sizeof(Tcl_Obj *)); + } else { + newMax = listRepPtr->maxElemCount; + newSize = 0; } - if (isShared || needGrow) { - Tcl_Obj **dst, **src = &listRepPtr->elements; - /* - * Either we have a shared intrep and we must copy to write, or we - * need to grow and realloc attempts failed. Attempt intrep copy. - */ - - attempt = 2 * numRequired; - newPtr = AttemptNewList(NULL, attempt, NULL); - if (newPtr == NULL) { - attempt = numRequired + 1 + TCL_MIN_ELEMENT_GROWTH; - if (attempt > LIST_MAX) { - attempt = LIST_MAX; - } - newPtr = AttemptNewList(NULL, attempt, NULL); - } - if (newPtr == NULL) { - attempt = numRequired; - newPtr = AttemptNewList(interp, attempt, NULL); - } - if (newPtr == NULL) { - /* - * All growth attempts failed; throw the error. - */ + if (listRepPtr->refCount > 1) { + List *oldListRepPtr = listRepPtr; + Tcl_Obj **oldElems; + listRepPtr = AttemptNewList(interp, newMax, NULL); + if (listRepPtr == NULL) { return TCL_ERROR; } - - dst = &newPtr->elements; - newPtr->refCount++; - newPtr->canonicalFlag = listRepPtr->canonicalFlag; - newPtr->elemCount = listRepPtr->elemCount; - - if (isShared) { - /* - * The original intrep must remain undisturbed. Copy into the new - * one and bump refcounts - */ - while (numElems--) { - *dst = *src++; - Tcl_IncrRefCount(*dst++); - } - listRepPtr->refCount--; - } else { - /* - * Old intrep to be freed, re-use refCounts. - */ - - memcpy(dst, src, (size_t) numElems * sizeof(Tcl_Obj *)); - ckfree(listRepPtr); + oldElems = &oldListRepPtr->elements; + elemPtrs = &listRepPtr->elements; + for (i=0; i<numElems; i++) { + elemPtrs[i] = oldElems[i]; + Tcl_IncrRefCount(elemPtrs[i]); } - listRepPtr = newPtr; + listRepPtr->elemCount = numElems; + listRepPtr->refCount++; + oldListRepPtr->refCount--; + listPtr->internalRep.twoPtrValue.ptr1 = (void *) listRepPtr; + } else if (newSize) { + listRepPtr = (List *) ckrealloc((char *)listRepPtr, (size_t)newSize); + listRepPtr->maxElemCount = newMax; + listPtr->internalRep.twoPtrValue.ptr1 = (void *) listRepPtr; } - listPtr->internalRep.twoPtrValue.ptr1 = listRepPtr; /* * Add objPtr to the end of listPtr's array of element pointers. Increment * the ref count for the (now shared) objPtr. */ - *(&listRepPtr->elements + listRepPtr->elemCount) = objPtr; + elemPtrs = &listRepPtr->elements; + elemPtrs[numElems] = objPtr; Tcl_IncrRefCount(objPtr); listRepPtr->elemCount++; @@ -852,7 +800,7 @@ Tcl_ListObjReplace( int first, /* Index of first element to replace. */ int count, /* Number of elements to replace. */ int objc, /* Number of objects to insert. */ - Tcl_Obj *const objv[]) /* An array of objc pointers to Tcl objects to + Tcl_Obj *CONST objv[]) /* An array of objc pointers to Tcl objects to * insert. */ { List *listRepPtr; @@ -864,10 +812,11 @@ Tcl_ListObjReplace( } if (listPtr->typePtr != &tclListType) { if (listPtr->bytes == tclEmptyStringRep) { - if (!objc) { + if (objc) { + Tcl_SetListObj(listPtr, objc, NULL); + } else { return TCL_OK; } - Tcl_SetListObj(listPtr, objc, NULL); } else { int result = SetListFromAny(interp, listPtr); @@ -900,9 +849,8 @@ Tcl_ListObjReplace( } else if (numElems < first+count || first+count < 0) { /* * The 'first+count < 0' condition here guards agains integer - * overflow in determining 'first+count'. + * overflow in determining 'first+count' */ - count = numElems - first; } @@ -956,31 +904,20 @@ Tcl_ListObjReplace( newMax = listRepPtr->maxElemCount; } - listRepPtr = AttemptNewList(NULL, newMax, NULL); + listRepPtr = AttemptNewList(interp, newMax, NULL); if (listRepPtr == NULL) { - unsigned int limit = LIST_MAX - numRequired; - unsigned int extra = numRequired - numElems - + TCL_MIN_ELEMENT_GROWTH; - int growth = (int) ((extra > limit) ? limit : extra); - - listRepPtr = AttemptNewList(NULL, numRequired + growth, NULL); - if (listRepPtr == NULL) { - listRepPtr = AttemptNewList(interp, numRequired, NULL); - if (listRepPtr == NULL) { - for (i = 0; i < objc; i++) { - /* See bug 3598580 */ + for (i = 0; i < objc; i++) { + /* See bug 3598580 */ #if TCL_MAJOR_VERSION > 8 - Tcl_DecrRefCount(objv[i]); + Tcl_DecrRefCount(objv[i]); #else - objv[i]->refCount--; + objv[i]->refCount--; #endif - } - return TCL_ERROR; - } } + return TCL_ERROR; } - listPtr->internalRep.twoPtrValue.ptr1 = listRepPtr; + listPtr->internalRep.twoPtrValue.ptr1 = (void *) listRepPtr; listRepPtr->refCount++; elemPtrs = &listRepPtr->elements; @@ -1034,7 +971,7 @@ Tcl_ListObjReplace( (size_t) numAfterLast * sizeof(Tcl_Obj *)); } - ckfree(oldListRepPtr); + ckfree((char *) oldListRepPtr); } } @@ -1094,6 +1031,8 @@ TclLindexList( { int index; /* Index into the list. */ + Tcl_Obj **indices = NULL; /* Array of list indices. */ + int indexCount = -1; /* Size of the array of list indices. */ Tcl_Obj *indexListCopy; /* @@ -1133,19 +1072,8 @@ TclLindexList( return TclLindexFlat(interp, listPtr, 1, &argPtr); } - if (indexListCopy->typePtr == &tclListType) { - List *listRepPtr = ListRepPtr(indexListCopy); - - 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); - } + TclListObjGetElements(NULL, indexListCopy, &indexCount, &indices); + listPtr = TclLindexFlat(interp, listPtr, indexCount, indices); Tcl_DecrRefCount(indexListCopy); return listPtr; } @@ -1327,8 +1255,8 @@ TclLsetList( * * Results: * Returns the new value of the list variable, or NULL if an error - * occurred. The returned object includes one reference count for the - * pointer returned. + * occurred. The returned object includes one reference count for + * the pointer returned. * * Side effects: * On entry, the reference count of the variable value does not reflect @@ -1370,12 +1298,12 @@ TclLsetFlat( /* Index args. */ Tcl_Obj *valuePtr) /* Value arg to 'lset'. */ { - int index, result, len; + int index, result; Tcl_Obj *subListPtr, *retValuePtr, *chainPtr; /* - * If there are no indices, simply return the new value. (Without - * indices, [lset] is a synonym for [set]. + * If there are no indices, simply return the new value. + * (Without indices, [lset] is a synonym for [set]. */ if (indexCount == 0) { @@ -1384,14 +1312,14 @@ TclLsetFlat( } /* - * If the list is shared, make a copy we can modify (copy-on-write). We - * use Tcl_DuplicateObj() instead of TclListObjCopy() for a few reasons: - * 1) we have not yet confirmed listPtr is actually a list; 2) We make a - * verbatim copy of any existing string rep, and when we combine that with - * the delayed invalidation of string reps of modified Tcl_Obj's - * implemented below, the outcome is that any error condition that causes - * this routine to return NULL, will leave the string rep of listPtr and - * all elements to be unchanged. + * If the list is shared, make a copy we can modify (copy-on-write). + * We use Tcl_DuplicateObj() instead of TclListObjCopy() for a few + * reasons: 1) we have not yet confirmed listPtr is actually a list; + * 2) We make a verbatim copy of any existing string rep, and when + * we combine that with the delayed invalidation of string reps of + * modified Tcl_Obj's implemented below, the outcome is that any + * error condition that causes this routine to return NULL, will + * leave the string rep of listPtr and all elements to be unchanged. */ subListPtr = Tcl_IsShared(listPtr) ? Tcl_DuplicateObj(listPtr) : listPtr; @@ -1403,25 +1331,21 @@ TclLsetFlat( retValuePtr = subListPtr; chainPtr = NULL; - result = TCL_OK; /* - * Loop through all the index arguments, and for each one dive into the - * appropriate sublist. + * Loop through all the index arguments, and for each one dive + * into the appropriate sublist. */ do { int elemCount; Tcl_Obj *parentList, **elemPtrs; - /* - * Check for the possible error conditions... - */ - + /* Check for the possible error conditions... */ + result = TCL_ERROR; if (TclListObjGetElements(interp, subListPtr, &elemCount, &elemPtrs) != TCL_OK) { /* ...the sublist we're indexing into isn't a list at all. */ - result = TCL_ERROR; break; } @@ -1429,42 +1353,35 @@ TclLsetFlat( * WARNING: the macro TclGetIntForIndexM is not safe for * post-increments, avoid '*indexArray++' here. */ - + if (TclGetIntForIndexM(interp, *indexArray, elemCount - 1, &index) != TCL_OK) { /* ...the index we're trying to use isn't an index at all. */ - result = TCL_ERROR; indexArray++; break; } indexArray++; - if (index < 0 || index > elemCount) { + if (index < 0 || index >= elemCount) { /* ...the index points outside the sublist. */ if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_NewStringObj("list index out of range", -1)); - Tcl_SetErrorCode(interp, "TCL", "OPERATION", "LSET", - "BADINDEX", NULL); } - result = TCL_ERROR; break; } /* - * No error conditions. As long as we're not yet on the last index, - * determine the next sublist for the next pass through the loop, and - * take steps to make sure it is an unshared copy, as we intend to - * modify it. + * No error conditions. As long as we're not yet on the last + * index, determine the next sublist for the next pass through + * the loop, and take steps to make sure it is an unshared copy, + * as we intend to modify it. */ + result = TCL_OK; if (--indexCount) { parentList = subListPtr; - if (index == elemCount) { - subListPtr = Tcl_NewObj(); - } else { - subListPtr = elemPtrs[index]; - } + subListPtr = elemPtrs[index]; if (Tcl_IsShared(subListPtr)) { subListPtr = Tcl_DuplicateObj(subListPtr); } @@ -1474,91 +1391,73 @@ TclLsetFlat( * we know to be unshared. This call will also deal with the * situation where parentList shares its intrep with other * Tcl_Obj's. Dealing with the shared intrep case can cause - * subListPtr to become shared again, so detect that case and make - * and store another copy. + * subListPtr to become shared again, so detect that case and + * make and store another copy. */ - if (index == elemCount) { - Tcl_ListObjAppendElement(NULL, parentList, subListPtr); - } else { - TclListObjSetElement(NULL, parentList, index, subListPtr); - } + TclListObjSetElement(NULL, parentList, index, subListPtr); if (Tcl_IsShared(subListPtr)) { subListPtr = Tcl_DuplicateObj(subListPtr); TclListObjSetElement(NULL, parentList, index, subListPtr); } /* - * The TclListObjSetElement() calls do not spoil the string rep of - * parentList, and that's fine for now, since all we've done so - * far is replace a list element with an unshared copy. The list - * value remains the same, so the string rep. is still valid, and - * unchanged, which is good because if this whole routine returns - * NULL, we'd like to leave no change to the value of the lset - * variable. Later on, when we set valuePtr in its proper place, - * then all containing lists will have their values changed, and - * will need their string reps spoiled. We maintain a list of all - * those Tcl_Obj's (via a little intrep surgery) so we can spoil - * them at that time. + * The TclListObjSetElement() calls do not spoil the string + * rep of parentList, and that's fine for now, since all we've + * done so far is replace a list element with an unshared copy. + * The list value remains the same, so the string rep. is still + * valid, and unchanged, which is good because if this whole + * routine returns NULL, we'd like to leave no change to the + * value of the lset variable. Later on, when we set valuePtr + * in its proper place, then all containing lists will have + * their values changed, and will need their string reps spoiled. + * We maintain a list of all those Tcl_Obj's (via a little intrep + * surgery) so we can spoil them at that time. */ - parentList->internalRep.twoPtrValue.ptr2 = chainPtr; + parentList->internalRep.twoPtrValue.ptr2 = (void *) chainPtr; chainPtr = parentList; } } while (indexCount > 0); /* - * Either we've detected and error condition, and exited the loop with - * result == TCL_ERROR, or we've successfully reached the last index, and - * we're ready to store valuePtr. In either case, we need to clean up our - * string spoiling list of Tcl_Obj's. + * Either we've detected and error condition, and exited the loop + * with result == TCL_ERROR, or we've successfully reached the last + * index, and we're ready to store valuePtr. In either case, we + * need to clean up our string spoiling list of Tcl_Obj's. */ while (chainPtr) { Tcl_Obj *objPtr = chainPtr; if (result == TCL_OK) { + /* - * We're going to store valuePtr, so spoil string reps of all - * containing lists. + * We're going to store valuePtr, so spoil string reps + * of all containing lists. */ TclInvalidateStringRep(objPtr); } - /* - * Clear away our intrep surgery mess. - */ - - chainPtr = objPtr->internalRep.twoPtrValue.ptr2; + /* Clear away our intrep surgery mess */ + chainPtr = (Tcl_Obj *) objPtr->internalRep.twoPtrValue.ptr2; objPtr->internalRep.twoPtrValue.ptr2 = NULL; } if (result != TCL_OK) { - /* - * Error return; message is already in interp. Clean up any excess - * memory. + /* + * Error return; message is already in interp. Clean up + * any excess memory. */ - if (retValuePtr != listPtr) { Tcl_DecrRefCount(retValuePtr); } return NULL; } - /* - * Store valuePtr in proper sublist and return. The -1 is to avoid a - * compiler warning (not a problem because we checked that we have a - * proper list - or something convertible to one - above). - */ - - len = -1; - TclListObjLength(NULL, subListPtr, &len); - if (index == len) { - Tcl_ListObjAppendElement(NULL, subListPtr, valuePtr); - } else { - TclListObjSetElement(NULL, subListPtr, index, valuePtr); - } + /* Store valuePtr in proper sublist and return */ + TclListObjSetElement(NULL, subListPtr, index, valuePtr); TclInvalidateStringRep(subListPtr); Tcl_IncrRefCount(retValuePtr); return retValuePtr; @@ -1622,8 +1521,6 @@ TclListObjSetElement( if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_NewStringObj("list index out of range", -1)); - Tcl_SetErrorCode(interp, "TCL", "OPERATION", "LSET", - "BADINDEX", NULL); } return TCL_ERROR; } @@ -1635,6 +1532,7 @@ TclListObjSetElement( listRepPtr = ListRepPtr(listPtr); elemCount = listRepPtr->elemCount; + elemPtrs = &listRepPtr->elements; /* * Ensure that the index is in bounds. @@ -1644,8 +1542,6 @@ TclListObjSetElement( if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_NewStringObj("list index out of range", -1)); - Tcl_SetErrorCode(interp, "TCL", "OPERATION", "LSET", "BADINDEX", - NULL); } return TCL_ERROR; } @@ -1655,30 +1551,25 @@ TclListObjSetElement( */ if (listRepPtr->refCount > 1) { - Tcl_Obj **dst, **src = &listRepPtr->elements; - List *newPtr = AttemptNewList(NULL, listRepPtr->maxElemCount, NULL); + List *oldListRepPtr = listRepPtr; + Tcl_Obj **oldElemPtrs = elemPtrs; + int i; - if (newPtr == NULL) { - newPtr = AttemptNewList(interp, elemCount, NULL); - if (newPtr == NULL) { - return TCL_ERROR; - } + listRepPtr = AttemptNewList(interp, listRepPtr->maxElemCount, NULL); + if (listRepPtr == NULL) { + return TCL_ERROR; } - newPtr->refCount++; - newPtr->elemCount = elemCount; - newPtr->canonicalFlag = listRepPtr->canonicalFlag; - - dst = &newPtr->elements; - while (elemCount--) { - *dst = *src++; - Tcl_IncrRefCount(*dst++); + listRepPtr->canonicalFlag = oldListRepPtr->canonicalFlag; + elemPtrs = &listRepPtr->elements; + for (i=0; i < elemCount; i++) { + elemPtrs[i] = oldElemPtrs[i]; + Tcl_IncrRefCount(elemPtrs[i]); } - - listRepPtr->refCount--; - - listPtr->internalRep.twoPtrValue.ptr1 = listRepPtr = newPtr; + listRepPtr->refCount++; + listRepPtr->elemCount = elemCount; + listPtr->internalRep.twoPtrValue.ptr1 = (void *) listRepPtr; + oldListRepPtr->refCount--; } - elemPtrs = &listRepPtr->elements; /* * Add a reference to the new list element. @@ -1726,14 +1617,14 @@ FreeListInternalRep( { List *listRepPtr = ListRepPtr(listPtr); - if (listRepPtr->refCount-- <= 1) { + if (--listRepPtr->refCount <= 0) { Tcl_Obj **elemPtrs = &listRepPtr->elements; int i, numElems = listRepPtr->elemCount; for (i = 0; i < numElems; i++) { Tcl_DecrRefCount(elemPtrs[i]); } - ckfree(listRepPtr); + ckfree((char *) listRepPtr); } listPtr->typePtr = NULL; @@ -1845,23 +1736,19 @@ SetListFromAny( */ estCount = TclMaxListLength(nextElem, length, &limit); - estCount += (estCount == 0); /* Smallest list struct holds 1 - * element. */ + estCount += (estCount == 0); /* Smallest List struct holds 1 element. */ listRepPtr = AttemptNewList(interp, estCount, NULL); if (listRepPtr == NULL) { return TCL_ERROR; } elemPtrs = &listRepPtr->elements; - /* - * Each iteration, parse and store a list element. - */ - + /* Each iteration, parse and store a list element */ while (nextElem < limit) { const char *elemStart; int elemSize, literal; - if (TCL_OK != TclFindElement(interp, nextElem, limit - nextElem, + if (TCL_OK != TclFindElement(interp, nextElem, (limit - nextElem), &elemStart, &nextElem, &elemSize, &literal)) { while (--elemPtrs >= &listRepPtr->elements) { Tcl_DecrRefCount(*elemPtrs); @@ -1930,8 +1817,7 @@ UpdateStringOfList( List *listRepPtr = ListRepPtr(listPtr); int numElems = listRepPtr->elemCount; int i, length, bytesNeeded = 0; - const char *elem; - char *dst; + char *elem, *dst; Tcl_Obj **elemPtrs; /* @@ -1942,9 +1828,7 @@ UpdateStringOfList( listRepPtr->canonicalFlag = 1; - /* - * Handle empty list case first, so rest of the routine is simpler. - */ + /* Handle empty list case first, so rest of the routine is simpler */ if (numElems == 0) { listPtr->bytes = tclEmptyStringRep; @@ -1959,15 +1843,12 @@ UpdateStringOfList( if (numElems <= LOCAL_SIZE) { flagPtr = localFlags; } else { - /* - * We know numElems <= LIST_MAX, so this is safe. - */ - - flagPtr = ckalloc(numElems * sizeof(int)); + /* We know numElems <= LIST_MAX, so this is safe. */ + flagPtr = (int *) ckalloc((unsigned) numElems * sizeof(int)); } elemPtrs = &listRepPtr->elements; for (i = 0; i < numElems; i++) { - flagPtr[i] = (i ? TCL_DONT_QUOTE_HASH : 0); + flagPtr[i] = ( i ? TCL_DONT_QUOTE_HASH : 0 ); elem = TclGetStringFromObj(elemPtrs[i], &length); bytesNeeded += TclScanElement(elem, length, flagPtr+i); if (bytesNeeded < 0) { @@ -1984,10 +1865,10 @@ UpdateStringOfList( */ listPtr->length = bytesNeeded - 1; - listPtr->bytes = ckalloc(bytesNeeded); + listPtr->bytes = ckalloc((unsigned) bytesNeeded); dst = listPtr->bytes; for (i = 0; i < numElems; i++) { - flagPtr[i] |= (i ? TCL_DONT_QUOTE_HASH : 0); + flagPtr[i] |= ( i ? TCL_DONT_QUOTE_HASH : 0 ); elem = TclGetStringFromObj(elemPtrs[i], &length); dst += TclConvertElement(elem, length, dst, flagPtr[i]); *dst++ = ' '; @@ -1995,7 +1876,7 @@ UpdateStringOfList( listPtr->bytes[listPtr->length] = '\0'; if (flagPtr != localFlags) { - ckfree(flagPtr); + ckfree((char *) flagPtr); } } |