summaryrefslogtreecommitdiffstats
path: root/generic/tclCmdIL.c
diff options
context:
space:
mode:
Diffstat (limited to 'generic/tclCmdIL.c')
-rw-r--r--generic/tclCmdIL.c97
1 files changed, 60 insertions, 37 deletions
diff --git a/generic/tclCmdIL.c b/generic/tclCmdIL.c
index 2e68f67..70e2242 100644
--- a/generic/tclCmdIL.c
+++ b/generic/tclCmdIL.c
@@ -2307,20 +2307,22 @@ Tcl_LassignObjCmd(
Tcl_Obj **listObjv; /* The contents of the list. */
Tcl_Size listObjc; /* The length of the list. */
Tcl_Size origListObjc; /* Original length */
- int code = TCL_OK;
+ int code;
if (objc < 2) {
Tcl_WrongNumArgs(interp, 1, objv, "list ?varName ...?");
return TCL_ERROR;
}
- listCopyPtr = TclListObjCopy(interp, objv[1]);
- if (listCopyPtr == NULL) {
- return TCL_ERROR;
- }
+ listCopyPtr = TclDuplicatePureObj(objv[1]);
Tcl_IncrRefCount(listCopyPtr); /* Important! fs */
- TclListObjGetElementsM(NULL, listCopyPtr, &listObjc, &listObjv);
+ code = TclListObjGetElementsM(
+ interp, listCopyPtr, &listObjc, &listObjv);
+ if (code != TCL_OK) {
+ Tcl_DecrRefCount(listCopyPtr);
+ return code;
+ }
origListObjc = listObjc;
objc -= 2;
@@ -2446,7 +2448,7 @@ Tcl_LinsertObjCmd(
{
Tcl_Obj *listPtr;
Tcl_Size len, index;
- int result;
+ int copied = 0, result;
if (objc < 3) {
Tcl_WrongNumArgs(interp, 1, objv, "list index ?element ...?");
@@ -2479,7 +2481,8 @@ Tcl_LinsertObjCmd(
listPtr = objv[1];
if (Tcl_IsShared(listPtr)) {
- listPtr = TclListObjCopy(NULL, listPtr);
+ listPtr = TclDuplicatePureObj(listPtr);
+ copied = 1;
}
if ((objc == 4) && (index == len)) {
@@ -2487,10 +2490,19 @@ Tcl_LinsertObjCmd(
* Special case: insert one element at the end of the list.
*/
- Tcl_ListObjAppendElement(NULL, listPtr, objv[3]);
+ result = Tcl_ListObjAppendElement(NULL, listPtr, objv[3]);
+ if (result != TCL_OK) {
+ if (copied) {
+ Tcl_DecrRefCount(listPtr);
+ }
+ return result;
+ }
} else {
if (TCL_OK != Tcl_ListObjReplace(interp, listPtr, index, 0,
(objc-3), &(objv[3]))) {
+ if (copied) {
+ Tcl_DecrRefCount(listPtr);
+ }
return TCL_ERROR;
}
}
@@ -2614,7 +2626,7 @@ Tcl_LpopObjCmd(
/* Argument objects. */
{
Tcl_Size listLen;
- int result;
+ int copied = 0, result;
Tcl_Obj *elemPtr, *stored;
Tcl_Obj *listPtr, **elemPtrs;
@@ -2666,18 +2678,26 @@ Tcl_LpopObjCmd(
if (objc == 2) {
if (Tcl_IsShared(listPtr)) {
- listPtr = TclListObjCopy(NULL, listPtr);
+ listPtr = TclDuplicatePureObj(listPtr);
+ copied = 1;
}
result = Tcl_ListObjReplace(interp, listPtr, listLen - 1, 1, 0, NULL);
if (result != TCL_OK) {
+ if (copied) {
+ Tcl_DecrRefCount(listPtr);
+ }
return result;
}
Tcl_IncrRefCount(listPtr);
} else {
- listPtr = TclLsetFlat(interp, listPtr, objc-2, objv+2, NULL);
-
- if (listPtr == NULL) {
+ Tcl_Obj *newListPtr = TclLsetFlat(interp, listPtr, objc-2, objv+2, NULL);
+ if (newListPtr == NULL) {
+ if (copied) {
+ Tcl_DecrRefCount(listPtr);
+ }
return TCL_ERROR;
+ } else {
+ listPtr = newListPtr;
}
}
@@ -2799,6 +2819,7 @@ Tcl_LremoveObjCmd(
Tcl_Size i, idxc, prevIdx, first, num;
Tcl_Size *idxv, listLen;
Tcl_Obj *listObj;
+ int copied = 0, status = TCL_OK;
/*
* Parse the arguments.
@@ -2821,10 +2842,10 @@ Tcl_LremoveObjCmd(
}
idxv = (Tcl_Size *)Tcl_Alloc((objc - 2) * sizeof(*idxv));
for (i = 2; i < objc; i++) {
- if (TclGetIntForIndexM(interp, objv[i], /*endValue*/ listLen - 1,
- &idxv[i - 2]) != TCL_OK) {
- Tcl_Free(idxv);
- return TCL_ERROR;
+ status = (TclGetIntForIndexM(interp, objv[i], /*endValue*/ listLen - 1,
+ &idxv[i - 2]) != TCL_OK);
+ if (status != TCL_OK) {
+ goto done;
}
}
@@ -2842,7 +2863,8 @@ Tcl_LremoveObjCmd(
*/
if (Tcl_IsShared(listObj)) {
- listObj = TclListObjCopy(NULL, listObj);
+ listObj = TclDuplicatePureObj(listObj);
+ copied = 1;
}
num = 0;
first = listLen;
@@ -2877,18 +2899,28 @@ Tcl_LremoveObjCmd(
* and we're only ever contracting that list.
*/
- (void) Tcl_ListObjReplace(interp, listObj, first, num, 0, NULL);
+ status = Tcl_ListObjReplace(interp, listObj, first, num, 0, NULL);
+ if (status != TCL_OK) {
+ goto done;
+ }
listLen -= num;
num = 1;
first = idx;
}
}
if (num != 0) {
- (void) Tcl_ListObjReplace(interp, listObj, first, num, 0, NULL);
+ status = Tcl_ListObjReplace(interp, listObj, first, num, 0, NULL);
+ if (status != TCL_OK) {
+ if (copied) {
+ Tcl_DecrRefCount(listObj);
+ }
+ goto done;
+ }
}
- Tcl_Free(idxv);
Tcl_SetObjResult(interp, listObj);
- return TCL_OK;
+done:
+ Tcl_Free(idxv);
+ return status;
}
/*
@@ -3082,7 +3114,7 @@ Tcl_LreplaceObjCmd(
listPtr = objv[1];
if (Tcl_IsShared(listPtr)) {
- listPtr = TclListObjCopy(NULL, listPtr);
+ listPtr = TclDuplicatePureObj(listPtr);
}
/*
@@ -3095,6 +3127,7 @@ Tcl_LreplaceObjCmd(
if (TCL_OK != Tcl_ListObjReplace(interp, listPtr, first, numToDelete,
objc-4, objv+4)) {
+ Tcl_DecrRefCount(listPtr);
return TCL_ERROR;
}
@@ -4709,7 +4742,7 @@ Tcl_LsortObjCmd(
* 1675116]
*/
- listObj = TclListObjCopy(interp, listObj);
+ listObj = TclDuplicatePureObj(listObj);
if (listObj == NULL) {
sortInfo.resultCode = TCL_ERROR;
goto done;
@@ -4726,8 +4759,6 @@ Tcl_LsortObjCmd(
if (Tcl_ListObjAppendElement(interp, newCommandPtr, newObjPtr)
!= TCL_OK) {
TclDecrRefCount(newCommandPtr);
- TclDecrRefCount(listObj);
- Tcl_IncrRefCount(newObjPtr);
TclDecrRefCount(newObjPtr);
sortInfo.resultCode = TCL_ERROR;
goto done;
@@ -5067,7 +5098,7 @@ Tcl_LeditObjCmd(
}
if (Tcl_IsShared(listPtr)) {
- listPtr = TclListObjCopy(NULL, listPtr);
+ listPtr = TclDuplicatePureObj(listPtr);
createdNewObj = 1;
} else {
createdNewObj = 0;
@@ -5084,18 +5115,10 @@ Tcl_LeditObjCmd(
/*
* Tcl_ObjSetVar2 may return a value different from listPtr in the
- * presence of traces etc.. Note that finalValuePtr will always have a
- * reference count of at least 1 corresponding to the reference from the
- * var. If it is same as listPtr, then ref count will be at least 2
- * since we are incr'ing the latter below (safer when calling
- * Tcl_ObjSetVar2 which can release it in some cases). Note that we
- * leave the incrref of listPtr this late because we want to pass it as
- * unshared to Tcl_ListObjReplace above if possible.
+ * presence of traces etc.
*/
- Tcl_IncrRefCount(listPtr);
finalValuePtr =
Tcl_ObjSetVar2(interp, objv[1], NULL, listPtr, TCL_LEAVE_ERR_MSG);
- Tcl_DecrRefCount(listPtr); /* safe irrespective of createdNewObj */
if (finalValuePtr == NULL) {
return TCL_ERROR;
}