Tcl Source Code

Check-in [cf82eb92c8]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Support the requested [lsort -entier] functionality.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | rfe-3216010
Files: files | file ages | folders
SHA1: cf82eb92c89eea9d80495817287a94d629d958bc
User & Date: dgp 2011-03-17 21:18:03
Context
2011-04-04
14:26
Merge to feature branch Closed-Leaf check-in: c29f1b7a0d user: dkf tags: rfe-3216010
2011-03-17
21:18
Support the requested [lsort -entier] functionality. check-in: cf82eb92c8 user: dgp tags: rfe-3216010
2011-03-16
15:53
[Bug #3197864] pointer truncation on Win64 TCL_MEM_DEBUG builds check-in: 8f397fe9f2 user: jan.nijtmans tags: core-8-5-branch
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to generic/tclCmdIL.c.

15
16
17
18
19
20
21

22
23
24
25
26
27
28
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"
#include "tclRegexp.h"


/*
 * During execution of the "lsort" command, structures of the following type
 * are used to arrange the objects being sorted into a collection of linked
 * lists.
 */








>







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tclInt.h"
#include "tclRegexp.h"
#include "tommath.h"

/*
 * During execution of the "lsort" command, structures of the following type
 * are used to arrange the objects being sorted into a collection of linked
 * lists.
 */

83
84
85
86
87
88
89

90
91
92
93
94
95
96
 */

#define SORTMODE_ASCII		0
#define SORTMODE_INTEGER	1
#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
 * index "end-1" will be translated to SORTIDX_END-1, etc.
 */








>







84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
 */

#define SORTMODE_ASCII		0
#define SORTMODE_INTEGER	1
#define SORTMODE_REAL		2
#define SORTMODE_COMMAND	3
#define SORTMODE_DICTIONARY	4
#define SORTMODE_ENTIER		5
#define SORTMODE_ASCII_NC	8

/*
 * Magic values for the index field of the SortInfo structure. Note that the
 * index "end-1" will be translated to SORTIDX_END-1, etc.
 */

3458
3459
3460
3461
3462
3463
3464
3465
3466

3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
{
    int i, j, index, indices, length, nocase = 0, sortMode, indexc;
    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. */
    static CONST char *switches[] = {
	"-ascii", "-command", "-decreasing", "-dictionary", "-increasing",
	"-index", "-indices", "-integer", "-nocase", "-real", "-unique", NULL

    };
    enum Lsort_Switches {
	LSORT_ASCII, LSORT_COMMAND, LSORT_DECREASING, LSORT_DICTIONARY,
	LSORT_INCREASING, LSORT_INDEX, LSORT_INDICES, LSORT_INTEGER,
	LSORT_NOCASE, LSORT_REAL, LSORT_UNIQUE
    };

    /*
     * The subList array below holds pointers to temporary lists built during
     * the merge sort. Element i of the array holds a list of length 2**i.
     */
#   define NUM_LISTS 30







|
|
>



|
|







3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
{
    int i, j, index, indices, length, nocase = 0, sortMode, indexc;
    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. */
    static CONST char *switches[] = {
	"-ascii", "-command", "-decreasing", "-dictionary", "-entier",
	"-increasing", "-index", "-indices", "-integer", "-nocase",
	"-real", "-unique", NULL
    };
    enum Lsort_Switches {
	LSORT_ASCII, LSORT_COMMAND, LSORT_DECREASING, LSORT_DICTIONARY,
	LSORT_ENTIER, LSORT_INCREASING, LSORT_INDEX, LSORT_INDICES,
	LSORT_INTEGER, LSORT_NOCASE, LSORT_REAL, LSORT_UNIQUE
    };

    /*
     * The subList array below holds pointers to temporary lists built during
     * the merge sort. Element i of the array holds a list of length 2**i.
     */
#   define NUM_LISTS 30
3524
3525
3526
3527
3528
3529
3530



3531
3532
3533
3534
3535
3536
3537
	    break;
	case LSORT_DECREASING:
	    sortInfo.isIncreasing = 0;
	    break;
	case LSORT_DICTIONARY:
	    sortInfo.sortMode = SORTMODE_DICTIONARY;
	    break;



	case LSORT_INCREASING:
	    sortInfo.isIncreasing = 1;
	    break;
	case LSORT_INDEX: {
	    Tcl_Obj **indices;

	    if (sortInfo.indexc > 1) {







>
>
>







3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
	    break;
	case LSORT_DECREASING:
	    sortInfo.isIncreasing = 0;
	    break;
	case LSORT_DICTIONARY:
	    sortInfo.sortMode = SORTMODE_DICTIONARY;
	    break;
	case LSORT_ENTIER:
	    sortInfo.sortMode = SORTMODE_ENTIER;
	    break;
	case LSORT_INCREASING:
	    sortInfo.isIncreasing = 1;
	    break;
	case LSORT_INDEX: {
	    Tcl_Obj **indices;

	    if (sortInfo.indexc > 1) {
3697
3698
3699
3700
3701
3702
3703
















3704
3705
3706
3707
3708
3709
3710

	/*
	 * Determine the "value" of this object for sorting purposes
	 */
	
	if (sortMode == SORTMODE_ASCII) {
	    elementArray[i].index.strValuePtr = TclGetString(indexPtr);
















	} else if (sortMode == SORTMODE_INTEGER) {
	    long a;
	    if (TclGetLongFromObj(sortInfo.interp, indexPtr, &a) != TCL_OK) {
		sortInfo.resultCode = TCL_ERROR;
		goto done1;
	    }
	    elementArray[i].index.intValue = a;







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







3703
3704
3705
3706
3707
3708
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
3725
3726
3727
3728
3729
3730
3731
3732

	/*
	 * Determine the "value" of this object for sorting purposes
	 */
	
	if (sortMode == SORTMODE_ASCII) {
	    elementArray[i].index.strValuePtr = TclGetString(indexPtr);
	} else if (sortMode == SORTMODE_ENTIER) {
	    ClientData ptr;
	    int type;
	
	    if (TclGetNumberFromObj(sortInfo.interp, indexPtr, &ptr, &type)
		    != TCL_OK) {
		sortInfo.resultCode = TCL_ERROR;
		goto done1;
	    }
	    if ((type == TCL_NUMBER_NAN) || (type == TCL_NUMBER_DOUBLE)) {
		/* Generate standard error message */
		Tcl_GetBignumFromObj(sortInfo.interp, indexPtr, NULL);
		sortInfo.resultCode = TCL_ERROR;
		goto done1;
	    }
	    elementArray[i].index.objValuePtr = indexPtr;
	} else if (sortMode == SORTMODE_INTEGER) {
	    long a;
	    if (TclGetLongFromObj(sortInfo.interp, indexPtr, &a) != TCL_OK) {
		sortInfo.resultCode = TCL_ERROR;
		goto done1;
	    }
	    elementArray[i].index.intValue = a;
3929
3930
3931
3932
3933
3934
3935































































3936
3937
3938
3939
3940
3941
3942
		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(elemPtr1->index.strValuePtr,
		elemPtr2->index.strValuePtr);































































    } else if (infoPtr->sortMode == SORTMODE_INTEGER) {
	long a, b;

	a = elemPtr1->index.intValue;
	b = elemPtr2->index.intValue;
	order = ((a >= b) - (a <= b));
    } else if (infoPtr->sortMode == SORTMODE_REAL) {







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







3951
3952
3953
3954
3955
3956
3957
3958
3959
3960
3961
3962
3963
3964
3965
3966
3967
3968
3969
3970
3971
3972
3973
3974
3975
3976
3977
3978
3979
3980
3981
3982
3983
3984
3985
3986
3987
3988
3989
3990
3991
3992
3993
3994
3995
3996
3997
3998
3999
4000
4001
4002
4003
4004
4005
4006
4007
4008
4009
4010
4011
4012
4013
4014
4015
4016
4017
4018
4019
4020
4021
4022
4023
4024
4025
4026
4027
		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(elemPtr1->index.strValuePtr,
		elemPtr2->index.strValuePtr);
    } else if (infoPtr->sortMode == SORTMODE_ENTIER) {
	ClientData ptr;
	int type1, type2, comparison;
	Tcl_Obj *objPtr1 = elemPtr1->index.objValuePtr;
	Tcl_Obj *objPtr2 = elemPtr2->index.objValuePtr;

	TclGetNumberFromObj(NULL, objPtr1, &ptr, &type1);
	TclGetNumberFromObj(NULL, objPtr2, &ptr, &type2);

	comparison = (type1 > type2) ? type1 : type2;

	switch (comparison) {
	case TCL_NUMBER_LONG: {
	    long a, b;

	    Tcl_GetLongFromObj(NULL, objPtr1, &a);
	    Tcl_GetLongFromObj(NULL, objPtr2, &b);
	    order = ((a >= b) - (a <= b));
	    break;
	}
#ifndef NO_WIDE_TYPE
	case TCL_NUMBER_WIDE: {
	    Tcl_WideInt a, b;

	    Tcl_GetWideIntFromObj(NULL, objPtr1, &a);
	    Tcl_GetWideIntFromObj(NULL, objPtr2, &b);
	    order = ((a >= b) - (a <= b));
	    break;
	}
#endif
	case TCL_NUMBER_BIG: {
	    mp_int a, b;

	    if (type1 < TCL_NUMBER_BIG) {
		Tcl_GetBignumFromObj(NULL, objPtr2, &b);
		order = 2*(mp_cmp_d(&b, 0) == MP_LT) - 1;
		mp_clear(&b);
		break;
	    }
	    if (type2 < TCL_NUMBER_BIG) {
		Tcl_GetBignumFromObj(NULL, objPtr1, &a);
		order = 1 - 2*(mp_cmp_d(&a, 0) == MP_LT);
		mp_clear(&a);
		break;
	    }

	    Tcl_GetBignumFromObj(NULL, objPtr1, &a);
	    Tcl_GetBignumFromObj(NULL, objPtr2, &b);
	    switch (mp_cmp(&a, &b)) {
	    case MP_LT:
		order = -1;
		break;
	    case MP_EQ:
		order = 0;
		break;
	    case MP_GT:
		order = 1;
		break;
	    }
	    mp_clear(&a);
	    mp_clear(&b);
	}
	}
    } else if (infoPtr->sortMode == SORTMODE_INTEGER) {
	long a, b;

	a = elemPtr1->index.intValue;
	b = elemPtr2->index.intValue;
	order = ((a >= b) - (a <= b));
    } else if (infoPtr->sortMode == SORTMODE_REAL) {

Changes to tests/cmdIL.test.

17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
testConstraint memory [llength [info commands memory]]

test cmdIL-1.1 {Tcl_LsortObjCmd procedure} {
    list [catch {lsort} msg] $msg
} {1 {wrong # args: should be "lsort ?options? list"}}
test cmdIL-1.2 {Tcl_LsortObjCmd procedure} {
    list [catch {lsort -foo {1 3 2 5}} msg] $msg
} {1 {bad option "-foo": must be -ascii, -command, -decreasing, -dictionary, -increasing, -index, -indices, -integer, -nocase, -real, or -unique}}
test cmdIL-1.3 {Tcl_LsortObjCmd procedure, default options} {
    lsort {d e c b a \{ d35 d300}
} {a b c d d300 d35 e \{}
test cmdIL-1.4 {Tcl_LsortObjCmd procedure, -ascii option} {
    lsort -integer -ascii {d e c b a d35 d300}
} {a b c d d300 d35 e}
test cmdIL-1.5 {Tcl_LsortObjCmd procedure, -command option} {







|







17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
testConstraint memory [llength [info commands memory]]

test cmdIL-1.1 {Tcl_LsortObjCmd procedure} {
    list [catch {lsort} msg] $msg
} {1 {wrong # args: should be "lsort ?options? list"}}
test cmdIL-1.2 {Tcl_LsortObjCmd procedure} {
    list [catch {lsort -foo {1 3 2 5}} msg] $msg
} {1 {bad option "-foo": must be -ascii, -command, -decreasing, -dictionary, -entier, -increasing, -index, -indices, -integer, -nocase, -real, or -unique}}
test cmdIL-1.3 {Tcl_LsortObjCmd procedure, default options} {
    lsort {d e c b a \{ d35 d300}
} {a b c d d300 d35 e \{}
test cmdIL-1.4 {Tcl_LsortObjCmd procedure, -ascii option} {
    lsort -integer -ascii {d e c b a d35 d300}
} {a b c d d300 d35 e}
test cmdIL-1.5 {Tcl_LsortObjCmd procedure, -command option} {