Tcl Source Code

Check-in [05efac2985]
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:Deal with backslashes in ${...}, change "char" to "character" in error, fix tests.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | tip-465
Files: files | file ages | folders
SHA1: 05efac2985dec778bdde77a42c60f2b786d402f3
User & Date: avl 2017-03-05 19:38:43
Context
2018-03-15
13:40
merge 8.7 check-in: d61fd7f243 user: dgp tags: tip-465
2017-03-05
19:38
Deal with backslashes in ${...}, change "char" to "character" in error, fix tests. check-in: 05efac2985 user: avl tags: tip-465
11:22
cherrypick 3bcf97f766: array index syntax done. ${...} not yet complete wrt backslashes. check-in: 52073ab224 user: avl tags: tip-465
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to generic/tclParse.c.

1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
....
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430

1431
1432







1433
1434
1435
1436
1437
1438
1439
....
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
    int append)			/* Non-zero means append tokens to existing
				 * information in parsePtr; zero means ignore
				 * existing tokens in parsePtr and
				 * reinitialize it. */
{
    Tcl_Token *tokenPtr;
    register const char *src;
    int varIndex, braceCount = 0;
    unsigned array;

    if ((numBytes == 0) || (start == NULL)) {
	return TCL_ERROR;
    }
    if (numBytes < 0) {
	numBytes = strlen(start);
................................................................................
     *	  parentheses is the array element name.
     * 3. The $ sign is followed by something that isn't a letter, digit, or
     *	  underscore: in this case, there is no variable name and the token is
     *	  just "$".
     */

    if (*src == '{') {
        char ch;
	src++;
	numBytes--;
	tokenPtr->type = TCL_TOKEN_TEXT;
	tokenPtr->start = src;
	tokenPtr->numComponents = 0;

	ch = *src;
	while (numBytes && (braceCount>0 || ch != '}')) {

	    if (ch == '{') { braceCount++; }
	    else if (ch == '}') { braceCount--; }







	    numBytes--;
	    src++;
	    ch= *src;
	}
	if (numBytes == 0) {
	    if (parsePtr->interp != NULL) {
		Tcl_SetObjResult(parsePtr->interp, Tcl_NewStringObj(
................................................................................
		parsePtr->errorType = TCL_PARSE_MISSING_PAREN;
		parsePtr->term = src;
		parsePtr->incomplete = 1;
		goto error;
	    } else if ((*parsePtr->term != ')')){
		if (parsePtr->interp != NULL) {
		    Tcl_SetObjResult(parsePtr->interp, Tcl_NewStringObj(
			    "invalid char in array index", -1));
		}
		parsePtr->errorType = TCL_PARSE_SYNTAX;
		parsePtr->term = src;
		goto error;
	    }
	    src = parsePtr->term + 1;
	}






|







 







|








>
|
|
>
>
>
>
>
>
>







 







|







1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
....
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
....
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
    int append)			/* Non-zero means append tokens to existing
				 * information in parsePtr; zero means ignore
				 * existing tokens in parsePtr and
				 * reinitialize it. */
{
    Tcl_Token *tokenPtr;
    register const char *src;
    int varIndex;
    unsigned array;

    if ((numBytes == 0) || (start == NULL)) {
	return TCL_ERROR;
    }
    if (numBytes < 0) {
	numBytes = strlen(start);
................................................................................
     *	  parentheses is the array element name.
     * 3. The $ sign is followed by something that isn't a letter, digit, or
     *	  underscore: in this case, there is no variable name and the token is
     *	  just "$".
     */

    if (*src == '{') {
	char ch; int braceCount = 0;
	src++;
	numBytes--;
	tokenPtr->type = TCL_TOKEN_TEXT;
	tokenPtr->start = src;
	tokenPtr->numComponents = 0;

	ch = *src;
	while (numBytes && (braceCount>0 || ch != '}')) {
	    switch (ch) {
	    case '{': braceCount++; break;
	    case '}': braceCount--; break;
	    case '\\':
		/* if 2 or more left, consume 2, else consume
		   just the \ and let it run into the end */ 
		if (numBytes > 1) {
		   src++; numBytes--;
		}
	    }
	    numBytes--;
	    src++;
	    ch= *src;
	}
	if (numBytes == 0) {
	    if (parsePtr->interp != NULL) {
		Tcl_SetObjResult(parsePtr->interp, Tcl_NewStringObj(
................................................................................
		parsePtr->errorType = TCL_PARSE_MISSING_PAREN;
		parsePtr->term = src;
		parsePtr->incomplete = 1;
		goto error;
	    } else if ((*parsePtr->term != ')')){
		if (parsePtr->interp != NULL) {
		    Tcl_SetObjResult(parsePtr->interp, Tcl_NewStringObj(
			    "invalid character in array index", -1));
		}
		parsePtr->errorType = TCL_PARSE_SYNTAX;
		parsePtr->term = src;
		goto error;
	    }
	    src = parsePtr->term + 1;
	}

Changes to tests/parse.test.

597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
...
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
test parse-12.5 {Tcl_ParseVarName procedure, just a dollar sign} testparsevarname {
    testparsevarname {$abcd} 1 0
} {- {} 0 text {$} 0 abcd}
test parse-12.6 {Tcl_ParseVarName procedure, braced variable name} testparser {
    testparser {${..[]b}cd} 0
} {- {${..[]b}cd} 1 word {${..[]b}cd} 3 variable {${..[]b}} 1 text {..[]b} 0 text cd 0 {}}
test parse-12.7 {Tcl_ParseVarName procedure, braced variable name} testparser {
    testparser "\$\{\{\} " 0
} {- \$\{\{\}\  1 word \$\{\{\} 2 variable \$\{\{\} 1 text \{ 0 {}}
test parse-12.8 {Tcl_ParseVarName procedure, missing close brace} testparser {
    list [catch {testparser "$\{abc" 0} msg] $msg $::errorInfo
} {1 {missing close-brace for variable name} missing\ close-brace\ for\ variable\ name\n\ \ \ \ (remainder\ of\ script:\ \"\{abc\")\n\ \ \ \ invoked\ from\ within\n\"testparser\ \"\$\\\{abc\"\ 0\"}
test parse-12.9 {Tcl_ParseVarName procedure, missing close brace} testparsevarname {
    list [catch {testparsevarname {${bcd}} 4 0} msg] $msg
} {1 {missing close-brace for variable name}}
test parse-12.10 {Tcl_ParseVarName procedure, missing close brace} testparsevarname {
................................................................................
    info complete {a b "cd"xyz}
} 1
test parse-15.16 {CommandComplete procedure} {
    info complete {a b "c $d() d"}
} 1
test parse-15.17 {CommandComplete procedure} {
    info complete {a b "c $dd("}
} 0
test parse-15.18 {CommandComplete procedure} {
    info complete {a b "c \"}
} 0
test parse-15.19 {CommandComplete procedure} {
    info complete {a b "c [d e f]"}
} 1
test parse-15.20 {CommandComplete procedure} {






|
|







 







|







597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
...
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
test parse-12.5 {Tcl_ParseVarName procedure, just a dollar sign} testparsevarname {
    testparsevarname {$abcd} 1 0
} {- {} 0 text {$} 0 abcd}
test parse-12.6 {Tcl_ParseVarName procedure, braced variable name} testparser {
    testparser {${..[]b}cd} 0
} {- {${..[]b}cd} 1 word {${..[]b}cd} 3 variable {${..[]b}} 1 text {..[]b} 0 text cd 0 {}}
test parse-12.7 {Tcl_ParseVarName procedure, braced variable name} testparser {
    testparser "\$\{\{\\\\\}\} " 0
} {- {${{\\}} } 1 word {${{\\}}} 2 variable {${{\\}}} 1 text {{\\}} 0 {}}
test parse-12.8 {Tcl_ParseVarName procedure, missing close brace} testparser {
    list [catch {testparser "$\{abc" 0} msg] $msg $::errorInfo
} {1 {missing close-brace for variable name} missing\ close-brace\ for\ variable\ name\n\ \ \ \ (remainder\ of\ script:\ \"\{abc\")\n\ \ \ \ invoked\ from\ within\n\"testparser\ \"\$\\\{abc\"\ 0\"}
test parse-12.9 {Tcl_ParseVarName procedure, missing close brace} testparsevarname {
    list [catch {testparsevarname {${bcd}} 4 0} msg] $msg
} {1 {missing close-brace for variable name}}
test parse-12.10 {Tcl_ParseVarName procedure, missing close brace} testparsevarname {
................................................................................
    info complete {a b "cd"xyz}
} 1
test parse-15.16 {CommandComplete procedure} {
    info complete {a b "c $d() d"}
} 1
test parse-15.17 {CommandComplete procedure} {
    info complete {a b "c $dd("}
} 1
test parse-15.18 {CommandComplete procedure} {
    info complete {a b "c \"}
} 0
test parse-15.19 {CommandComplete procedure} {
    info complete {a b "c [d e f]"}
} 1
test parse-15.20 {CommandComplete procedure} {

Changes to tests/parseExpr.test.

913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
in expression "...012345678901234567890*"abcdefghijklmnopqrstuv..."}
test parseExpr-21.43 {error message} -body {
    expr "123456789012345678901234567890*\"foobar\$\{abcdefghijklmnopqrstuvwxyz\""
} -returnCodes error -result "missing close-brace for variable name
in expression \"...8901234567890*\"foobar\$\{abcdefghijklmnopqrstuv...\""
test parseExpr-21.44 {error message} -body {
    expr {123456789012345678901234567890*"foo$bar(abcdefghijklmnopqrstuvwxyz"}
} -returnCodes error -result {missing )
in expression "...8901234567890*"foo$bar(abcdefghijklmnopqrstuv..."}
test parseExpr-21.45 {error message} -body {
    expr {123456789012345678901234567890*"foo$bar([{}abcdefghijklmnopqrstuvwxyz])"}
} -returnCodes error -result {extra characters after close-brace
in expression "...234567890*"foo$bar([{}abcdefghijklmnopqrstuv..."}
test parseExpr-21.46 {error message} -body {
    expr {123456789012345678901234567890*"foo$bar([""abcdefghijklmnopqrstuvwxyz])"}
} -returnCodes error -result {extra characters after close-quote






|
|







913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
in expression "...012345678901234567890*"abcdefghijklmnopqrstuv..."}
test parseExpr-21.43 {error message} -body {
    expr "123456789012345678901234567890*\"foobar\$\{abcdefghijklmnopqrstuvwxyz\""
} -returnCodes error -result "missing close-brace for variable name
in expression \"...8901234567890*\"foobar\$\{abcdefghijklmnopqrstuv...\""
test parseExpr-21.44 {error message} -body {
    expr {123456789012345678901234567890*"foo$bar(abcdefghijklmnopqrstuvwxyz"}
} -returnCodes error -result {invalid character in array index
in expression "...8901234567890*"foo$bar(abcdefghijklmnopqrstu..."}
test parseExpr-21.45 {error message} -body {
    expr {123456789012345678901234567890*"foo$bar([{}abcdefghijklmnopqrstuvwxyz])"}
} -returnCodes error -result {extra characters after close-brace
in expression "...234567890*"foo$bar([{}abcdefghijklmnopqrstuv..."}
test parseExpr-21.46 {error message} -body {
    expr {123456789012345678901234567890*"foo$bar([""abcdefghijklmnopqrstuvwxyz])"}
} -returnCodes error -result {extra characters after close-quote