Attachment "cmdIL.diff" to
ticket [1856994fff]
added by
msofer
2007-12-23 23:40:39.
Index: generic/tclCmdIL.c
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclCmdIL.c,v
retrieving revision 1.132
diff -u -r1.132 tclCmdIL.c
--- generic/tclCmdIL.c 22 Dec 2007 21:50:52 -0000 1.132
+++ generic/tclCmdIL.c 23 Dec 2007 16:34:26 -0000
@@ -29,6 +29,12 @@
*/
typedef struct SortElement {
+ union {
+ char *strValuePtr;
+ long intValue;
+ double doubleValue;
+ Tcl_Obj *objValuePtr;
+ } index;
Tcl_Obj *objPtr; /* Object being sorted. */
int count; /* Number of same elements in list. */
struct SortElement *nextPtr;/* Next element in the list, or NULL for end
@@ -54,8 +60,6 @@
int isIncreasing; /* Nonzero means sort in increasing order. */
int sortMode; /* The sort mode. One of SORTMODE_* values
* defined below. */
- SortStrCmpFn_t strCmpFn; /* Basic string compare command (used with
- * ASCII mode). */
Tcl_Obj *compareCmdPtr; /* The Tcl comparison command when sortMode is
* SORTMODE_COMMAND. Pre-initialized to hold
* base of command. */
@@ -84,6 +88,7 @@
#define SORTMODE_REAL 2
#define SORTMODE_COMMAND 3
#define SORTMODE_DICTIONARY 4
+#define SORTMODE_ASCII_NC 8
/*
* Magic values for the index field of the SortInfo structure. Note that the
@@ -139,7 +144,7 @@
static SortElement * MergeSort(SortElement *headPt, SortInfo *infoPtr);
static SortElement * MergeLists(SortElement *leftPtr, SortElement *rightPtr,
SortInfo *infoPtr);
-static int SortCompare(Tcl_Obj *firstPtr, Tcl_Obj *second,
+static int SortCompare(SortElement *firstPtr, SortElement *second,
SortInfo *infoPtr);
static Tcl_Obj * SelectObjFromSublist(Tcl_Obj *firstPtr,
SortInfo *infoPtr);
@@ -3421,8 +3426,8 @@
int objc, /* Number of arguments. */
Tcl_Obj *CONST objv[]) /* Argument values. */
{
- int i, index, unique, indices, length;
- Tcl_Obj *resultPtr, *cmdPtr, **listObjPtrs, *listObj;
+ int i, index, unique, indices, length, nocase = 0;
+ Tcl_Obj *resultPtr, *cmdPtr, **listObjPtrs, *listObj, *indexPtr;
SortElement *elementArray, *elementPtr;
SortInfo sortInfo; /* Information about this sort that needs to
* be passed to the comparison function. */
@@ -3447,7 +3452,6 @@
sortInfo.isIncreasing = 1;
sortInfo.sortMode = SORTMODE_ASCII;
- sortInfo.strCmpFn = strcmp;
sortInfo.indexv = NULL;
sortInfo.indexc = 0;
sortInfo.interp = interp;
@@ -3544,7 +3548,7 @@
sortInfo.sortMode = SORTMODE_INTEGER;
break;
case LSORT_NOCASE:
- sortInfo.strCmpFn = strcasecmp;
+ nocase = 1;
break;
case LSORT_REAL:
sortInfo.sortMode = SORTMODE_REAL;
@@ -3557,6 +3561,10 @@
break;
}
}
+ if (nocase && (sortInfo.sortMode == SORTMODE_ASCII)) {
+ sortInfo.sortMode = SORTMODE_ASCII_NC;
+ }
+
listObj = objv[objc-1];
if (sortInfo.sortMode == SORTMODE_COMMAND) {
@@ -3608,11 +3616,80 @@
elementArray = (SortElement *)
TclStackAlloc(interp, length * sizeof(SortElement));
- for (i=0; i < length; i++){
- elementArray[i].objPtr = listObjPtrs[i];
- elementArray[i].count = 0;
- elementArray[i].nextPtr = &elementArray[i+1];
+ if ((sortInfo.sortMode == SORTMODE_ASCII)
+ || (sortInfo.sortMode == SORTMODE_ASCII_NC)
+ || (sortInfo.sortMode == SORTMODE_DICTIONARY)) {
+ for (i=0; i < length; i++){
+ if (sortInfo.indexc != 0) {
+ indexPtr = SelectObjFromSublist(listObjPtrs[i], &sortInfo);
+ if (sortInfo.resultCode != TCL_OK) {
+ goto done1;
+ }
+ } else {
+ indexPtr = listObjPtrs[i];
+ }
+ elementArray[i].index.strValuePtr = TclGetString(indexPtr);
+ elementArray[i].objPtr = listObjPtrs[i];
+ elementArray[i].count = 0;
+ elementArray[i].nextPtr = &elementArray[i+1];
+ }
+ } else if (sortInfo.sortMode == SORTMODE_INTEGER) {
+ for (i=0; i < length; i++){
+ long a;
+ if (sortInfo.indexc != 0) {
+ indexPtr = SelectObjFromSublist(listObjPtrs[i], &sortInfo);
+ if (sortInfo.resultCode != TCL_OK) {
+ goto done1;
+ }
+ } else {
+ indexPtr = listObjPtrs[i];
+ }
+ if (TclGetLongFromObj(sortInfo.interp, indexPtr, &a) != TCL_OK) {
+ sortInfo.resultCode = TCL_ERROR;
+ goto done1;
+ }
+ elementArray[i].index.intValue = a;
+ elementArray[i].objPtr = listObjPtrs[i];
+ elementArray[i].count = 0;
+ elementArray[i].nextPtr = &elementArray[i+1];
+ }
+ } else if (sortInfo.sortMode == SORTMODE_REAL) {
+ for (i=0; i < length; i++){
+ double a;
+ if (sortInfo.indexc != 0) {
+ indexPtr = SelectObjFromSublist(listObjPtrs[i], &sortInfo);
+ if (sortInfo.resultCode != TCL_OK) {
+ goto done1;
+ }
+ } else {
+ indexPtr = listObjPtrs[i];
+ }
+ if (Tcl_GetDoubleFromObj(sortInfo.interp, indexPtr, &a) != TCL_OK) {
+ sortInfo.resultCode = TCL_ERROR;
+ goto done1;
+ }
+ elementArray[i].index.doubleValue = a;
+ elementArray[i].objPtr = listObjPtrs[i];
+ elementArray[i].count = 0;
+ elementArray[i].nextPtr = &elementArray[i+1];
+ }
+ } else {
+ for (i=0; i < length; i++){
+ if (sortInfo.indexc != 0) {
+ indexPtr = SelectObjFromSublist(listObjPtrs[i], &sortInfo);
+ if (sortInfo.resultCode != TCL_OK) {
+ goto done1;
+ }
+ } else {
+ indexPtr = listObjPtrs[i];
+ }
+ elementArray[i].index.objValuePtr = indexPtr;
+ elementArray[i].objPtr = listObjPtrs[i];
+ elementArray[i].count = 0;
+ elementArray[i].nextPtr = &elementArray[i+1];
+ }
}
+
elementArray[length-1].nextPtr = NULL;
elementPtr = MergeSort(elementArray, &sortInfo);
if (sortInfo.resultCode == TCL_OK) {
@@ -3657,6 +3734,8 @@
listRepPtr->elemCount = i;
Tcl_SetObjResult(interp, resultPtr);
}
+
+ done1:
TclStackFree(interp, elementArray);
done:
@@ -3760,7 +3839,7 @@
if (rightPtr == NULL) {
return leftPtr;
}
- cmp = SortCompare(leftPtr->objPtr, rightPtr->objPtr, infoPtr);
+ cmp = SortCompare(leftPtr, rightPtr, infoPtr);
if (cmp > 0) {
tailPtr = rightPtr;
rightPtr = rightPtr->nextPtr;
@@ -3773,7 +3852,7 @@
}
headPtr = tailPtr;
while ((leftPtr != NULL) && (rightPtr != NULL)) {
- cmp = SortCompare(leftPtr->objPtr, rightPtr->objPtr, infoPtr);
+ cmp = SortCompare(leftPtr, rightPtr, infoPtr);
if (cmp > 0) {
tailPtr->nextPtr = rightPtr;
tailPtr = rightPtr;
@@ -3817,7 +3896,7 @@
static int
SortCompare(
- Tcl_Obj *objPtr1, Tcl_Obj *objPtr2,
+ SortElement *elemPtr1, SortElement *elemPtr2,
/* Values to be compared. */
SortInfo *infoPtr) /* Information passed from the top-level
* "lsort" command. */
@@ -3834,32 +3913,20 @@
return order;
}
- if (infoPtr->indexc != 0) {
- objPtr1 = SelectObjFromSublist(objPtr1, infoPtr);
- if (infoPtr->resultCode != TCL_OK) {
- return order;
- }
- objPtr2 = SelectObjFromSublist(objPtr2, infoPtr);
- if (infoPtr->resultCode != TCL_OK) {
- return order;
- }
- }
-
if (infoPtr->sortMode == SORTMODE_ASCII) {
- order = infoPtr->strCmpFn(TclGetString(objPtr1),
- TclGetString(objPtr2));
+ order = strcmp(elemPtr1->index.strValuePtr,
+ elemPtr2->index.strValuePtr);
+ } else if (infoPtr->sortMode == SORTMODE_ASCII_NC) {
+ order = strcasecmp(elemPtr1->index.strValuePtr,
+ elemPtr2->index.strValuePtr);
} else if (infoPtr->sortMode == SORTMODE_DICTIONARY) {
- order = DictionaryCompare(
- TclGetString(objPtr1), TclGetString(objPtr2));
+ order = DictionaryCompare(elemPtr1->index.strValuePtr,
+ elemPtr2->index.strValuePtr);
} else if (infoPtr->sortMode == SORTMODE_INTEGER) {
long a, b;
- if ((TclGetLongFromObj(infoPtr->interp, objPtr1, &a) != TCL_OK)
- || (TclGetLongFromObj(infoPtr->interp, objPtr2, &b)
- != TCL_OK)) {
- infoPtr->resultCode = TCL_ERROR;
- return order;
- }
+ a = elemPtr1->index.intValue;
+ b = elemPtr2->index.intValue;
if (a > b) {
order = 1;
} else if (b > a) {
@@ -3868,11 +3935,8 @@
} else if (infoPtr->sortMode == SORTMODE_REAL) {
double a, b;
- if (Tcl_GetDoubleFromObj(infoPtr->interp, objPtr1, &a) != TCL_OK ||
- Tcl_GetDoubleFromObj(infoPtr->interp, objPtr2, &b) != TCL_OK){
- infoPtr->resultCode = TCL_ERROR;
- return order;
- }
+ a = elemPtr1->index.doubleValue;
+ b = elemPtr2->index.doubleValue;
if (a > b) {
order = 1;
} else if (b > a) {
@@ -3881,7 +3945,11 @@
} else {
Tcl_Obj **objv, *paramObjv[2];
int objc;
+ Tcl_Obj *objPtr1, *objPtr2;
+ objPtr1 = elemPtr1->index.objValuePtr;
+ objPtr2 = elemPtr2->index.objValuePtr;
+
paramObjv[0] = objPtr1;
paramObjv[1] = objPtr2;
Index: tests/cmdIL.test
===================================================================
RCS file: /cvsroot/tcl/tcl/tests/cmdIL.test,v
retrieving revision 1.35
diff -u -r1.35 cmdIL.test
--- tests/cmdIL.test 13 Dec 2007 15:26:06 -0000 1.35
+++ tests/cmdIL.test 23 Dec 2007 16:34:27 -0000
@@ -175,6 +175,9 @@
} {1 {element 2 missing from sublist "20 10"}}
test cmdIL-3.4 {SortCompare procedure, -index option} {
list [catch {lsort -integer -index 2 "{a b c} \\\{"} msg] $msg
+} {1 {expected integer but got "c"}}
+test cmdIL-3.4.1 {SortCompare procedure, -index option} {
+ list [catch {lsort -integer -index 2 "{1 2 3} \\\{"} msg] $msg
} {1 {unmatched open brace in list}}
test cmdIL-3.5 {SortCompare procedure, -index option} {
list [catch {lsort -integer -index 2 {{20 10 13} {15}}} msg] $msg