summaryrefslogtreecommitdiffstats
path: root/generic/tclCmdIL.c
diff options
context:
space:
mode:
authorKevin B Kenny <kennykb@acm.org>2011-03-01 04:16:27 (GMT)
committerKevin B Kenny <kennykb@acm.org>2011-03-01 04:16:27 (GMT)
commitb153d7d08398bacf50287f086acee27748d21799 (patch)
treefe0d74fb715de8a7a2d9ae7bfd47e54e1114fc38 /generic/tclCmdIL.c
parent7c4049a13f83930bf6a57ef889abc9e49fa414ec (diff)
parentcd34f84f42b4e64866a9177553e91417ded252a0 (diff)
downloadtcl-b153d7d08398bacf50287f086acee27748d21799.zip
tcl-b153d7d08398bacf50287f086acee27748d21799.tar.gz
tcl-b153d7d08398bacf50287f086acee27748d21799.tar.bz2
merge trunk
Diffstat (limited to 'generic/tclCmdIL.c')
-rw-r--r--generic/tclCmdIL.c143
1 files changed, 75 insertions, 68 deletions
diff --git a/generic/tclCmdIL.c b/generic/tclCmdIL.c
index 8900d14..ffb8b98 100644
--- a/generic/tclCmdIL.c
+++ b/generic/tclCmdIL.c
@@ -16,7 +16,7 @@
* See the file "license.terms" for information on usage and redistribution of
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tclCmdIL.c,v 1.184.2.2 2010/12/11 18:39:28 kennykb Exp $
+ * RCS: @(#) $Id: tclCmdIL.c,v 1.188 2011/01/01 10:49:09 dkf Exp $
*/
#include "tclInt.h"
@@ -29,13 +29,16 @@
*/
typedef struct SortElement {
- union {
+ union { /* The value that we sorting by. */
const char *strValuePtr;
long intValue;
double doubleValue;
Tcl_Obj *objValuePtr;
- } index;
- Tcl_Obj *objPtr; /* Object being sorted, or its index. */
+ } collationKey;
+ union { /* Object being sorted, or its index. */
+ Tcl_Obj *objPtr;
+ int index;
+ } payload;
struct SortElement *nextPtr;/* Next element in the list, or NULL for end
* of list. */
} SortElement;
@@ -3640,6 +3643,7 @@ Tcl_LsortObjCmd(
group = 0;
groupSize = 1;
groupOffset = 0;
+ indexPtr = NULL;
for (i = 1; i < objc-1; i++) {
if (Tcl_GetIndexFromObj(interp, objv[i], switches, "option", 0,
&index) != TCL_OK) {
@@ -3672,66 +3676,40 @@ Tcl_LsortObjCmd(
sortInfo.isIncreasing = 1;
break;
case LSORT_INDEX: {
+ int indexc, dummy;
Tcl_Obj **indexv;
- /* === START SPECIAL CASE ===
- *
- * When reviewing code flow in this function, note that from here
- * to the line a bit below (END SPECIAL CASE) the contents of the
- * indexc and indexv fields of the sortInfo structure may not be
- * matched, so jumping to the done2 label to exit is wrong.
- */
-
- if (sortInfo.indexc > 1) {
- TclStackFree(interp, sortInfo.indexv);
- }
if (i == objc-2) {
Tcl_AppendResult(interp, "\"-index\" option must be "
"followed by list index", NULL);
- return TCL_ERROR;
+ sortInfo.resultCode = TCL_ERROR;
+ goto done2;
}
-
- /*
- * Take copy to prevent shimmering problems.
- */
-
- if (TclListObjGetElements(interp, objv[i+1], &sortInfo.indexc,
+ if (TclListObjGetElements(interp, objv[i+1], &indexc,
&indexv) != TCL_OK) {
- return TCL_ERROR;
- }
- /* === END SPECIAL CASE === */
-
- switch (sortInfo.indexc) {
- case 0:
- sortInfo.indexv = NULL;
- break;
- case 1:
- sortInfo.indexv = &sortInfo.singleIndex;
- break;
- default:
- sortInfo.indexv =
- TclStackAlloc(interp, sizeof(int) * sortInfo.indexc);
- allocatedIndexVector = 1; /* Cannot use indexc field, as
- * it might be decreased by 1
- * later. */
+ sortInfo.resultCode = TCL_ERROR;
+ goto done2;
}
- /*
- * Fill the array by parsing each index. We don't know whether
- * their scale is sensible yet, but we at least perform the
- * syntactic check here.
- */
+ /*
+ * Check each of the indices for syntactic correctness. Note that
+ * we do not store the converted values here because we do not
+ * know if this is the only -index option yet and so we can't
+ * allocate any space; that happens after the scan through all the
+ * options is done.
+ */
- for (j=0 ; j<sortInfo.indexc ; j++) {
+ for (j=0 ; j<indexc ; j++) {
if (TclGetIntForIndexM(interp, indexv[j], SORTIDX_END,
- &sortInfo.indexv[j]) != TCL_OK) {
+ &dummy) != TCL_OK) {
Tcl_AppendObjToErrorInfo(interp, Tcl_ObjPrintf(
"\n (-index option item number %d)", j));
sortInfo.resultCode = TCL_ERROR;
goto done2;
}
}
- i++;
+ indexPtr = objv[i+1];
+ i++;
break;
}
case LSORT_INTEGER:
@@ -3775,6 +3753,35 @@ Tcl_LsortObjCmd(
sortInfo.sortMode = SORTMODE_ASCII_NC;
}
+ /*
+ * Now extract the -index list for real, if present. No failures are
+ * expected here; the values are all of the right type or convertible to
+ * it.
+ */
+
+ if (indexPtr) {
+ Tcl_Obj **indexv;
+
+ TclListObjGetElements(interp, indexPtr, &sortInfo.indexc, &indexv);
+ switch (sortInfo.indexc) {
+ case 0:
+ sortInfo.indexv = NULL;
+ break;
+ case 1:
+ sortInfo.indexv = &sortInfo.singleIndex;
+ break;
+ default:
+ sortInfo.indexv =
+ TclStackAlloc(interp, sizeof(int) * sortInfo.indexc);
+ allocatedIndexVector = 1; /* Cannot use indexc field, as it
+ * might be decreased by 1 later. */
+ }
+ for (j=0 ; j<sortInfo.indexc ; j++) {
+ TclGetIntForIndexM(interp, indexv[j], SORTIDX_END,
+ &sortInfo.indexv[j]);
+ }
+ }
+
listObj = objv[objc-1];
if (sortInfo.sortMode == SORTMODE_COMMAND) {
@@ -3918,7 +3925,7 @@ Tcl_LsortObjCmd(
*/
if (sortMode == SORTMODE_ASCII) {
- elementArray[i].index.strValuePtr = TclGetString(indexPtr);
+ elementArray[i].collationKey.strValuePtr = TclGetString(indexPtr);
} else if (sortMode == SORTMODE_INTEGER) {
long a;
@@ -3926,7 +3933,7 @@ Tcl_LsortObjCmd(
sortInfo.resultCode = TCL_ERROR;
goto done1;
}
- elementArray[i].index.intValue = a;
+ elementArray[i].collationKey.intValue = a;
} else if (sortInfo.sortMode == SORTMODE_REAL) {
double a;
@@ -3935,9 +3942,9 @@ Tcl_LsortObjCmd(
sortInfo.resultCode = TCL_ERROR;
goto done1;
}
- elementArray[i].index.doubleValue = a;
+ elementArray[i].collationKey.doubleValue = a;
} else {
- elementArray[i].index.objValuePtr = indexPtr;
+ elementArray[i].collationKey.objValuePtr = indexPtr;
}
/*
@@ -3946,9 +3953,9 @@ Tcl_LsortObjCmd(
*/
if (indices || group) {
- elementArray[i].objPtr = INT2PTR(idx);
+ elementArray[i].payload.index = idx;
} else {
- elementArray[i].objPtr = listObjPtrs[idx];
+ elementArray[i].payload.objPtr = listObjPtrs[idx];
}
/*
@@ -3990,7 +3997,7 @@ Tcl_LsortObjCmd(
newArray = &listRepPtr->elements;
if (group) {
for (i=0; elementPtr!=NULL ; elementPtr=elementPtr->nextPtr) {
- idx = PTR2INT(elementPtr->objPtr);
+ idx = elementPtr->payload.index;
for (j = 0; j < groupSize; j++) {
if (indices) {
objPtr = Tcl_NewIntObj(idx + j - groupOffset);
@@ -4005,13 +4012,13 @@ Tcl_LsortObjCmd(
}
} else if (indices) {
for (i=0; elementPtr != NULL ; elementPtr = elementPtr->nextPtr) {
- objPtr = Tcl_NewIntObj(PTR2INT(elementPtr->objPtr));
+ objPtr = Tcl_NewIntObj(elementPtr->payload.index);
newArray[i++] = objPtr;
Tcl_IncrRefCount(objPtr);
}
} else {
for (i=0; elementPtr != NULL ; elementPtr = elementPtr->nextPtr) {
- objPtr = elementPtr->objPtr;
+ objPtr = elementPtr->payload.objPtr;
newArray[i++] = objPtr;
Tcl_IncrRefCount(objPtr);
}
@@ -4166,25 +4173,25 @@ SortCompare(
int order = 0;
if (infoPtr->sortMode == SORTMODE_ASCII) {
- order = strcmp(elemPtr1->index.strValuePtr,
- elemPtr2->index.strValuePtr);
+ order = strcmp(elemPtr1->collationKey.strValuePtr,
+ elemPtr2->collationKey.strValuePtr);
} else if (infoPtr->sortMode == SORTMODE_ASCII_NC) {
- order = strcasecmp(elemPtr1->index.strValuePtr,
- elemPtr2->index.strValuePtr);
+ order = strcasecmp(elemPtr1->collationKey.strValuePtr,
+ elemPtr2->collationKey.strValuePtr);
} else if (infoPtr->sortMode == SORTMODE_DICTIONARY) {
- order = DictionaryCompare(elemPtr1->index.strValuePtr,
- elemPtr2->index.strValuePtr);
+ order = DictionaryCompare(elemPtr1->collationKey.strValuePtr,
+ elemPtr2->collationKey.strValuePtr);
} else if (infoPtr->sortMode == SORTMODE_INTEGER) {
long a, b;
- a = elemPtr1->index.intValue;
- b = elemPtr2->index.intValue;
+ a = elemPtr1->collationKey.intValue;
+ b = elemPtr2->collationKey.intValue;
order = ((a >= b) - (a <= b));
} else if (infoPtr->sortMode == SORTMODE_REAL) {
double a, b;
- a = elemPtr1->index.doubleValue;
- b = elemPtr2->index.doubleValue;
+ a = elemPtr1->collationKey.doubleValue;
+ b = elemPtr2->collationKey.doubleValue;
order = ((a >= b) - (a <= b));
} else {
Tcl_Obj **objv, *paramObjv[2];
@@ -4201,8 +4208,8 @@ SortCompare(
}
- objPtr1 = elemPtr1->index.objValuePtr;
- objPtr2 = elemPtr2->index.objValuePtr;
+ objPtr1 = elemPtr1->collationKey.objValuePtr;
+ objPtr2 = elemPtr2->collationKey.objValuePtr;
paramObjv[0] = objPtr1;
paramObjv[1] = objPtr2;