summaryrefslogtreecommitdiffstats
path: root/generic/tclCmdIL.c
diff options
context:
space:
mode:
authorjan.nijtmans <nijtmans@users.sourceforge.net>2019-05-10 16:35:53 (GMT)
committerjan.nijtmans <nijtmans@users.sourceforge.net>2019-05-10 16:35:53 (GMT)
commit8ffde10c063dd49dd207d2c8cf8b09e4487edf18 (patch)
tree103b667a0137ede85b2de0abd509bd7a12e87cd9 /generic/tclCmdIL.c
parentd50da922b1c1a3043e6ee9f24282a638ee143b48 (diff)
parentb1139d3d2099aad8ad1981deaa0f689e1b4c322a (diff)
downloadtcl-8ffde10c063dd49dd207d2c8cf8b09e4487edf18.zip
tcl-8ffde10c063dd49dd207d2c8cf8b09e4487edf18.tar.gz
tcl-8ffde10c063dd49dd207d2c8cf8b09e4487edf18.tar.bz2
Merge 8.7
Diffstat (limited to 'generic/tclCmdIL.c')
-rw-r--r--generic/tclCmdIL.c171
1 files changed, 154 insertions, 17 deletions
diff --git a/generic/tclCmdIL.c b/generic/tclCmdIL.c
index a1a7f3e..c11534e 100644
--- a/generic/tclCmdIL.c
+++ b/generic/tclCmdIL.c
@@ -56,7 +56,7 @@ typedef int (*SortMemCmpFn_t) (const void *, const void *, size_t);
* The following structure is used to pass this information.
*/
-typedef struct SortInfo {
+typedef struct {
int isIncreasing; /* Nonzero means sort in increasing order. */
int sortMode; /* The sort mode. One of SORTMODE_* values
* defined below. */
@@ -566,7 +566,7 @@ InfoBodyCmd(
* the object do not invalidate the internal rep.
*/
- bytes = Tcl_GetStringFromObj(procPtr->bodyPtr, &numBytes);
+ bytes = TclGetStringFromObj(procPtr->bodyPtr, &numBytes);
Tcl_SetObjResult(interp, Tcl_NewStringObj(bytes, numBytes));
return TCL_OK;
}
@@ -1047,7 +1047,7 @@ InfoErrorStackCmd(
target = interp;
if (objc == 2) {
- target = Tcl_GetSlave(interp, Tcl_GetString(objv[1]));
+ target = Tcl_GetSlave(interp, TclGetString(objv[1]));
if (target == NULL) {
return TCL_ERROR;
}
@@ -2155,7 +2155,7 @@ InfoCmdTypeCmd(
Tcl_WrongNumArgs(interp, 1, objv, "commandName");
return TCL_ERROR;
}
- command = Tcl_FindCommand(interp, Tcl_GetString(objv[1]), NULL,
+ command = Tcl_FindCommand(interp, TclGetString(objv[1]), NULL,
TCL_LEAVE_ERR_MSG);
if (command == NULL) {
return TCL_ERROR;
@@ -2231,7 +2231,7 @@ Tcl_JoinObjCmd(
joinObjPtr = (objc == 2) ? Tcl_NewStringObj(" ", 1) : objv[2];
Tcl_IncrRefCount(joinObjPtr);
- (void) Tcl_GetStringFromObj(joinObjPtr, &length);
+ (void) TclGetStringFromObj(joinObjPtr, &length);
if (length == 0) {
resObjPtr = TclStringCat(interp, listLen, elemPtrs, 0);
} else {
@@ -2584,7 +2584,7 @@ Tcl_LpopObjCmd(
/* Argument objects. */
{
int listLen, result;
- Tcl_Obj *elemPtr;
+ Tcl_Obj *elemPtr, *stored;
Tcl_Obj *listPtr, **elemPtrs;
if (objc < 2) {
@@ -2622,6 +2622,7 @@ Tcl_LpopObjCmd(
/*
* Second, remove the element.
+ * TclLsetFlat adds a ref count which is handled.
*/
if (objc == 2) {
@@ -2632,6 +2633,7 @@ Tcl_LpopObjCmd(
if (result != TCL_OK) {
return result;
}
+ Tcl_IncrRefCount(listPtr);
} else {
listPtr = TclLsetFlat(interp, listPtr, objc-2, objv+2, NULL);
@@ -2640,8 +2642,9 @@ Tcl_LpopObjCmd(
}
}
- listPtr = Tcl_ObjSetVar2(interp, objv[1], NULL, listPtr, TCL_LEAVE_ERR_MSG);
- if (listPtr == NULL) {
+ stored = Tcl_ObjSetVar2(interp, objv[1], NULL, listPtr, TCL_LEAVE_ERR_MSG);
+ Tcl_DecrRefCount(listPtr);
+ if (stored == NULL) {
return TCL_ERROR;
}
@@ -2704,6 +2707,140 @@ Tcl_LrangeObjCmd(
/*
*----------------------------------------------------------------------
*
+ * Tcl_LremoveObjCmd --
+ *
+ * This procedure is invoked to process the "lremove" Tcl command. See the
+ * user documentation for details on what it does.
+ *
+ * Results:
+ * A standard Tcl object result.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+static int
+LremoveIndexCompare(
+ const void *el1Ptr,
+ const void *el2Ptr)
+{
+ int idx1 = *((const int *) el1Ptr);
+ int idx2 = *((const int *) el2Ptr);
+
+ /*
+ * This will put the larger element first.
+ */
+
+ return (idx1 < idx2) ? 1 : (idx1 > idx2) ? -1 : 0;
+}
+
+int
+Tcl_LremoveObjCmd(
+ ClientData notUsed, /* Not used. */
+ Tcl_Interp *interp, /* Current interpreter. */
+ int objc, /* Number of arguments. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
+{
+ int i, idxc;
+ int listLen, *idxv, prevIdx, first, num;
+ Tcl_Obj *listObj;
+
+ /*
+ * Parse the arguments.
+ */
+
+ if (objc < 2) {
+ Tcl_WrongNumArgs(interp, 1, objv, "list ?index ...?");
+ return TCL_ERROR;
+ }
+
+ listObj = objv[1];
+ if (TclListObjLength(interp, listObj, &listLen) != TCL_OK) {
+ return TCL_ERROR;
+ }
+
+ idxc = objc - 2;
+ if (idxc == 0) {
+ Tcl_SetObjResult(interp, listObj);
+ return TCL_OK;
+ }
+ idxv = ckalloc((objc - 2) * sizeof(int));
+ for (i = 2; i < objc; i++) {
+ if (TclGetIntForIndexM(interp, objv[i], /*endValue*/ listLen - 1,
+ &idxv[i - 2]) != TCL_OK) {
+ ckfree(idxv);
+ return TCL_ERROR;
+ }
+ }
+
+ /*
+ * Sort the indices, large to small so that when we remove an index we
+ * don't change the indices still to be processed.
+ */
+
+ if (idxc > 1) {
+ qsort(idxv, idxc, sizeof(int), LremoveIndexCompare);
+ }
+
+ /*
+ * Make our working copy, then do the actual removes piecemeal.
+ */
+
+ if (Tcl_IsShared(listObj)) {
+ listObj = TclListObjCopy(NULL, listObj);
+ }
+ num = 0;
+ first = listLen;
+ for (i = 0, prevIdx = -1 ; i < idxc ; i++) {
+ int idx = idxv[i];
+
+ /*
+ * Repeated index and sanity check.
+ */
+
+ if (idx == prevIdx) {
+ continue;
+ }
+ prevIdx = idx;
+ if (idx < 0 || idx >= listLen) {
+ continue;
+ }
+
+ /*
+ * Coalesce adjacent removes to reduce the number of copies.
+ */
+
+ if (num == 0) {
+ num = 1;
+ first = idx;
+ } else if (idx + 1 == first) {
+ num++;
+ first = idx;
+ } else {
+ /*
+ * Note that this operation can't fail now; we know we have a list
+ * and we're only ever contracting that list.
+ */
+
+ (void) Tcl_ListObjReplace(interp, listObj, first, num, 0, NULL);
+ listLen -= num;
+ num = 1;
+ first = idx;
+ }
+ }
+ if (num != 0) {
+ (void) Tcl_ListObjReplace(interp, listObj, first, num, 0, NULL);
+ }
+ ckfree(idxv);
+ Tcl_SetObjResult(interp, listObj);
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
* Tcl_LrepeatObjCmd --
*
* This procedure is invoked to process the "lrepeat" Tcl command. See
@@ -2864,7 +3001,7 @@ Tcl_LreplaceObjCmd(
return result;
}
- if (first < 0) {
+ if (first == TCL_INDEX_NONE) {
first = 0;
}
if (first > listLen) {
@@ -3243,10 +3380,10 @@ Tcl_LsearchObjCmd(
TCL_INDEX_NONE, &encoded) != TCL_OK) {
result = TCL_ERROR;
}
- if (encoded == TCL_INDEX_NONE) {
+ if (encoded == (int)TCL_INDEX_NONE) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"index \"%s\" cannot select an element "
- "from any list", Tcl_GetString(indices[j])));
+ "from any list", TclGetString(indices[j])));
Tcl_SetErrorCode(interp, "TCL", "VALUE", "INDEX"
"OUTOFRANGE", NULL);
result = TCL_ERROR;
@@ -3376,8 +3513,8 @@ Tcl_LsearchObjCmd(
if (result != TCL_OK) {
goto done;
}
- if (start < 0) {
- start = 0;
+ if (start == TCL_INDEX_NONE) {
+ start = TCL_INDEX_START;
}
/*
@@ -3960,10 +4097,10 @@ Tcl_LsortObjCmd(
int result = TclIndexEncode(interp, indexv[j],
TCL_INDEX_NONE, TCL_INDEX_NONE, &encoded);
- if ((result == TCL_OK) && (encoded == TCL_INDEX_NONE)) {
+ if ((result == TCL_OK) && (encoded == (int)TCL_INDEX_NONE)) {
Tcl_SetObjResult(interp, Tcl_ObjPrintf(
"index \"%s\" cannot select an element "
- "from any list", Tcl_GetString(indexv[j])));
+ "from any list", TclGetString(indexv[j])));
Tcl_SetErrorCode(interp, "TCL", "VALUE", "INDEX"
"OUTOFRANGE", NULL);
result = TCL_ERROR;
@@ -4182,7 +4319,7 @@ Tcl_LsortObjCmd(
elementArray = ckalloc(length * sizeof(SortElement));
- for (i=0; i < length; i++){
+ for (i=0; i < length; i++) {
idx = groupSize * i + groupOffset;
if (indexc) {
/*
@@ -4720,7 +4857,7 @@ SelectObjFromSublist(
return NULL;
}
if (currentObj == NULL) {
- if (index == TCL_INDEX_NONE) {
+ if (index == (int)TCL_INDEX_NONE) {
index = TCL_INDEX_END - infoPtr->indexv[i];
Tcl_SetObjResult(infoPtr->interp, Tcl_ObjPrintf(
"element end-%d missing from sublist \"%s\"",