From e4b884c4fa1756e7818c02382f806000cd2ea5e5 Mon Sep 17 00:00:00 2001 From: dkf Date: Wed, 6 Mar 2002 11:28:08 +0000 Subject: TIP#81 implementation, tests and docs --- ChangeLog | 7 + doc/lsearch.n | 67 +++++++-- generic/tclCmdIL.c | 394 ++++++++++++++++++++++++++++++++++------------------- tests/lsearch.test | 100 +++++++++++--- 4 files changed, 399 insertions(+), 169 deletions(-) diff --git a/ChangeLog b/ChangeLog index 13f300d..7dbb452 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2002-03-06 Donal K. Fellows + + * doc/lsearch.n: Documentation of new features, plus examples. + * tests/lsearch.test: Tests of new features. + * generic/tclCmdIL.c (Tcl_LsearchObjCmd): TIP#80 support. See + http://purl.org/tcl/tip/80 for details. + 2002-03-05 Jeff Hobbs *** 8.4a4 TAGGED FOR RELEASE *** diff --git a/doc/lsearch.n b/doc/lsearch.n index 48c24b8..30ce348 100644 --- a/doc/lsearch.n +++ b/doc/lsearch.n @@ -6,7 +6,7 @@ '\" See the file "license.terms" for information on usage and redistribution '\" of this file, and for a DISCLAIMER OF ALL WARRANTIES. '\" -'\" RCS: @(#) $Id: lsearch.n,v 1.9 2001/11/14 23:38:39 hobbs Exp $ +'\" RCS: @(#) $Id: lsearch.n,v 1.10 2002/03/06 11:28:08 dkf Exp $ '\" .so man.macros .TH lsearch n 8.4 Tcl "Tcl Built-In Commands" @@ -22,10 +22,19 @@ lsearch \- See if a list contains a particular element .PP This command searches the elements of \fIlist\fR to see if one of them matches \fIpattern\fR. If so, the command returns the index -of the first matching element. If not, the command returns \fB\-1\fR. -The \fIoption\fR arguments indicates how the elements of the list are to -be matched against \fIpattern\fR and it must have one of the following -values: +of the first matching element +.VS 8.4 +(unless the options \fB\-all\fR or \fB\-inline\fR are specified.) +.VE 8.4 +If not, the command returns \fB\-1\fR. The \fIoption\fR arguments +indicates how the elements of the list are to be matched against +\fIpattern\fR and it must have one of the following values: +.TP +\fB\-all\fR +.VS 8.4 +Changes the result to be the list of all matching indices (or all +matching values if \fB\-inline\fR is specified as well.) +.VE 8.4 .TP \fB\-ascii\fR The list elements are to be examined as ASCII strings. This option is only @@ -43,17 +52,30 @@ comparisons. This option is only meaningful when used with \fB\-exact\fR The list element must contain exactly the same string as \fIpattern\fR. .TP +\fB\-glob\fR +\fIPattern\fR is a glob-style pattern which is matched against each list +element using the same rules as the \fBstring match\fR command. +.TP \fB\-increasing\fR The list elements are sorted in increasing order. This option is only meaningful when used with \fB\-sorted\fR. .TP +\fB\-inline\fR +.VS 8.4 +The matching value is returned instead of its index (or an empty +string if no value matches.) If \fB\-all\fR is also specified, then +the result of the command is the list of all values that matched. +.VE 8.4 +.TP \fB\-integer\fR The list elements are to be compared as integers. This option is only meaningful when used with \fB\-exact\fR or \fB\-sorted\fR. .TP -\fB\-glob\fR -\fIPattern\fR is a glob-style pattern which is matched against each list -element using the same rules as the \fBstring match\fR command. +\fB\-not\fR +.VS 8.4 +This negates the sense of the match, returning the index of the first +non-matching value in the list. +.VE 8.4 .TP \fB\-real\fR The list elements are to be compared as floating-point values. This @@ -69,7 +91,16 @@ The list elements are in sorted order. If this option is specified, \fBlsearch\fR will use a more efficient searching algorithm to search \fIlist\fR. If no other options are specified, \fIlist\fR is assumed to be sorted in increasing order, and to contain ASCII strings. This -option cannot be used with \fB\-glob\fR or \fB\-regexp\fR. +option cannot be used with \fB\-all\fR, \fB\-glob\fR, \fB\-not\fR or +\fB\-regexp\fR. +.TP +\fB\-start\fR \fIindex\fR +.VS 8.4 +The list is searched starting at position \fIindex\fR. If \fIindex\fR +has the value \fBend\fR, it refers to the last element in the list, +and \fBend\-\fIinteger\fR refers to the last element in the list minus +the specified integer offset. +.VE 8.4 .PP If \fIoption\fR is omitted then it defaults to \fB\-glob\fR. If more than one of \fB\-exact\fR, \fB\-glob\fR, \fB\-regexp\fR, and @@ -77,11 +108,25 @@ than one of \fB\-exact\fR, \fB\-glob\fR, \fB\-regexp\fR, and precendence. If more than one of \fB\-ascii\fR, \fB\-dictionary\fR, \fB\-integer\fR and \fB\-real\fR is specified, the option specified last takes precendence. If more than one of \fB\-increasing\fR and -\fB\-decreasing\fR is specified, the option specified last takes precedence. +\fB\-decreasing\fR is specified, the option specified last takes +precedence. + +.SH EXAMPLES +.VS 8.4 +.CS +lsearch {a b c d e} c => 2 +lsearch -all {a b c a b c} c => 2 5 +lsearch -data {a20 b35 c47} b* => b35 +lsearch -data -not {a20 b35 c47} b* => a20 +lsearch -all -data -not {a20 b35 c47} b* => a20 c47 +lsearch -all -not {a20 b35 c47} b* => 0 2 +lsearch -start 3 {a b c a b c} c => 5 +.CE +.VE 8.4 .SH "SEE ALSO" .VS 8.4 -list(n), lappend(n), lindex(n), linsert(n), llength(n), +foreach(n), list(n), lappend(n), lindex(n), linsert(n), llength(n), lset(n), lsort(n), lrange(n), lreplace(n) .VE diff --git a/generic/tclCmdIL.c b/generic/tclCmdIL.c index f7cdf29..405245a 100644 --- a/generic/tclCmdIL.c +++ b/generic/tclCmdIL.c @@ -15,7 +15,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.41 2002/02/15 14:28:48 dkf Exp $ + * RCS: @(#) $Id: tclCmdIL.c,v 1.42 2002/03/06 11:28:08 dkf Exp $ */ #include "tclInt.h" @@ -2767,22 +2767,24 @@ Tcl_LsearchObjCmd(clientData, interp, objc, objv) char *bytes, *patternBytes; int i, match, mode, index, result, listc, length, elemLen; int dataType, isIncreasing, lower, upper, patInt, objInt; + int offset, allMatches, inlineReturn, negatedMatch; double patDouble, objDouble; - Tcl_Obj *patObj, **listv; + Tcl_Obj *patObj, **listv, *listPtr, *startPtr; static CONST char *options[] = { - "-ascii", "-decreasing", "-dictionary", "-exact", "-increasing", - "-integer", "-glob", "-real", "-regexp", "-sorted", NULL + "-all", "-ascii", "-decreasing", "-dictionary", + "-exact", "-glob", "-increasing", "-inline", + "-integer", "-not", "-real", "-regexp", + "-sorted", "-start", NULL }; enum options { - LSEARCH_ASCII, LSEARCH_DECREASING, LSEARCH_DICTIONARY, LSEARCH_EXACT, - LSEARCH_INCREASING, LSEARCH_INTEGER, LSEARCH_GLOB, - LSEARCH_REAL, LSEARCH_REGEXP, LSEARCH_SORTED + LSEARCH_ALL, LSEARCH_ASCII, LSEARCH_DECREASING, LSEARCH_DICTIONARY, + LSEARCH_EXACT, LSEARCH_GLOB, LSEARCH_INCREASING, LSEARCH_INLINE, + LSEARCH_INTEGER, LSEARCH_NOT, LSEARCH_REAL, LSEARCH_REGEXP, + LSEARCH_SORTED, LSEARCH_START }; - enum datatypes { ASCII, DICTIONARY, INTEGER, REAL }; - enum modes { EXACT, GLOB, REGEXP, SORTED }; @@ -2790,48 +2792,93 @@ Tcl_LsearchObjCmd(clientData, interp, objc, objv) mode = GLOB; dataType = ASCII; isIncreasing = 1; - + allMatches = 0; + inlineReturn = 0; + negatedMatch = 0; + listPtr = NULL; + startPtr = NULL; + offset = 0; + if (objc < 3) { Tcl_WrongNumArgs(interp, 1, objv, "?options? list pattern"); return TCL_ERROR; } - + for (i = 1; i < objc-2; i++) { if (Tcl_GetIndexFromObj(interp, objv[i], options, "option", 0, &index) != TCL_OK) { + if (startPtr) { + Tcl_DecrRefCount(startPtr); + } return TCL_ERROR; } switch ((enum options) index) { - case LSEARCH_ASCII: /* -ascii */ - dataType = ASCII; - break; - case LSEARCH_DECREASING: /* -decreasing */ - isIncreasing = 0; - break; - case LSEARCH_DICTIONARY: /* -dictionary */ - dataType = DICTIONARY; - break; - case LSEARCH_EXACT: /* -increasing */ - mode = EXACT; - break; - case LSEARCH_INCREASING: /* -increasing */ - isIncreasing = 1; - break; - case LSEARCH_INTEGER: /* -integer */ - dataType = INTEGER; - break; - case LSEARCH_GLOB: /* -glob */ - mode = GLOB; - break; - case LSEARCH_REAL: /* -real */ - dataType = REAL; - break; - case LSEARCH_REGEXP: /* -regexp */ - mode = REGEXP; - break; - case LSEARCH_SORTED: /* -sorted */ - mode = SORTED; - break; + case LSEARCH_ALL: /* -all */ + allMatches = 1; + break; + case LSEARCH_ASCII: /* -ascii */ + dataType = ASCII; + break; + case LSEARCH_DECREASING: /* -decreasing */ + isIncreasing = 0; + break; + case LSEARCH_DICTIONARY: /* -dictionary */ + dataType = DICTIONARY; + break; + case LSEARCH_EXACT: /* -increasing */ + mode = EXACT; + break; + case LSEARCH_GLOB: /* -glob */ + mode = GLOB; + break; + case LSEARCH_INCREASING: /* -increasing */ + isIncreasing = 1; + break; + case LSEARCH_INLINE: /* -inline */ + inlineReturn = 1; + break; + case LSEARCH_INTEGER: /* -integer */ + dataType = INTEGER; + break; + case LSEARCH_NOT: /* -not */ + negatedMatch = 1; + break; + case LSEARCH_REAL: /* -real */ + dataType = REAL; + break; + case LSEARCH_REGEXP: /* -regexp */ + mode = REGEXP; + break; + case LSEARCH_SORTED: /* -sorted */ + mode = SORTED; + break; + case LSEARCH_START: /* -start */ + /* + * If there was a previous -start option, release its saved + * index because it will either be replaced or there will be + * an error. + */ + if (startPtr) { + Tcl_DecrRefCount(startPtr); + } + if (i > objc-4) { + Tcl_AppendResult(interp, "missing starting index", NULL); + return TCL_ERROR; + } + i++; + if (objv[i] == objv[objc - 2]) { + /* + * Take copy to prevent shimmering problems. Note + * that it does not matter if the index obj is also a + * component of the list being searched. We only need + * to copy where the list and the index are + * one-and-the-same. + */ + startPtr = Tcl_DuplicateObj(objv[i]); + } else { + startPtr = objv[i]; + Tcl_IncrRefCount(startPtr); + } } } @@ -2842,29 +2889,48 @@ Tcl_LsearchObjCmd(clientData, interp, objc, objv) result = Tcl_ListObjGetElements(interp, objv[objc - 2], &listc, &listv); if (result != TCL_OK) { + if (startPtr) { + Tcl_DecrRefCount(startPtr); + } return result; } + /* + * Get the user-specified start offset. + */ + if (startPtr) { + result = TclGetIntForIndex(interp, startPtr, listc-1, &offset); + Tcl_DecrRefCount(startPtr); + if (result != TCL_OK) { + return result; + } + if (offset < 0) { + offset = 0; + } else if (offset > listc-1) { + offset = listc-1; + } + } + patObj = objv[objc - 1]; patternBytes = NULL; if ((enum modes) mode == EXACT || (enum modes) mode == SORTED) { switch ((enum datatypes) dataType) { - case ASCII: - case DICTIONARY: - patternBytes = Tcl_GetStringFromObj(patObj, &length); - break; - case INTEGER: - result = Tcl_GetIntFromObj(interp, patObj, &patInt); - if (result != TCL_OK) { - return result; - } - break; - case REAL: - result = Tcl_GetDoubleFromObj(interp, patObj, &patDouble); - if (result != TCL_OK) { - return result; - } - break; + case ASCII: + case DICTIONARY: + patternBytes = Tcl_GetStringFromObj(patObj, &length); + break; + case INTEGER: + result = Tcl_GetIntFromObj(interp, patObj, &patInt); + if (result != TCL_OK) { + return result; + } + break; + case REAL: + result = Tcl_GetDoubleFromObj(interp, patObj, &patDouble); + if (result != TCL_OK) { + return result; + } + break; } } else { patternBytes = Tcl_GetStringFromObj(patObj, &length); @@ -2877,52 +2943,54 @@ Tcl_LsearchObjCmd(clientData, interp, objc, objv) */ index = -1; match = 0; - if ((enum modes) mode == SORTED) { - /* If the data is sorted, we can do a more intelligent search */ - lower = -1; + + if ((enum modes) mode == SORTED && !allMatches && !negatedMatch) { + /* + * If the data is sorted, we can do a more intelligent search. + * Note that there is no point in being smart when -all was + * specified; in that case, we have to look at all items anyway, + * and there is no sense in doing this when the match sense is + * inverted. + */ + lower = offset - 1; upper = listc; while (lower + 1 != upper) { i = (lower + upper)/2; switch ((enum datatypes) dataType) { - case ASCII: { - bytes = Tcl_GetString(listv[i]); - match = strcmp(patternBytes, bytes); - break; + case ASCII: + bytes = Tcl_GetString(listv[i]); + match = strcmp(patternBytes, bytes); + break; + case DICTIONARY: + bytes = Tcl_GetString(listv[i]); + match = DictionaryCompare(patternBytes, bytes); + break; + case INTEGER: + result = Tcl_GetIntFromObj(interp, listv[i], &objInt); + if (result != TCL_OK) { + return result; } - case DICTIONARY: { - bytes = Tcl_GetString(listv[i]); - match = DictionaryCompare(patternBytes, bytes); - break; + if (patInt == objInt) { + match = 0; + } else if (patInt < objInt) { + match = -1; + } else { + match = 1; } - case INTEGER: { - result = Tcl_GetIntFromObj(interp, listv[i], &objInt); - if (result != TCL_OK) { - return result; - } - if (patInt == objInt) { - match = 0; - } else if (patInt < objInt) { - match = -1; - } else { - match = 1; - } - break; + break; + case REAL: + result = Tcl_GetDoubleFromObj(interp, listv[i], &objDouble); + if (result != TCL_OK) { + return result; } - case REAL: { - result = Tcl_GetDoubleFromObj(interp, listv[i], - &objDouble); - if (result != TCL_OK) { - return result; - } - if (patDouble == objDouble) { - match = 0; - } else if (patDouble < objDouble) { - match = -1; - } else { - match = 1; - } - break; + if (patDouble == objDouble) { + match = 0; + } else if (patDouble < objDouble) { + match = -1; + } else { + match = 1; } + break; } if (match == 0) { /* @@ -2953,68 +3021,110 @@ Tcl_LsearchObjCmd(clientData, interp, objc, objv) } } } + } else { - for (i = 0; i < listc; i++) { + /* + * We need to do a linear search, because (at least one) of: + * - our matcher can only tell equal vs. not equal + * - our matching sense is negated + * - we're building a list of all matched items + */ + if (allMatches) { + listPtr = Tcl_NewListObj(0, (Tcl_Obj **) NULL); + } + for (i = offset; i < listc; i++) { match = 0; switch ((enum modes) mode) { - case SORTED: - case EXACT: { - switch ((enum datatypes) dataType) { - case ASCII: { - bytes = Tcl_GetStringFromObj(listv[i], &elemLen); - if (length == elemLen) { - match = (memcmp(bytes, patternBytes, - (size_t) length) == 0); - } - break; - } - case DICTIONARY: { - bytes = Tcl_GetString(listv[i]); - match = - (DictionaryCompare(bytes, patternBytes) == 0); - break; - } - case INTEGER: { - result = Tcl_GetIntFromObj(interp, listv[i], - &objInt); - if (result != TCL_OK) { - return result; - } - match = (objInt == patInt); - break; - } - case REAL: { - result = Tcl_GetDoubleFromObj(interp, listv[i], - &objDouble); - if (result != TCL_OK) { - return result; - } - match = (objDouble == patDouble); - break; + case SORTED: + case EXACT: + switch ((enum datatypes) dataType) { + case ASCII: + bytes = Tcl_GetStringFromObj(listv[i], &elemLen); + if (length == elemLen) { + match = (memcmp(bytes, patternBytes, + (size_t) length) == 0); + } + break; + case DICTIONARY: + bytes = Tcl_GetString(listv[i]); + match = (DictionaryCompare(bytes, patternBytes) == 0); + break; + case INTEGER: + result = Tcl_GetIntFromObj(interp, listv[i], &objInt); + if (result != TCL_OK) { + if (listPtr) { + Tcl_DecrRefCount(listPtr); } + return result; } + match = (objInt == patInt); break; - } - case GLOB: { - match = Tcl_StringMatch(Tcl_GetString(listv[i]), - patternBytes); + case REAL: + result = Tcl_GetDoubleFromObj(interp, listv[i], + &objDouble); + if (result != TCL_OK) { + if (listPtr) { + Tcl_DecrRefCount(listPtr); + } + return result; + } + match = (objDouble == patDouble); break; } - case REGEXP: { - match = Tcl_RegExpMatchObj(interp, listv[i], patObj); - if (match < 0) { - return TCL_ERROR; + break; + case GLOB: + match = Tcl_StringMatch(Tcl_GetString(listv[i]), + patternBytes); + break; + case REGEXP: + match = Tcl_RegExpMatchObj(interp, listv[i], patObj); + if (match < 0) { + if (listPtr) { + Tcl_DecrRefCount(listPtr); } - break; + return TCL_ERROR; } + break; + } + /* + * Invert match condition for -not + */ + if (negatedMatch) { + match = !match; } if (match != 0) { - index = i; - break; + if (!allMatches) { + index = i; + break; + } else if (inlineReturn) { + /* + * Note that these appends are not expected to fail. + */ + Tcl_ListObjAppendElement(interp, listPtr, listv[i]); + } else { + Tcl_ListObjAppendElement(interp, listPtr, + Tcl_NewIntObj(i)); + } } } } - Tcl_SetIntObj(Tcl_GetObjResult(interp), index); + + /* + * Return everything or a single value. + */ + if (allMatches) { + Tcl_SetObjResult(interp, listPtr); + } else if (!inlineReturn) { + Tcl_SetIntObj(Tcl_GetObjResult(interp), index); + } else if (index < 0) { + /* + * Is this superfluous? The result should be a blank object + * by default... + */ + Tcl_SetObjResult(interp, Tcl_NewObj()); + } else { + Tcl_SetObjResult(interp, listv[index]); + } return TCL_OK; } diff --git a/tests/lsearch.test b/tests/lsearch.test index 44ec96e..887edb9 100644 --- a/tests/lsearch.test +++ b/tests/lsearch.test @@ -11,7 +11,7 @@ # See the file "license.terms" for information on usage and redistribution # of this file, and for a DISCLAIMER OF ALL WARRANTIES. # -# RCS: @(#) $Id: lsearch.test,v 1.7 2001/09/12 20:28:50 dgp Exp $ +# RCS: @(#) $Id: lsearch.test,v 1.8 2002/03/06 11:28:08 dkf Exp $ if {[lsearch [namespace children] ::tcltest] == -1} { package require tcltest @@ -61,7 +61,7 @@ test lsearch-2.9 {search modes} { } 1 test lsearch-2.10 {search modes} { list [catch {lsearch -glib {b.x bx xy bcx} b.x} msg] $msg -} {1 {bad option "-glib": must be -ascii, -decreasing, -dictionary, -exact, -increasing, -integer, -glob, -real, -regexp, or -sorted}} +} {1 {bad option "-glib": must be -all, -ascii, -decreasing, -dictionary, -exact, -glob, -increasing, -inline, -integer, -not, -real, -regexp, -sorted, or -start}} test lsearch-3.1 {lsearch errors} { list [catch lsearch msg] $msg @@ -71,10 +71,10 @@ test lsearch-3.2 {lsearch errors} { } {1 {wrong # args: should be "lsearch ?options? list pattern"}} test lsearch-3.3 {lsearch errors} { list [catch {lsearch a b c} msg] $msg -} {1 {bad option "a": must be -ascii, -decreasing, -dictionary, -exact, -increasing, -integer, -glob, -real, -regexp, or -sorted}} +} {1 {bad option "a": must be -all, -ascii, -decreasing, -dictionary, -exact, -glob, -increasing, -inline, -integer, -not, -real, -regexp, -sorted, or -start}} test lsearch-3.4 {lsearch errors} { list [catch {lsearch a b c d} msg] $msg -} {1 {bad option "a": must be -ascii, -decreasing, -dictionary, -exact, -increasing, -integer, -glob, -real, -regexp, or -sorted}} +} {1 {bad option "a": must be -all, -ascii, -decreasing, -dictionary, -exact, -glob, -increasing, -inline, -integer, -not, -real, -regexp, -sorted, or -start}} test lsearch-3.5 {lsearch errors} { list [catch {lsearch "\{" b} msg] $msg } {1 {unmatched open brace in list}} @@ -267,21 +267,89 @@ test lsearch-9.4 {decreasing sorted ascii search} { set res } [list 6 5 4 3 2 1 0] +test lsearch-10.1 {offset searching} { + lsearch -start 2 {a b c a b c} a +} 3 +test lsearch-10.2 {offset searching} { + lsearch -start 2 {a b c d e f} a +} -1 +test lsearch-10.3 {offset searching} { + lsearch -start end-4 {a b c a b c} a +} 3 +test lsearch-10.4 {offset searching} { + list [catch {lsearch -start foobar {a b c a b c} a} msg] $msg +} {1 {bad index "foobar": must be integer or end?-integer?}} +test lsearch-10.5 {offset searching} { + list [catch {lsearch -start 1 2} msg] $msg +} {1 {missing starting index}} +test lsearch-10.6 {binary search with offset} { + set res {} + for {set i 0} {$i < 100} {incr i} { + lappend res [lsearch -integer -start 2 -sorted $increasingIntegers $i] + } + set res +} [concat -1 -1 [lrange $increasingIntegers 2 end]] +test lsearch-11.1 {negated searches} { + lsearch -not {a a a b a a a} a +} 3 +test lsearch-11.2 {negated searches} { + lsearch -not {a a a a a a a} a +} -1 -# cleanup -catch {unset res} -::tcltest::cleanupTests -return - - - - - - - - +test lsearch-12.1 {return values instead of indices} { + lsearch -glob -inline {a1 b2 c3 d4} c* +} c3 +test lsearch-12.2 {return values instead of indices} { + lsearch -glob -inline {a1 b2 c3 d4} e* +} {} +test lsearch-13.1 {search for all matches} { + lsearch -all {a b a c a d} 1 +} {} +test lsearch-13.2 {search for all matches} { + lsearch -all {a b a c a d} a +} {0 2 4} +test lsearch-13.1 {combinations: -all and -inline} { + lsearch -all -inline -glob {a1 b2 a3 c4 a5 d6} a* +} {a1 a3 a5} +test lsearch-13.2 {combinations: -all, -inline and -not} { + lsearch -all -inline -not -glob {a1 b2 a3 c4 a5 d6} a* +} {b2 c4 d6} +test lsearch-13.3 {combinations: -all and -not} { + lsearch -all -not -glob {a1 b2 a3 c4 a5 d6} a* +} {1 3 5} +test lsearch-13.4 {combinations: -inline and -not} { + lsearch -inline -not -glob {a1 b2 a3 c4 a5 d6} a* +} {b2} +test lsearch-13.5 {combinations: -start, -all and -inline} { + lsearch -start 2 -all -inline -glob {a1 b2 a3 c4 a5 d6} a* +} {a3 a5} +test lsearch-13.6 {combinations: -start, -all, -inline and -not} { + lsearch -start 2 -all -inline -not -glob {a1 b2 a3 c4 a5 d6} a* +} {c4 d6} +test lsearch-13.7 {combinations: -start, -all and -not} { + lsearch -start 2 -all -not -glob {a1 b2 a3 c4 a5 d6} a* +} {3 5} +test lsearch-13.8 {combinations: -start, -inline and -not} { + lsearch -start 2 -inline -not -glob {a1 b2 a3 c4 a5 d6} a* +} {c4} +test lsearch-14.1 {make sure no shimmering occurs} { + set x [expr int(sin(0))] + lsearch -start $x $x $x +} 0 +# cleanup +catch {unset res} +catch {unset increasingIntegers} +catch {unset decreasingIntegers} +catch {unset increasingDoubles} +catch {unset decreasingDoubles} +catch {unset increasingStrings} +catch {unset decreasingStrings} +catch {unset increasingDictionary} +catch {unset decreasingDictionary} +::tcltest::cleanupTests +return -- cgit v0.12