Tcl Source Code

Check-in [9ce779b099]
Login
Bounty program for improvements to Tcl and certain Tcl packages.
Tcl 2019 Conference, Houston/TX, US, Nov 4-8
Send your abstracts to [email protected]
or submit via the online form by Sep 9.

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

Overview
Comment:TIP 429 Implementation: [string cat]
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | tip-429
Files: files | file ages | folders
SHA1: 9ce779b0993f852b38d0f629284a01fe5be39a91
User & Date: ferrieux 2014-08-02 13:04:16
Context
2014-08-02
15:26
Don't use [pid] in tests, stick to constant literals. check-in: a3fb69be9f user: ferrieux tags: tip-429
13:04
TIP 429 Implementation: [string cat] check-in: 9ce779b099 user: ferrieux tags: tip-429
2014-08-01
20:07
Addition of a cast in tclWinFile.c to match types in a comparison, and fix of a TRACE string literal... check-in: f8304cc503 user: andreask tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to doc/string.n.

14
15
16
17
18
19
20








21
22
23
24
25
26
27
.SH SYNOPSIS
\fBstring \fIoption arg \fR?\fIarg ...?\fR
.BE
.SH DESCRIPTION
.PP
Performs one of several string operations, depending on \fIoption\fR.
The legal \fIoption\fRs (which may be abbreviated) are:








.TP
\fBstring compare\fR ?\fB\-nocase\fR? ?\fB\-length\fI length\fR? \fIstring1 string2\fR
.
Perform a character-by-character comparison of strings \fIstring1\fR
and \fIstring2\fR.  Returns \-1, 0, or 1, depending on whether
\fIstring1\fR is lexicographically less than, equal to, or greater
than \fIstring2\fR.  If \fB\-length\fR is specified, then only the






>
>
>
>
>
>
>
>







14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
.SH SYNOPSIS
\fBstring \fIoption arg \fR?\fIarg ...?\fR
.BE
.SH DESCRIPTION
.PP
Performs one of several string operations, depending on \fIoption\fR.
The legal \fIoption\fRs (which may be abbreviated) are:
.TP
\fBstring cat\fR ?\fIstring1\fR? ?\fIstring2...\fR?
.
Concatenate the given strings just like direct juxtaposition
would. This primitive is occasionally handier than juxtaposition when
mixed quoting is wanted, or when the aim is to return the result of a
concatenation without resorting to \fB[return -level 0]\fR. If no arg
is present, an empty string is returned.
.TP
\fBstring compare\fR ?\fB\-nocase\fR? ?\fB\-length\fI length\fR? \fIstring1 string2\fR
.
Perform a character-by-character comparison of strings \fIstring1\fR
and \fIstring2\fR.  Returns \-1, 0, or 1, depending on whether
\fIstring1\fR is lexicographically less than, equal to, or greater
than \fIstring2\fR.  If \fB\-length\fR is specified, then only the

Changes to generic/tclCmdMZ.c.

2834
2835
2836
2837
2838
2839
2840






































































2841
2842
2843
2844
2845
2846
2847
....
3326
3327
3328
3329
3330
3331
3332

3333
3334
3335
3336
3337
3338
3339
	    Tcl_NewIntObj((match > 0) ? 1 : (match < 0) ? -1 : 0));
    return TCL_OK;
}
 
/*
 *----------------------------------------------------------------------
 *






































































 * StringBytesCmd --
 *
 *	This procedure is invoked to process the "string bytelength" Tcl
 *	command. See the user documentation for details on what it does. Note
 *	that this command only functions correctly on properly formed Tcl UTF
 *	strings.
 *
................................................................................

Tcl_Command
TclInitStringCmd(
    Tcl_Interp *interp)		/* Current interpreter. */
{
    static const EnsembleImplMap stringImplMap[] = {
	{"bytelength",	StringBytesCmd,	TclCompileBasic1ArgCmd, NULL, NULL, 0},

	{"compare",	StringCmpCmd,	TclCompileStringCmpCmd, NULL, NULL, 0},
	{"equal",	StringEqualCmd,	TclCompileStringEqualCmd, NULL, NULL, 0},
	{"first",	StringFirstCmd,	TclCompileStringFirstCmd, NULL, NULL, 0},
	{"index",	StringIndexCmd,	TclCompileStringIndexCmd, NULL, NULL, 0},
	{"is",		StringIsCmd,	TclCompileStringIsCmd, NULL, NULL, 0},
	{"last",	StringLastCmd,	TclCompileStringLastCmd, NULL, NULL, 0},
	{"length",	StringLenCmd,	TclCompileStringLenCmd, NULL, NULL, 0},






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







 







>







2834
2835
2836
2837
2838
2839
2840
2841
2842
2843
2844
2845
2846
2847
2848
2849
2850
2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
....
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410
	    Tcl_NewIntObj((match > 0) ? 1 : (match < 0) ? -1 : 0));
    return TCL_OK;
}
 
/*
 *----------------------------------------------------------------------
 *
 * StringCatCmd --
 *
 *	This procedure is invoked to process the "string cat" Tcl command.
 *	See the user documentation for details on what it does.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	See the user documentation.
 *
 *----------------------------------------------------------------------
 */

static int
StringCatCmd(
    ClientData dummy,		/* Not used. */
    Tcl_Interp *interp,		/* Current interpreter. */
    int objc,			/* Number of arguments. */
    Tcl_Obj *const objv[])	/* Argument objects. */
{
    int tot, i, length;
    char *bytes, *p;
    Tcl_Obj *objResultPtr;

    /*
     * NOTE: this implementation aims for simplicity, not speed, because all
     * speed-critical uses of [string cat] will involve the compiled variant
     * anyway. Thus we avoid code duplication (from TEBC/INST_CONCAT1) without
     * sacrificing perf.
     */
	
    if (objc < 2) {
	/*
	 * If there are no args, the result is an empty object.
	 * Just leave the preset empty interp result.
	 */
	return TCL_OK;
    }
    tot = 0;
    for(i = 1;i < objc;i++) {
	bytes = TclGetStringFromObj(objv[i], &length);
	if (bytes != NULL) {
	    tot += length;
	}
    }
    if (tot < 0) {
	/* TODO: convert panic to error ? */
	Tcl_Panic("max size for a Tcl value (%d bytes) exceeded", INT_MAX);
    }
    p = ckalloc(tot + 1);
    TclNewObj(objResultPtr);
    objResultPtr->bytes = p;
    objResultPtr->length = tot;
    for (i = 1;i < objc;i++) {
	bytes = TclGetStringFromObj(objv[i], &length);
	if (bytes != NULL) {
	    memcpy(p, bytes, (size_t) length);
	    p += length;
	}
    }
    *p = '\0';
    Tcl_SetObjResult(interp,objResultPtr);
    
    return TCL_OK;
}
 
/*
 *----------------------------------------------------------------------
 *
 * StringBytesCmd --
 *
 *	This procedure is invoked to process the "string bytelength" Tcl
 *	command. See the user documentation for details on what it does. Note
 *	that this command only functions correctly on properly formed Tcl UTF
 *	strings.
 *
................................................................................

Tcl_Command
TclInitStringCmd(
    Tcl_Interp *interp)		/* Current interpreter. */
{
    static const EnsembleImplMap stringImplMap[] = {
	{"bytelength",	StringBytesCmd,	TclCompileBasic1ArgCmd, NULL, NULL, 0},
	{"cat",		StringCatCmd,	TclCompileStringCatCmd, NULL, NULL, 0},
	{"compare",	StringCmpCmd,	TclCompileStringCmpCmd, NULL, NULL, 0},
	{"equal",	StringEqualCmd,	TclCompileStringEqualCmd, NULL, NULL, 0},
	{"first",	StringFirstCmd,	TclCompileStringFirstCmd, NULL, NULL, 0},
	{"index",	StringIndexCmd,	TclCompileStringIndexCmd, NULL, NULL, 0},
	{"is",		StringIsCmd,	TclCompileStringIsCmd, NULL, NULL, 0},
	{"last",	StringLastCmd,	TclCompileStringLastCmd, NULL, NULL, 0},
	{"length",	StringLenCmd,	TclCompileStringLenCmd, NULL, NULL, 0},

Changes to generic/tclCompCmdsSZ.c.

263
264
265
266
267
268
269

































270
271
272
273
274
275
276
 *
 * Side effects:
 *	Instructions are added to envPtr to execute the "string" command at
 *	runtime.
 *
 *----------------------------------------------------------------------
 */


































int
TclCompileStringCmpCmd(
    Tcl_Interp *interp,		/* Used for error reporting. */
    Tcl_Parse *parsePtr,	/* Points to a parse structure for the command
				 * created by Tcl_ParseCommand. */
    Command *cmdPtr,		/* Points to defintion of command being






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







263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
 *
 * Side effects:
 *	Instructions are added to envPtr to execute the "string" command at
 *	runtime.
 *
 *----------------------------------------------------------------------
 */

int
TclCompileStringCatCmd(
    Tcl_Interp *interp,		/* Used for error reporting. */
    Tcl_Parse *parsePtr,	/* Points to a parse structure for the command
				 * created by Tcl_ParseCommand. */
    Command *cmdPtr,		/* Points to defintion of command being
				 * compiled. */
    CompileEnv *envPtr)		/* Holds resulting instructions. */
{
    int numWords = parsePtr->numWords;
    Tcl_Token *wordTokenPtr = TokenAfter(parsePtr->tokenPtr);
    DefineLineInformation;	/* TIP #280 */

    if (numWords>=2) {
	int i;

	for (i = 1; i < numWords; i++) {
	    CompileWord(envPtr, wordTokenPtr, interp, i);
	    wordTokenPtr = TokenAfter(wordTokenPtr);
	}
	while (numWords > 256) {
	    TclEmitInstInt1(INST_STR_CONCAT1, 255, envPtr);
	    numWords -= 254;	/* concat pushes 1 obj, the result */
	}
	if (numWords > 2) {
	    TclEmitInstInt1(INST_STR_CONCAT1, numWords - 1, envPtr);
	}
    } else {
	PushStringLiteral(envPtr, "");
    }
    return TCL_OK;
}

int
TclCompileStringCmpCmd(
    Tcl_Interp *interp,		/* Used for error reporting. */
    Tcl_Parse *parsePtr,	/* Points to a parse structure for the command
				 * created by Tcl_ParseCommand. */
    Command *cmdPtr,		/* Points to defintion of command being

Changes to generic/tclInt.h.

3641
3642
3643
3644
3645
3646
3647



3648
3649
3650
3651
3652
3653
3654
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileReturnCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileSetCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,



			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileStringCmpCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileStringEqualCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);






>
>
>







3641
3642
3643
3644
3645
3646
3647
3648
3649
3650
3651
3652
3653
3654
3655
3656
3657
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileReturnCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileSetCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileStringCatCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileStringCmpCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);
MODULE_SCOPE int	TclCompileStringEqualCmd(Tcl_Interp *interp,
			    Tcl_Parse *parsePtr, Command *cmdPtr,
			    struct CompileEnv *envPtr);

Changes to tests/string.test.

26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
..
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
..
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
....
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
....
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
....
1964
1965
1966
1967
1968
1969
1970
























1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
testConstraint testindexobj [expr {[info commands testindexobj] != {}}]

# Used for constraining memory leak tests
testConstraint memory [llength [info commands memory]]

test string-1.1 {error conditions} {
    list [catch {string gorp a b} msg] $msg
} {1 {unknown or ambiguous subcommand "gorp": must be bytelength, compare, equal, first, index, is, last, length, map, match, range, repeat, replace, reverse, tolower, totitle, toupper, trim, trimleft, trimright, wordend, or wordstart}}
test string-1.2 {error conditions} {
    list [catch {string} msg] $msg
} {1 {wrong # args: should be "string subcommand ?arg ...?"}}

test string-2.1 {string compare, too few args} {
    list [catch {string compare a} msg] $msg
} {1 {wrong # args: should be "string compare ?-nocase? ?-length int? string1 string2"}}
................................................................................
test string-2.5 {string compare with length unspecified} {
    list [catch {string compare -length 10 10} msg] $msg
} {1 {wrong # args: should be "string compare ?-nocase? ?-length int? string1 string2"}}
test string-2.6 {string compare} {
    string compare abcde abdef
} -1
test string-2.7 {string compare, shortest method name} {
    string c abcde ABCDE
} 1
test string-2.8 {string compare} {
    string compare abcde abcde
} 0
test string-2.9 {string compare with length} {
    string compare -length 2 abcde abxyz
} 0
................................................................................
    # translated into a 2 or more bytelength but whose first byte has
    # the high bit set.
} 1
test string-2.13 {string compare -nocase} {
    string compare -nocase abcde abdef
} -1
test string-2.14 {string compare -nocase} {
    string c -nocase abcde ABCDE
} 0
test string-2.15 {string compare -nocase} {
    string compare -nocase abcde abcde
} 0
test string-2.16 {string compare -nocase with length} {
    string compare -length 2 -nocase abcde Abxyz
} 0
................................................................................
} \u1361ABC

test string-20.1 {string trimright errors} {
    list [catch {string trimright} msg] $msg
} {1 {wrong # args: should be "string trimright string ?chars?"}}
test string-20.2 {string trimright errors} {
    list [catch {string trimg a} msg] $msg
} {1 {unknown or ambiguous subcommand "trimg": must be bytelength, compare, equal, first, index, is, last, length, map, match, range, repeat, replace, reverse, tolower, totitle, toupper, trim, trimleft, trimright, wordend, or wordstart}}
test string-20.3 {string trimright} {
    string trimright "    XYZ      "
} {    XYZ}
test string-20.4 {string trimright} {
    string trimright "   "
} {}
test string-20.5 {string trimright} {
................................................................................
} 3
test string-21.14 {string wordend, unicode} {
    string wordend "\uc700\uc700 abc" 8
} 6

test string-22.1 {string wordstart} {
    list [catch {string word a} msg] $msg
} {1 {unknown or ambiguous subcommand "word": must be bytelength, compare, equal, first, index, is, last, length, map, match, range, repeat, replace, reverse, tolower, totitle, toupper, trim, trimleft, trimright, wordend, or wordstart}}
test string-22.2 {string wordstart} {
    list [catch {string wordstart a} msg] $msg
} {1 {wrong # args: should be "string wordstart string index"}}
test string-22.3 {string wordstart} {
    list [catch {string wordstart a b c} msg] $msg
} {1 {wrong # args: should be "string wordstart string index"}}
test string-22.4 {string wordstart} {
................................................................................
test string-28.12 {tcl::prefix longest} {
    tcl::prefix longest {apa {} appa} {}
} {}
test string-28.13 {tcl::prefix longest} {
    # Test UTF8 handling
    tcl::prefix longest {ax\x90 bep ax\x91} a
} ax

























# cleanup
rename MemStress {}
catch {rename foo {}}
::tcltest::cleanupTests
return

# Local Variables:
# mode: tcl
# End:






|







 







|







 







|







 







|







 







|







 







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










26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
..
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
..
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
....
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
....
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
....
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
testConstraint testindexobj [expr {[info commands testindexobj] != {}}]

# Used for constraining memory leak tests
testConstraint memory [llength [info commands memory]]

test string-1.1 {error conditions} {
    list [catch {string gorp a b} msg] $msg
} {1 {unknown or ambiguous subcommand "gorp": must be bytelength, cat, compare, equal, first, index, is, last, length, map, match, range, repeat, replace, reverse, tolower, totitle, toupper, trim, trimleft, trimright, wordend, or wordstart}}
test string-1.2 {error conditions} {
    list [catch {string} msg] $msg
} {1 {wrong # args: should be "string subcommand ?arg ...?"}}

test string-2.1 {string compare, too few args} {
    list [catch {string compare a} msg] $msg
} {1 {wrong # args: should be "string compare ?-nocase? ?-length int? string1 string2"}}
................................................................................
test string-2.5 {string compare with length unspecified} {
    list [catch {string compare -length 10 10} msg] $msg
} {1 {wrong # args: should be "string compare ?-nocase? ?-length int? string1 string2"}}
test string-2.6 {string compare} {
    string compare abcde abdef
} -1
test string-2.7 {string compare, shortest method name} {
    string co abcde ABCDE
} 1
test string-2.8 {string compare} {
    string compare abcde abcde
} 0
test string-2.9 {string compare with length} {
    string compare -length 2 abcde abxyz
} 0
................................................................................
    # translated into a 2 or more bytelength but whose first byte has
    # the high bit set.
} 1
test string-2.13 {string compare -nocase} {
    string compare -nocase abcde abdef
} -1
test string-2.14 {string compare -nocase} {
    string compare -nocase abcde ABCDE
} 0
test string-2.15 {string compare -nocase} {
    string compare -nocase abcde abcde
} 0
test string-2.16 {string compare -nocase with length} {
    string compare -length 2 -nocase abcde Abxyz
} 0
................................................................................
} \u1361ABC

test string-20.1 {string trimright errors} {
    list [catch {string trimright} msg] $msg
} {1 {wrong # args: should be "string trimright string ?chars?"}}
test string-20.2 {string trimright errors} {
    list [catch {string trimg a} msg] $msg
} {1 {unknown or ambiguous subcommand "trimg": must be bytelength, cat, compare, equal, first, index, is, last, length, map, match, range, repeat, replace, reverse, tolower, totitle, toupper, trim, trimleft, trimright, wordend, or wordstart}}
test string-20.3 {string trimright} {
    string trimright "    XYZ      "
} {    XYZ}
test string-20.4 {string trimright} {
    string trimright "   "
} {}
test string-20.5 {string trimright} {
................................................................................
} 3
test string-21.14 {string wordend, unicode} {
    string wordend "\uc700\uc700 abc" 8
} 6

test string-22.1 {string wordstart} {
    list [catch {string word a} msg] $msg
} {1 {unknown or ambiguous subcommand "word": must be bytelength, cat, compare, equal, first, index, is, last, length, map, match, range, repeat, replace, reverse, tolower, totitle, toupper, trim, trimleft, trimright, wordend, or wordstart}}
test string-22.2 {string wordstart} {
    list [catch {string wordstart a} msg] $msg
} {1 {wrong # args: should be "string wordstart string index"}}
test string-22.3 {string wordstart} {
    list [catch {string wordstart a b c} msg] $msg
} {1 {wrong # args: should be "string wordstart string index"}}
test string-22.4 {string wordstart} {
................................................................................
test string-28.12 {tcl::prefix longest} {
    tcl::prefix longest {apa {} appa} {}
} {}
test string-28.13 {tcl::prefix longest} {
    # Test UTF8 handling
    tcl::prefix longest {ax\x90 bep ax\x91} a
} ax

test string-29.1 {string cat, no arg} {
    string cat
} ""
test string-29.2 {string cat, single arg} {
    set x [pid]
    string compare $x [string cat $x]
} 0
test string-29.3 {string cat, two args} {
    set x [pid]
    string compare $x$x [string cat $x $x]
} 0
test string-29.4 {string cat, many args} {
    set x [pid]
    set n 260
    set xx [string repeat $x $n]
    set vv [string repeat {$x} $n]
    set vvs [string repeat {$x } $n]
    set r1 [string compare $xx [subst $vv]]
    set r2 [string compare $xx [eval "string cat $vvs"]]
    list $r1 $r2
} {0 0}



# cleanup
rename MemStress {}
catch {rename foo {}}
::tcltest::cleanupTests
return

# Local Variables:
# mode: tcl
# End:

Changes to tests/stringComp.test.

42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
...
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
...
731
732
733
734
735
736
737


































738
739
740
741
742
743
744
745
746
	return [expr {$end - $tmp}]
    }
}
 
test stringComp-1.1 {error conditions} {
    proc foo {} {string gorp a b}
    list [catch {foo} msg] $msg
} {1 {unknown or ambiguous subcommand "gorp": must be bytelength, compare, equal, first, index, is, last, length, map, match, range, repeat, replace, reverse, tolower, totitle, toupper, trim, trimleft, trimright, wordend, or wordstart}}
test stringComp-1.2 {error conditions} {
    proc foo {} {string}
    list [catch {foo} msg] $msg
} {1 {wrong # args: should be "string subcommand ?arg ...?"}}
test stringComp-1.3 {error condition - undefined method during compile} {
    # We don't want this to complain about 'never' because it may never
    # be called, or string may get redefined.  This must compile OK.
................................................................................
    test stringComp-2.[incr i] "string equal bc, $tname" \
	-body "[list proc foo {} $tbody];foo" \
	-returnCodes $tcode -result $tresult
}

# need a few extra tests short abbr cmd
test stringComp-3.1 {string compare, shortest method name} {
    proc foo {} {string c abcde ABCDE}
    foo
} 1
test stringComp-3.2 {string equal, shortest method name} {
    proc foo {} {string e abcde ABCDE}
    foo
} 0
test stringComp-3.3 {string equal -nocase} {
................................................................................
## not yet bc

## string trim*
## not yet bc

## string word*
## not yet bc


































 
# cleanup
catch {rename foo {}}
::tcltest::cleanupTests
return

# Local Variables:
# mode: tcl
# End:






|







 







|







 







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









42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
...
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
...
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
	return [expr {$end - $tmp}]
    }
}
 
test stringComp-1.1 {error conditions} {
    proc foo {} {string gorp a b}
    list [catch {foo} msg] $msg
} {1 {unknown or ambiguous subcommand "gorp": must be bytelength, cat, compare, equal, first, index, is, last, length, map, match, range, repeat, replace, reverse, tolower, totitle, toupper, trim, trimleft, trimright, wordend, or wordstart}}
test stringComp-1.2 {error conditions} {
    proc foo {} {string}
    list [catch {foo} msg] $msg
} {1 {wrong # args: should be "string subcommand ?arg ...?"}}
test stringComp-1.3 {error condition - undefined method during compile} {
    # We don't want this to complain about 'never' because it may never
    # be called, or string may get redefined.  This must compile OK.
................................................................................
    test stringComp-2.[incr i] "string equal bc, $tname" \
	-body "[list proc foo {} $tbody];foo" \
	-returnCodes $tcode -result $tresult
}

# need a few extra tests short abbr cmd
test stringComp-3.1 {string compare, shortest method name} {
    proc foo {} {string co abcde ABCDE}
    foo
} 1
test stringComp-3.2 {string equal, shortest method name} {
    proc foo {} {string e abcde ABCDE}
    foo
} 0
test stringComp-3.3 {string equal -nocase} {
................................................................................
## not yet bc

## string trim*
## not yet bc

## string word*
## not yet bc

## string cat
test stringComp-29.1 {string cat, no arg} {
    proc foo {} {string cat}
    foo
} ""
test stringComp-29.2 {string cat, single arg} {
    proc foo {} {
	set x [pid]
	string compare $x [string cat $x]
    }
    foo
} 0
test stringComp-29.3 {string cat, two args} {
    proc foo {} {
	set x [pid]
	string compare $x$x [string cat $x $x]
    }
    foo
} 0
test stringComp-29.4 {string cat, many args} {
    proc foo {} {
	set x [pid]
	set n 260
	set xx [string repeat $x $n]
	set vv [string repeat {$x} $n]
	set vvs [string repeat {$x } $n]
	set r1 [string compare $xx [subst $vv]]
	set r2 [string compare $xx [eval "string cat $vvs"]]
	list $r1 $r2
    }
    foo
} {0 0}

 
# cleanup
catch {rename foo {}}
::tcltest::cleanupTests
return

# Local Variables:
# mode: tcl
# End: