Tcl Source Code

Check-in [01861c022a]
Login

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

Overview
Comment:merge trunk
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | compile-lpop-ledit
Files: files | file ages | folders
SHA3-256: 01861c022a4d5d509b2be19a12b4033e20fda4bb470e0876de76b4c3bc3d9256
User & Date: dkf 2025-06-26 07:56:35.871
Context
2025-06-26
10:32
mark some more commands for future expansion consideration Leaf check-in: 81a8754c40 user: dkf tags: compile-lpop-ledit
07:56
merge trunk check-in: 01861c022a user: dkf tags: compile-lpop-ledit
07:53
Change bytecode flag names to match their related instruction check-in: 37bed52197 user: dkf tags: trunk, main
2025-06-25
13:46
Better disassembly of [lpop]-related flag argument check-in: 5686a13052 user: dkf tags: compile-lpop-ledit
Changes
Unified Diff Ignore Whitespace Patch
Changes to generic/tclCompCmdsGR.c.
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
    for (i=3 ; i<numWords ; i++,tokenPtr=TokenAfter(tokenPtr)) {
	PUSH_TOKEN(		tokenPtr, i);
    }

    /*
     * First operand is count of arguments.
     * Second operand is bitmask
     *  TCL_LREPLACE4_END_IS_LAST - end refers to last element
     *  TCL_LREPLACE4_SINGLE_INDEX - second index is not present
     *     indicating this is a pure insert
     */
    OP41(			LREPLACE, numWords - 1,
					TCL_LREPLACE4_SINGLE_INDEX);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TclCompileLreplaceCmd --







|
|



|







1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
    for (i=3 ; i<numWords ; i++,tokenPtr=TokenAfter(tokenPtr)) {
	PUSH_TOKEN(		tokenPtr, i);
    }

    /*
     * First operand is count of arguments.
     * Second operand is bitmask
     *  TCL_LREPLACE_END_IS_LAST - end refers to last element
     *  TCL_LREPLACE_SINGLE_INDEX - second index is not present
     *     indicating this is a pure insert
     */
    OP41(			LREPLACE, numWords - 1,
					TCL_LREPLACE_SINGLE_INDEX);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TclCompileLreplaceCmd --
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
    for (i=4; i<numWords; i++,tokenPtr=TokenAfter(tokenPtr)) {
	PUSH_TOKEN(		tokenPtr, i);
    }

    /*
     * First operand is count of arguments.
     * Second operand is bitmask
     *  TCL_LREPLACE4_END_IS_LAST - end refers to last element
     */
    OP41(			LREPLACE, numWords - 1,
					TCL_LREPLACE4_END_IS_LAST);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TclCompileLeditCmd --







|


|







1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
    for (i=4; i<numWords; i++,tokenPtr=TokenAfter(tokenPtr)) {
	PUSH_TOKEN(		tokenPtr, i);
    }

    /*
     * First operand is count of arguments.
     * Second operand is bitmask
     *  TCL_LREPLACE_END_IS_LAST - end refers to last element
     */
    OP41(			LREPLACE, numWords - 1,
					TCL_LREPLACE_END_IS_LAST);
    return TCL_OK;
}

/*
 *----------------------------------------------------------------------
 *
 * TclCompileLeditCmd --
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
	OP(			SWAP);
    }
    // Stack: varWords... listValue idx1 idx2 values...

    /*
     * First operand is count of arguments.
     * Second operand is bitmask
     *  TCL_LREPLACE4_END_IS_LAST - end refers to last element
     */
    OP41(			LREPLACE, numWords - 1,
					TCL_LREPLACE4_END_IS_LAST);
    // Stack: varWords... listValue

    /*
     * Write back the updated value. We've prepped the stack exactly right for
     * this to be something we can Just Do at this point.
     */








|


|







1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
	OP(			SWAP);
    }
    // Stack: varWords... listValue idx1 idx2 values...

    /*
     * First operand is count of arguments.
     * Second operand is bitmask
     *  TCL_LREPLACE_END_IS_LAST - end refers to last element
     */
    OP41(			LREPLACE, numWords - 1,
					TCL_LREPLACE_END_IS_LAST);
    // Stack: varWords... listValue

    /*
     * Write back the updated value. We've prepped the stack exactly right for
     * this to be something we can Just Do at this point.
     */

1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
	} else {
	    PUSH(		"end");
	}
    }
    // Stack: value list index
    OP(				DUP);
    // Stack: value list index index
    OP41(			LREPLACE, 3, TCL_LREPLACE4_END_IS_LAST
					| TCL_LREPLACE4_NEED_IN_RANGE);
    // Stack: value newList
    OP4(			STORE_SCALAR, varIdx);
    OP(				POP);
    // Stack: value

    return TCL_OK;
}







|
|







1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
	} else {
	    PUSH(		"end");
	}
    }
    // Stack: value list index
    OP(				DUP);
    // Stack: value list index index
    OP41(			LREPLACE, 3, TCL_LREPLACE_END_IS_LAST
					| TCL_LREPLACE_NEED_IN_RANGE);
    // Stack: value newList
    OP4(			STORE_SCALAR, varIdx);
    OP(				POP);
    // Stack: value

    return TCL_OK;
}
Changes to generic/tclCompile.c.
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
	/* String Less or equal:	push (stknext <= stktop) */
    TCL_INSTRUCTION_ENTRY(
	"strge",		-1),
	/* String Greater or equal:	push (stknext >= stktop) */
    TCL_INSTRUCTION_ENTRY2(
	"lreplace",	  6,	INT_MIN,  OPERAND_UINT4, OPERAND_LRPL1),
	/* Operands: number of arguments, flags
	 * flags: Combination of TCL_LREPLACE4_* flags
	 * Stack: ... listobj index1 ?index2? new1 ... newN => ... newlistobj
	 * where index2 is present only if TCL_LREPLACE_SINGLE_INDEX is not
	 * set in flags. */

    TCL_INSTRUCTION_ENTRY1(
	"constImm",	  5,	-1,	  OPERAND_LVT4),
	/* Create constant. Index into LVT is immediate, value is on stack.







|







864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
	/* String Less or equal:	push (stknext <= stktop) */
    TCL_INSTRUCTION_ENTRY(
	"strge",		-1),
	/* String Greater or equal:	push (stknext >= stktop) */
    TCL_INSTRUCTION_ENTRY2(
	"lreplace",	  6,	INT_MIN,  OPERAND_UINT4, OPERAND_LRPL1),
	/* Operands: number of arguments, flags
	 * flags: Combination of TCL_LREPLACE_* flags
	 * Stack: ... listobj index1 ?index2? new1 ... newN => ... newlistobj
	 * where index2 is present only if TCL_LREPLACE_SINGLE_INDEX is not
	 * set in flags. */

    TCL_INSTRUCTION_ENTRY1(
	"constImm",	  5,	-1,	  OPERAND_LVT4),
	/* Create constant. Index into LVT is immediate, value is on stack.
Changes to generic/tclCompile.h.
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
    OPERAND_LIT1,		/* One byte unsigned index into table of
				 * literals. */
    OPERAND_LIT4,		/* Four byte unsigned index into table of
				 * literals. */
    OPERAND_SCLS1,		/* Index into tclStringClassTable. */
    OPERAND_UNSF1,		/* Flags for [unset] */
    OPERAND_CLK1,		/* Index into [clock] types. */
    OPERAND_LRPL1		/* Combination of TCL_LREPLACE4_* flags. */
} InstOperandType;

typedef struct InstructionDesc {
    const char *name;		/* Name of instruction. */
    int numBytes;		/* Total number of bytes for instruction. */
    int stackEffect;		/* The worst-case balance stack effect of the
				 * instruction, used for stack requirements







|







969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
    OPERAND_LIT1,		/* One byte unsigned index into table of
				 * literals. */
    OPERAND_LIT4,		/* Four byte unsigned index into table of
				 * literals. */
    OPERAND_SCLS1,		/* Index into tclStringClassTable. */
    OPERAND_UNSF1,		/* Flags for [unset] */
    OPERAND_CLK1,		/* Index into [clock] types. */
    OPERAND_LRPL1		/* Combination of TCL_LREPLACE_* flags. */
} InstOperandType;

typedef struct InstructionDesc {
    const char *name;		/* Name of instruction. */
    int numBytes;		/* Total number of bytes for instruction. */
    int stackEffect;		/* The worst-case balance stack effect of the
				 * instruction, used for stack requirements
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
    TCL_NO_ELEMENT = 2		/* Do not push the array element. */
};

/*
 * Flags bits used by lreplace4 instruction
 */
enum Lreplace4Flags {
    TCL_LREPLACE4_END_IS_LAST = 1,	/* "end" refers to last element */
    TCL_LREPLACE4_SINGLE_INDEX = 2,	/* Second index absent (pure insert) */
    TCL_LREPLACE4_NEED_IN_RANGE = 4	/* First index must resolve to real list index */
};

/*
 * Helper functions for jump tables that call other internal API bits.
 */

static inline Tcl_Size







|
|
|







2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
    TCL_NO_ELEMENT = 2		/* Do not push the array element. */
};

/*
 * Flags bits used by lreplace4 instruction
 */
enum Lreplace4Flags {
    TCL_LREPLACE_END_IS_LAST = 1,	/* "end" refers to last element */
    TCL_LREPLACE_SINGLE_INDEX = 2,	/* Second index absent (pure insert) */
    TCL_LREPLACE_NEED_IN_RANGE = 4	/* First index must resolve to real list index */
};

/*
 * Helper functions for jump tables that call other internal API bits.
 */

static inline Tcl_Size
Changes to generic/tclDisassemble.c.
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
	case OPERAND_LRPL1:
	    opnd = TclGetUInt1AtPtr(pc+numBytes);
	    numBytes++;
	    switch (opnd) {
	    case 0:
		Tcl_AppendPrintfToObj(bufferObj, "0 ");
		break;
	    case TCL_LREPLACE4_END_IS_LAST:
		Tcl_AppendPrintfToObj(bufferObj, "endLast ");
		break;
	    case TCL_LREPLACE4_SINGLE_INDEX:
		Tcl_AppendPrintfToObj(bufferObj, "singleIdx ");
		break;
	    case TCL_LREPLACE4_END_IS_LAST | TCL_LREPLACE4_NEED_IN_RANGE:
		Tcl_AppendPrintfToObj(bufferObj, "endLast,indexTest ");
		break;
	    default:
		Tcl_AppendPrintfToObj(bufferObj, "endLast,singleIdx ");
		break;
	    }
	    break;







|


|


|







710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
	case OPERAND_LRPL1:
	    opnd = TclGetUInt1AtPtr(pc+numBytes);
	    numBytes++;
	    switch (opnd) {
	    case 0:
		Tcl_AppendPrintfToObj(bufferObj, "0 ");
		break;
	    case TCL_LREPLACE_END_IS_LAST:
		Tcl_AppendPrintfToObj(bufferObj, "endLast ");
		break;
	    case TCL_LREPLACE_SINGLE_INDEX:
		Tcl_AppendPrintfToObj(bufferObj, "singleIdx ");
		break;
	    case TCL_LREPLACE_END_IS_LAST | TCL_LREPLACE_NEED_IN_RANGE:
		Tcl_AppendPrintfToObj(bufferObj, "endLast,indexTest ");
		break;
	    default:
		Tcl_AppendPrintfToObj(bufferObj, "endLast,singleIdx ");
		break;
	    }
	    break;
Changes to generic/tclExecute.c.
5466
5467
5468
5469
5470
5471
5472
5473
5474
5475
5476
5477
5478
5479
5480
5481
5482
5483
5484
5485
5486
5487
5488
5489
5490
5491
5492
5493
5494
5495
5496
5497
5498
5499
	numArgs = TclGetUInt4AtPtr(pc + 1);
	int flags = TclGetInt1AtPtr(pc + 5);

	/* Stack: ... listobj index1 ?index2? new1 ... newN */
	valuePtr = OBJ_AT_DEPTH(numArgs - 1);

	/* haveSecondIndex==0 => pure insert */
	int haveSecondIndex = (flags & TCL_LREPLACE4_SINGLE_INDEX) == 0;
	size_t numNewElems = numArgs - 2 - haveSecondIndex;

	/* end_indicator==1 => "end" is last element's index, 0=>index beyond */
	int endIndicator = (flags & TCL_LREPLACE4_END_IS_LAST) != 0;
	Tcl_Obj *fromIdxObj = OBJ_AT_DEPTH(numArgs - 2);
	Tcl_Obj *toIdxObj = haveSecondIndex ? OBJ_AT_DEPTH(numArgs - 3) : NULL;
	if (Tcl_ListObjLength(interp, valuePtr, &length) != TCL_OK) {
	    TRACE_ERROR(interp);
	    goto gotError;
	}

	DECACHE_STACK_INFO();
	if (TclGetIntForIndexM(interp, fromIdxObj, length - endIndicator,
		&fromIdx) != TCL_OK) {
	    CACHE_STACK_INFO();
	    TRACE_ERROR(interp);
	    goto gotError;
	}
	if (flags & TCL_LREPLACE4_NEED_IN_RANGE) {
	    if (fromIdx < 0 || fromIdx >= length) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"index \"%s\" out of range", Tcl_GetString(fromIdxObj)));
		Tcl_SetErrorCode(interp, "TCL", "VALUE", "INDEX", "OUTOFRANGE",
			(char *)NULL);
		CACHE_STACK_INFO();
		TRACE_ERROR(interp);







|



|














|







5466
5467
5468
5469
5470
5471
5472
5473
5474
5475
5476
5477
5478
5479
5480
5481
5482
5483
5484
5485
5486
5487
5488
5489
5490
5491
5492
5493
5494
5495
5496
5497
5498
5499
	numArgs = TclGetUInt4AtPtr(pc + 1);
	int flags = TclGetInt1AtPtr(pc + 5);

	/* Stack: ... listobj index1 ?index2? new1 ... newN */
	valuePtr = OBJ_AT_DEPTH(numArgs - 1);

	/* haveSecondIndex==0 => pure insert */
	int haveSecondIndex = (flags & TCL_LREPLACE_SINGLE_INDEX) == 0;
	size_t numNewElems = numArgs - 2 - haveSecondIndex;

	/* end_indicator==1 => "end" is last element's index, 0=>index beyond */
	int endIndicator = (flags & TCL_LREPLACE_END_IS_LAST) != 0;
	Tcl_Obj *fromIdxObj = OBJ_AT_DEPTH(numArgs - 2);
	Tcl_Obj *toIdxObj = haveSecondIndex ? OBJ_AT_DEPTH(numArgs - 3) : NULL;
	if (Tcl_ListObjLength(interp, valuePtr, &length) != TCL_OK) {
	    TRACE_ERROR(interp);
	    goto gotError;
	}

	DECACHE_STACK_INFO();
	if (TclGetIntForIndexM(interp, fromIdxObj, length - endIndicator,
		&fromIdx) != TCL_OK) {
	    CACHE_STACK_INFO();
	    TRACE_ERROR(interp);
	    goto gotError;
	}
	if (flags & TCL_LREPLACE_NEED_IN_RANGE) {
	    if (fromIdx < 0 || fromIdx >= length) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf(
			"index \"%s\" out of range", Tcl_GetString(fromIdxObj)));
		Tcl_SetErrorCode(interp, "TCL", "VALUE", "INDEX", "OUTOFRANGE",
			(char *)NULL);
		CACHE_STACK_INFO();
		TRACE_ERROR(interp);
Added library/encoding/cp165.enc.








































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# Encoding file: cp165, single-byte
S
003F 0 1
00
0000000100020003000400050006000700080009000A000B000C000D000E000F
0010001100120013001400150016001700180019001A001B001C001D001E001F
00200021002200230024066A0026002700280029002A002B002C002D002E002F
0030003100320033003400350036003700380039003A003B003C003D003E003F
0040004100420043004400450046004700480049004A004B004C004D004E004F
0050005100520053005400550056005700580059005A005B005C005D005E005F
0060006100620063006400650066006700680069006A006B006C006D006E006F
0070007100720073007400750076007700780079007A007B007C007D007E007F
00B000B72219221A259225002502253C2524252C251C25342510250C25142518
03B2221E03C600B100BD00BC224800AB00BBFEF7FEF8FEF9FEFAFEFBFEFCFE73
00A000ADFE8200A300A4FE84FE87FE88FE8EFE8FFE95FE99060CFE9DFEA1FEA5
0660066106620663066406650666066706680669FED1061BFEB1FEB5FEB9061F
00A2FE80FE81FE83FE85FECAFE8BFE8DFE91FE93FE97FE9BFE9FFEA3FEA7FEA9
FEABFEADFEAFFEB3FEB7FEBBFEBFFEC1FEC5FECBFECF00A600AC00F700D7FEC9
0640FED3FED7FEDBFEDFFEE3FEE7FEEBFEEDFEEFFEF3FEBDFECCFECEFECDFEE1
FE7D0651FEE5FEE9FEECFEF0FEF2FED0FED5FEF5FEF6FEDDFED9FEF125A000A0
Changes to library/encoding/cp864.enc.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# Encoding file: cp864, single-byte
S
003F 0 1
00
0000000100020003000400050006000700080009000A000B000C000D000E000F
0010001100120013001400150016001700180019001A001B001C001D001E001F
00200021002200230024066A0026002700280029002A002B002C002D002E002F
0030003100320033003400350036003700380039003A003B003C003D003E003F
0040004100420043004400450046004700480049004A004B004C004D004E004F
0050005100520053005400550056005700580059005A005B005C005D005E005F
0060006100620063006400650066006700680069006A006B006C006D006E006F
0070007100720073007400750076007700780079007A007B007C007D007E007F
00B000B72219221A259225002502253C2524252C251C25342510250C25142518
03B2221E03C600B100BD00BC224800AB00BBFEF7FEF800000000FEFBFEFC0000
00A000ADFE8200A300A4FE8400000000FE8EFE8FFE95FE99060CFE9DFEA1FEA5
0660066106620663066406650666066706680669FED1061BFEB1FEB5FEB9061F
00A2FE80FE81FE83FE85FECAFE8BFE8DFE91FE93FE97FE9BFE9FFEA3FEA7FEA9
FEABFEADFEAFFEB3FEB7FEBBFEBFFEC1FEC5FECBFECF00A600AC00F700D7FEC9
0640FED3FED7FEDBFEDFFEE3FEE7FEEBFEEDFEEFFEF3FEBDFECCFECEFECDFEE1
FE7D0651FEE5FEE9FEECFEF0FEF2FED0FED5FEF5FEF6FEDDFED9FEF125A00000













|
|





1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# Encoding file: cp864, single-byte
S
003F 0 1
00
0000000100020003000400050006000700080009000A000B000C000D000E000F
0010001100120013001400150016001700180019001A001B001C001D001E001F
00200021002200230024066A0026002700280029002A002B002C002D002E002F
0030003100320033003400350036003700380039003A003B003C003D003E003F
0040004100420043004400450046004700480049004A004B004C004D004E004F
0050005100520053005400550056005700580059005A005B005C005D005E005F
0060006100620063006400650066006700680069006A006B006C006D006E006F
0070007100720073007400750076007700780079007A007B007C007D007E007F
00B000B72219221A259225002502253C2524252C251C25342510250C25142518
03B2221E03C600B100BD00BC224800AB00BBFEF7FEF800000000FEFBFEFCFE73
00A000ADFE8200A300A4FE84000020ACFE8EFE8FFE95FE99060CFE9DFEA1FEA5
0660066106620663066406650666066706680669FED1061BFEB1FEB5FEB9061F
00A2FE80FE81FE83FE85FECAFE8BFE8DFE91FE93FE97FE9BFE9FFEA3FEA7FEA9
FEABFEADFEAFFEB3FEB7FEBBFEBFFEC1FEC5FECBFECF00A600AC00F700D7FEC9
0640FED3FED7FEDBFEDFFEE3FEE7FEEBFEEDFEEFFEF3FEBDFECCFECEFECDFEE1
FE7D0651FEE5FEE9FEECFEF0FEF2FED0FED5FEF5FEF6FEDDFED9FEF125A00000
Changes to tests/aaa_exit.test.
12
13
14
15
16
17
18




19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.

if {"::tcltest" ni [namespace children]} {
    package require tcltest 2.5
    namespace import -force ::tcltest::*
}





test exit-1.1 {normal, quick exit} {
    set f [open "|[interpreter] << \"exec [interpreter] << {set ::env(TCL_FINALIZE_ON_EXIT) 0;exit}\"" r]
    set aft [after 1000 {set done "Quick exit hangs !!!"}]
    fileevent $f readable {after cancel $aft;set done OK}
    vwait done
    if {$done != "OK"} {
	fconfigure $f -blocking 0
	close $f
    } else {
	if {[catch {close $f} err]} {
	    set done "Quick exit misbehaves: $err"
	}
    }
    set done
} OK

test exit-1.2 {full-finalized exit} {
    set f [open "|[interpreter] << \"exec [interpreter] << {set ::env(TCL_FINALIZE_ON_EXIT) 1;exit}\"" r]
    set aft [after 1000 {set done "Full-finalized exit hangs !!!"}]
    fileevent $f readable {after cancel $aft;set done OK}
    vwait done
    if {$done != "OK"} {
	fconfigure $f -blocking 0
	close $f
    } else {
	if {[catch {close $f} err]} {
	    set done "Full-finalized exit misbehaves: $err"
	}
    }
    set done
} OK


# cleanup
::tcltest::cleanupTests
return







>
>
>
>
|













|

|













|





12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.

if {"::tcltest" ni [namespace children]} {
    package require tcltest 2.5
    namespace import -force ::tcltest::*
}

testConstraint noappverifier [expr {
        [llength [info commands testappverifierpresent]] == 0
        || ![testappverifierpresent]}]

test exit-1.1 {normal, quick exit} -constraints noappverifier -body {
    set f [open "|[interpreter] << \"exec [interpreter] << {set ::env(TCL_FINALIZE_ON_EXIT) 0;exit}\"" r]
    set aft [after 1000 {set done "Quick exit hangs !!!"}]
    fileevent $f readable {after cancel $aft;set done OK}
    vwait done
    if {$done != "OK"} {
	fconfigure $f -blocking 0
	close $f
    } else {
	if {[catch {close $f} err]} {
	    set done "Quick exit misbehaves: $err"
	}
    }
    set done
} -result OK

test exit-1.2 {full-finalized exit} -constraints noappverifier -body {
    set f [open "|[interpreter] << \"exec [interpreter] << {set ::env(TCL_FINALIZE_ON_EXIT) 1;exit}\"" r]
    set aft [after 1000 {set done "Full-finalized exit hangs !!!"}]
    fileevent $f readable {after cancel $aft;set done OK}
    vwait done
    if {$done != "OK"} {
	fconfigure $f -blocking 0
	close $f
    } else {
	if {[catch {close $f} err]} {
	    set done "Full-finalized exit misbehaves: $err"
	}
    }
    set done
} -result OK


# cleanup
::tcltest::cleanupTests
return
Changes to tests/chanio.test.
14
15
16
17
18
19
20




21
22
23
24
25
26
27
# this file, and for a DISCLAIMER OF ALL WARRANTIES.

if {"::tcltest" ni [namespace children]} {
    package require tcltest 2.5
    namespace import -force ::tcltest::*
}





namespace eval ::tcl::test::io {

    if {"::tcltest" ni [namespace children]} {
	package require tcltest 2.5
	namespace import -force ::tcltest::*
    }








>
>
>
>







14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# this file, and for a DISCLAIMER OF ALL WARRANTIES.

if {"::tcltest" ni [namespace children]} {
    package require tcltest 2.5
    namespace import -force ::tcltest::*
}

testConstraint noappverifier [expr {
        [llength [info commands testappverifierpresent]] == 0
        || ![testappverifierpresent]}]

namespace eval ::tcl::test::io {

    if {"::tcltest" ni [namespace children]} {
	package require tcltest 2.5
	namespace import -force ::tcltest::*
    }

1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
    list [chan gets $f line] $line [chan gets $f line] $line [chan gets $f line] $line
} -cleanup {
    chan close $f
} -result [list 8 "there一ok" 11 "丁more bytes" 4 "here"]
test chan-io-6.56 {Tcl_GetsObj: incomplete lines should disable file events} -setup {
    update
    variable x {}
} -constraints {stdio fileevent} -body {
    set f [openpipe w+ $path(cat)]
    chan configure $f -buffering none
    chan puts -nonewline $f "foobar"
    chan configure $f -blocking 0
    after 500 [namespace code {
	lappend x timeout
    }]







|







1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
    list [chan gets $f line] $line [chan gets $f line] $line [chan gets $f line] $line
} -cleanup {
    chan close $f
} -result [list 8 "there一ok" 11 "丁more bytes" 4 "here"]
test chan-io-6.56 {Tcl_GetsObj: incomplete lines should disable file events} -setup {
    update
    variable x {}
} -constraints {stdio fileevent noappverifier} -body {
    set f [openpipe w+ $path(cat)]
    chan configure $f -buffering none
    chan puts -nonewline $f "foobar"
    chan configure $f -blocking 0
    after 500 [namespace code {
	lappend x timeout
    }]
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
    chan read $f
} -cleanup {
    chan close $f
} -result "abcd\ndef\nfgh"
test chan-io-13.6 {TranslateInputEOL: auto mode: saw cr in last segment} -setup {
    variable x {}
    variable y {}
} -constraints {stdio testchannel fileevent} -body {
    # (chanPtr->flags & INPUT_SAW_CR)
    # This test may fail on slower machines.
    set f [openpipe w+ $path(cat)]
    chan configure $f -blocking 0 -buffering none -translation {auto lf}
    chan event $f read [namespace code {
	lappend x [chan read $f] [testchannel queuedcr $f]
    }]







|







1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
    chan read $f
} -cleanup {
    chan close $f
} -result "abcd\ndef\nfgh"
test chan-io-13.6 {TranslateInputEOL: auto mode: saw cr in last segment} -setup {
    variable x {}
    variable y {}
} -constraints {stdio testchannel fileevent noappverifier} -body {
    # (chanPtr->flags & INPUT_SAW_CR)
    # This test may fail on slower machines.
    set f [openpipe w+ $path(cat)]
    chan configure $f -blocking 0 -buffering none -translation {auto lf}
    chan event $f read [namespace code {
	lappend x [chan read $f] [testchannel queuedcr $f]
    }]
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
    set cat [makeFile {
	fconfigure stdout -buffering line
	while {[gets stdin line] >= 0} {puts $line}
	puts DONE
	exit 0
    } cat.tcl]
    variable done
} -body {
    set ff [openpipe r+ $cat]
    puts $ff Hey
    close $ff w
    set timer [after 1000 [namespace code {set done Failed}]]
    set acc {}
    fileevent $ff readable [namespace code {
	if {[gets $ff line] < 0} {







|







2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
    set cat [makeFile {
	fconfigure stdout -buffering line
	while {[gets stdin line] >= 0} {puts $line}
	puts DONE
	exit 0
    } cat.tcl]
    variable done
} -constraints noappverifier -body {
    set ff [openpipe r+ $cat]
    puts $ff Hey
    close $ff w
    set timer [after 1000 [namespace code {set done Failed}]]
    set acc {}
    fileevent $ff readable [namespace code {
	if {[gets $ff line] < 0} {
Changes to tests/clock.test.
21
22
23
24
25
26
27







28
29
30
31
32
33
34
    if {[catch {
	    ::tcltest::loadTestedCommands
	}]} {
	# nothing to be done (registry loaded on demand)
    }
}








package require msgcat 1.4

testConstraint detroit \
    [expr {![catch {clock format 0 -timezone :America/Detroit -format %z}]}]
testConstraint y2038 \
    [expr {[clock format 2158894800 -format %z -timezone :America/Detroit] eq {-0400}}]








>
>
>
>
>
>
>







21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
    if {[catch {
	    ::tcltest::loadTestedCommands
	}]} {
	# nothing to be done (registry loaded on demand)
    }
}

# Application Verifier hooks system calls in a way that locale
# detection fails. Disable tests that depend on that if
# it is running.
testConstraint noappverifier [expr {
        [llength [info commands testappverifierpresent]] == 0
        || ![testappverifierpresent]}]

package require msgcat 1.4

testConstraint detroit \
    [expr {![catch {clock format 0 -timezone :America/Detroit -format %z}]}]
testConstraint y2038 \
    [expr {[clock format 2158894800 -format %z -timezone :America/Detroit] eq {-0400}}]

35939
35940
35941
35942
35943
35944
35945
35946
35947
35948
35949
35950
35951
35952
35953
    rename test_add_dst {}
} -result {}

# END testcases30


test clock-31.1 {system locale} \
    -constraints win \
    -setup {
	namespace eval ::tcl::clock {
	    namespace import -force ::testClock::registry
	}
	set noreg [info exists ::tcl::clock::NoRegistry]
	if {$noreg} {unset ::tcl::clock::NoRegistry}
	::tcl::clock::ClearCaches







|







35946
35947
35948
35949
35950
35951
35952
35953
35954
35955
35956
35957
35958
35959
35960
    rename test_add_dst {}
} -result {}

# END testcases30


test clock-31.1 {system locale} \
    -constraints {win noappverifier} \
    -setup {
	namespace eval ::tcl::clock {
	    namespace import -force ::testClock::registry
	}
	set noreg [info exists ::tcl::clock::NoRegistry]
	if {$noreg} {unset ::tcl::clock::NoRegistry}
	::tcl::clock::ClearCaches
35962
35963
35964
35965
35966
35967
35968
35969
35970
35971
35972
35973
35974
35975
35976
	if {$noreg} {set ::tcl::clock::NoRegistry {}}
	::tcl::clock::ClearCaches
    } \
    -result [clock format 0 -timezone :UTC -locale current \
		 -format {%d-%b-%Y}]

test clock-31.2 {system locale} \
    -constraints win \
    -setup {
	namespace eval ::tcl::clock {
	    namespace import -force ::testClock::registry
	}
	set noreg [info exists ::tcl::clock::NoRegistry]
	if {$noreg} {unset ::tcl::clock::NoRegistry}
	::tcl::clock::ClearCaches







|







35969
35970
35971
35972
35973
35974
35975
35976
35977
35978
35979
35980
35981
35982
35983
	if {$noreg} {set ::tcl::clock::NoRegistry {}}
	::tcl::clock::ClearCaches
    } \
    -result [clock format 0 -timezone :UTC -locale current \
		 -format {%d-%b-%Y}]

test clock-31.2 {system locale} \
    -constraints {win noappverifier} \
    -setup {
	namespace eval ::tcl::clock {
	    namespace import -force ::testClock::registry
	}
	set noreg [info exists ::tcl::clock::NoRegistry]
	if {$noreg} {unset ::tcl::clock::NoRegistry}
	::tcl::clock::ClearCaches
35985
35986
35987
35988
35989
35990
35991
35992
35993
35994
35995
35996
35997
35998
35999
	if {$noreg} {set ::tcl::clock::NoRegistry {}}
	::tcl::clock::ClearCaches
    } \
    -result [clock format 0 -timezone :UTC -locale current \
		 -format {the %d' day of %B %Y}]

test clock-31.3 {system locale} \
    -constraints win \
    -setup {
	namespace eval ::tcl::clock {
	    namespace import -force ::testClock::registry
	}
	set noreg [info exists ::tcl::clock::NoRegistry]
	if {$noreg} {unset ::tcl::clock::NoRegistry}
	::tcl::clock::ClearCaches







|







35992
35993
35994
35995
35996
35997
35998
35999
36000
36001
36002
36003
36004
36005
36006
	if {$noreg} {set ::tcl::clock::NoRegistry {}}
	::tcl::clock::ClearCaches
    } \
    -result [clock format 0 -timezone :UTC -locale current \
		 -format {the %d' day of %B %Y}]

test clock-31.3 {system locale} \
    -constraints {win noappverifier} \
    -setup {
	namespace eval ::tcl::clock {
	    namespace import -force ::testClock::registry
	}
	set noreg [info exists ::tcl::clock::NoRegistry]
	if {$noreg} {unset ::tcl::clock::NoRegistry}
	::tcl::clock::ClearCaches
36008
36009
36010
36011
36012
36013
36014
36015
36016
36017
36018
36019
36020
36021
36022
	if {$noreg} {set ::tcl::clock::NoRegistry {}}
	::tcl::clock::ClearCaches
    } \
    -result [clock format 0 -timezone :UTC -locale current \
		 -format {%l:%M:%S %p}]

test clock-31.4 {system locale} \
    -constraints win \
    -setup {
	namespace eval ::tcl::clock {
	    namespace import -force ::testClock::registry
	}
	set noreg [info exists ::tcl::clock::NoRegistry]
	if {$noreg} {unset ::tcl::clock::NoRegistry}
	if { [info exists env(TZ)] } {







|







36015
36016
36017
36018
36019
36020
36021
36022
36023
36024
36025
36026
36027
36028
36029
	if {$noreg} {set ::tcl::clock::NoRegistry {}}
	::tcl::clock::ClearCaches
    } \
    -result [clock format 0 -timezone :UTC -locale current \
		 -format {%l:%M:%S %p}]

test clock-31.4 {system locale} \
    -constraints {win noappverifier} \
    -setup {
	namespace eval ::tcl::clock {
	    namespace import -force ::testClock::registry
	}
	set noreg [info exists ::tcl::clock::NoRegistry]
	if {$noreg} {unset ::tcl::clock::NoRegistry}
	if { [info exists env(TZ)] } {
36045
36046
36047
36048
36049
36050
36051
36052
36053
36054
36055
36056
36057
36058
36059
	if {$noreg} {set ::tcl::clock::NoRegistry {}}
	::tcl::clock::ClearCaches
    } \
    -result [clock format 0 -locale current -timezone EST5 \
		 -format {%d-%b-%Y}]

test clock-31.5 {system locale} \
    -constraints win \
    -setup {
	namespace eval ::tcl::clock {
	    namespace import -force ::testClock::registry
	}
	set noreg [info exists ::tcl::clock::NoRegistry]
	if {$noreg} {unset ::tcl::clock::NoRegistry}
	if { [info exists env(TZ)] } {







|







36052
36053
36054
36055
36056
36057
36058
36059
36060
36061
36062
36063
36064
36065
36066
	if {$noreg} {set ::tcl::clock::NoRegistry {}}
	::tcl::clock::ClearCaches
    } \
    -result [clock format 0 -locale current -timezone EST5 \
		 -format {%d-%b-%Y}]

test clock-31.5 {system locale} \
    -constraints {win noappverifier} \
    -setup {
	namespace eval ::tcl::clock {
	    namespace import -force ::testClock::registry
	}
	set noreg [info exists ::tcl::clock::NoRegistry]
	if {$noreg} {unset ::tcl::clock::NoRegistry}
	if { [info exists env(TZ)] } {
36082
36083
36084
36085
36086
36087
36088
36089
36090
36091
36092
36093
36094
36095
36096
	}
	::tcl::clock::ClearCaches
    } \
    -result [clock format 0 -locale current -timezone EST5 \
		 -format {the %d' day of %B %Y}]

test clock-31.6 {system locale} \
    -constraints win \
    -setup {
	namespace eval ::tcl::clock {
	    namespace import -force ::testClock::registry
	}
	set noreg [info exists ::tcl::clock::NoRegistry]
	if {$noreg} {unset ::tcl::clock::NoRegistry}
	if { [info exists env(TZ)] } {







|







36089
36090
36091
36092
36093
36094
36095
36096
36097
36098
36099
36100
36101
36102
36103
	}
	::tcl::clock::ClearCaches
    } \
    -result [clock format 0 -locale current -timezone EST5 \
		 -format {the %d' day of %B %Y}]

test clock-31.6 {system locale} \
    -constraints {win noappverifier} \
    -setup {
	namespace eval ::tcl::clock {
	    namespace import -force ::testClock::registry
	}
	set noreg [info exists ::tcl::clock::NoRegistry]
	if {$noreg} {unset ::tcl::clock::NoRegistry}
	if { [info exists env(TZ)] } {
37544
37545
37546
37547
37548
37549
37550
37551
37552
37553
37554
37555
37556
37557
37558
	    clock format -86400 -timezone :localtime -format %Y
	} result] $result
    } \
    -match regexp \
    -result {0 1969|1 {localtime failed \(clock value may be too large/small to represent\)}}

test clock-49.2 {regression test - missing time zone file (Bug 1237907)} \
    -constraints win \
    -setup {
	# override the registry so that the test takes place in New York time
	namespace eval ::tcl::clock {
	    namespace import -force ::testClock::registry
	}
	set noreg [info exists ::tcl::clock::NoRegistry]
	if {$noreg} {unset ::tcl::clock::NoRegistry}







|







37551
37552
37553
37554
37555
37556
37557
37558
37559
37560
37561
37562
37563
37564
37565
	    clock format -86400 -timezone :localtime -format %Y
	} result] $result
    } \
    -match regexp \
    -result {0 1969|1 {localtime failed \(clock value may be too large/small to represent\)}}

test clock-49.2 {regression test - missing time zone file (Bug 1237907)} \
    -constraints {win noappverifier} \
    -setup {
	# override the registry so that the test takes place in New York time
	namespace eval ::tcl::clock {
	    namespace import -force ::testClock::registry
	}
	set noreg [info exists ::tcl::clock::NoRegistry]
	if {$noreg} {unset ::tcl::clock::NoRegistry}
Changes to tests/cmdMZ.test.
12
13
14
15
16
17
18




19
20
21
22
23
24
25
# this file, and for a DISCLAIMER OF ALL WARRANTIES.

if {"::tcltest" ni [namespace children]} {
    package require tcltest 2.5
    namespace import -force ::tcltest::*
}





namespace eval ::tcl::test::cmdMZ {
    namespace import ::tcltest::cleanupTests
    namespace import ::tcltest::customMatch
    namespace import ::tcltest::makeFile
    namespace import ::tcltest::removeFile
    namespace import ::tcltest::temporaryDirectory
    namespace import ::tcltest::testConstraint







>
>
>
>







12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# this file, and for a DISCLAIMER OF ALL WARRANTIES.

if {"::tcltest" ni [namespace children]} {
    package require tcltest 2.5
    namespace import -force ::tcltest::*
}

testConstraint noappverifier [expr {
        [llength [info commands testappverifierpresent]] == 0
        || ![testappverifierpresent]}]

namespace eval ::tcl::test::cmdMZ {
    namespace import ::tcltest::cleanupTests
    namespace import ::tcltest::customMatch
    namespace import ::tcltest::makeFile
    namespace import ::tcltest::removeFile
    namespace import ::tcltest::temporaryDirectory
    namespace import ::tcltest::testConstraint
416
417
418
419
420
421
422

423


424
425
426
427
428
429
430
} {1 {missing close-brace}}
test cmdMZ-6.5a {Tcl_TimeRateObjCmd: result format and one iteration} {
    regexp {^\d+(?:\.\d+)? \ws/# 1 # \d+(?:\.\d+)? #/sec \d+(?:\.\d+)? net-ms$} [timerate {} 0]
} 1
test cmdMZ-6.5b {Tcl_TimeRateObjCmd: result format without iterations} {
    regexp {^0 \ws/# 0 # 0 #/sec 0 net-ms$} [timerate {} 0 0]
} 1

test cmdMZ-6.6 {Tcl_TimeRateObjCmd: slower commands take longer, but it remains almost the same time of measurement} -body {


    set m1 [timerate {_nrt_sleep 0.01} 50]
    set m2 [timerate {_nrt_sleep 1.00} 50]
    if {[testConstraint valgrind] && ([lindex $m1 0] >= 100 || [lindex $m1 2] <= 500)} {
	tcltest::Skip "too-slow-by-valgrind"
    }
    list [list \
	[expr {[lindex $m1 0] < [lindex $m2 0]}] \







>
|
>
>







420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
} {1 {missing close-brace}}
test cmdMZ-6.5a {Tcl_TimeRateObjCmd: result format and one iteration} {
    regexp {^\d+(?:\.\d+)? \ws/# 1 # \d+(?:\.\d+)? #/sec \d+(?:\.\d+)? net-ms$} [timerate {} 0]
} 1
test cmdMZ-6.5b {Tcl_TimeRateObjCmd: result format without iterations} {
    regexp {^0 \ws/# 0 # 0 #/sec 0 net-ms$} [timerate {} 0 0]
} 1
test cmdMZ-6.6 {
    Tcl_TimeRateObjCmd: slower commands take longer, but it
    remains almost the same time of measurement
} -constraints noappverifier -body {
    set m1 [timerate {_nrt_sleep 0.01} 50]
    set m2 [timerate {_nrt_sleep 1.00} 50]
    if {[testConstraint valgrind] && ([lindex $m1 0] >= 100 || [lindex $m1 2] <= 500)} {
	tcltest::Skip "too-slow-by-valgrind"
    }
    list [list \
	[expr {[lindex $m1 0] < [lindex $m2 0]}] \
Changes to tests/encoding.test.
308
309
310
311
312
313
314






315
316
317
318
319
320
321
    append x [encoding convertfrom jis0208 8C&A]
} "8C&A乎α"
test encoding-12.5 {LoadTableEncoding: symbol encoding} {
    set x [encoding convertto symbol γ]
    append x [encoding convertto symbol g]
    append x [encoding convertfrom symbol g]
} "ggγ"







test encoding-13.1 {LoadEscapeTable} {
    encoding convertto iso2022 ab乎棙g
} ab\x1B\$B8C\x1B\$\(DD%\x1B(Bg

test encoding-15.1 {UtfToUtfProc} {
    encoding convertto utf-8 £







>
>
>
>
>
>







308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
    append x [encoding convertfrom jis0208 8C&A]
} "8C&A乎α"
test encoding-12.5 {LoadTableEncoding: symbol encoding} {
    set x [encoding convertto symbol γ]
    append x [encoding convertto symbol g]
    append x [encoding convertfrom symbol g]
} "ggγ"
test encoding-12.7 {cp864 [ecafd8611d]} {
    encoding convertfrom cp864 \xA7
} €
test encoding-12.8 {cp165 [ecafd8611d]} {
    encoding convertfrom cp165 \xA7
} ﺈ

test encoding-13.1 {LoadEscapeTable} {
    encoding convertto iso2022 ab乎棙g
} ab\x1B\$B8C\x1B\$\(DD%\x1B(Bg

test encoding-15.1 {UtfToUtfProc} {
    encoding convertto utf-8 £
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
		encoding convertto -profile tcl8 $name $string

		# discard the cached internal representation of Tcl_Encoding
		# Unfortunately, without this, encoding 2-1 fails.
		llength $name
	}
	return $count
} -result 93

runtests

test encoding-bug-183a1adcc0-1 {Bug [183a1adcc0] Buffer overflow Tcl_UtfToExternal} -constraints {
    testencoding
} -body {
    # Note - buffers are initialized to \xFF







|







1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
		encoding convertto -profile tcl8 $name $string

		# discard the cached internal representation of Tcl_Encoding
		# Unfortunately, without this, encoding 2-1 fails.
		llength $name
	}
	return $count
} -result 94

runtests

test encoding-bug-183a1adcc0-1 {Bug [183a1adcc0] Buffer overflow Tcl_UtfToExternal} -constraints {
    testencoding
} -body {
    # Note - buffers are initialized to \xFF
Changes to tests/env.test.
98
99
100
101
102
103
104

105
106
107
108
109
110
111
112
113
114
115
116
117


proc cleanup1 {} {
    encodingrestore
    envrestore
}


variable keep {
    TCL_LIBRARY PATH LD_LIBRARY_PATH LIBPATH PURE_PROG_NAME DISPLAY
    SHLIB_PATH SYSTEMDRIVE SYSTEMROOT DYLD_LIBRARY_PATH DYLD_FRAMEWORK_PATH
    DYLD_NEW_LOCAL_SHARED_REGIONS DYLD_NO_FIX_PREBINDING MSYSTEM
    __CF_USER_TEXT_ENCODING SECURITYSESSIONID LANG WINDIR TERM
    CommonProgramFiles CommonProgramFiles(x86) ProgramFiles
    ProgramFiles(x86) CommonProgramW6432 ProgramW6432
    PROCESSOR_ARCHITECTURE PROCESSOR_ARCHITEW6432 USERPROFILE
    WINECONFIGDIR WINEDATADIR WINEDLLDIR0 WINEHOMEDIR
    WINELOADER WINEUSERLOCALE WINEUSERNAME
}

variable printenvScript [makeFile [string map [list @keep@ [list $keep]] {







>





|







98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118


proc cleanup1 {} {
    encodingrestore
    envrestore
}

# OANOCACHE comes from Application Verifier
variable keep {
    TCL_LIBRARY PATH LD_LIBRARY_PATH LIBPATH PURE_PROG_NAME DISPLAY
    SHLIB_PATH SYSTEMDRIVE SYSTEMROOT DYLD_LIBRARY_PATH DYLD_FRAMEWORK_PATH
    DYLD_NEW_LOCAL_SHARED_REGIONS DYLD_NO_FIX_PREBINDING MSYSTEM
    __CF_USER_TEXT_ENCODING SECURITYSESSIONID LANG WINDIR TERM
    CommonProgramFiles CommonProgramFiles(x86) OANOCACHE ProgramFiles
    ProgramFiles(x86) CommonProgramW6432 ProgramW6432
    PROCESSOR_ARCHITECTURE PROCESSOR_ARCHITEW6432 USERPROFILE
    WINECONFIGDIR WINEDATADIR WINEDLLDIR0 WINEHOMEDIR
    WINELOADER WINEUSERLOCALE WINEUSERNAME
}

variable printenvScript [makeFile [string map [list @keep@ [list $keep]] {
Changes to tools/encoding/cp864.txt.
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
0x98	0x00bb	#RIGHT POINTING GUILLEMET
0x99	0xfef7	#ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE ISOLATED FORM
0x9a	0xfef8	#ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE FINAL FORM
0x9b		#UNDEFINED
0x9c		#UNDEFINED
0x9d	0xfefb	#ARABIC LIGATURE LAM WITH ALEF ISOLATED FORM
0x9e	0xfefc	#ARABIC LIGATURE LAM WITH ALEF FINAL FORM
0x9f		#UNDEFINED
0xa0	0x00a0	#NON-BREAKING SPACE
0xa1	0x00ad	#SOFT HYPHEN
0xa2	0xfe82	#ARABIC LETTER ALEF WITH MADDA ABOVE FINAL FORM
0xa3	0x00a3	#POUND SIGN
0xa4	0x00a4	#CURRENCY SIGN
0xa5	0xfe84	#ARABIC LETTER ALEF WITH HAMZA ABOVE FINAL FORM
0xa6		#UNDEFINED
0xa7		#UNDEFINED
0xa8	0xfe8e	#ARABIC LETTER ALEF FINAL FORM
0xa9	0xfe8f	#ARABIC LETTER BEH ISOLATED FORM
0xaa	0xfe95	#ARABIC LETTER TEH ISOLATED FORM
0xab	0xfe99	#ARABIC LETTER THEH ISOLATED FORM
0xac	0x060c	#ARABIC COMMA
0xad	0xfe9d	#ARABIC LETTER JEEM ISOLATED FORM
0xae	0xfea1	#ARABIC LETTER HAH ISOLATED FORM







|







|







170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
0x98	0x00bb	#RIGHT POINTING GUILLEMET
0x99	0xfef7	#ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE ISOLATED FORM
0x9a	0xfef8	#ARABIC LIGATURE LAM WITH ALEF WITH HAMZA ABOVE FINAL FORM
0x9b		#UNDEFINED
0x9c		#UNDEFINED
0x9d	0xfefb	#ARABIC LIGATURE LAM WITH ALEF ISOLATED FORM
0x9e	0xfefc	#ARABIC LIGATURE LAM WITH ALEF FINAL FORM
0x9f	0xfe73	#ARABIC TAIL FRAGMENT
0xa0	0x00a0	#NON-BREAKING SPACE
0xa1	0x00ad	#SOFT HYPHEN
0xa2	0xfe82	#ARABIC LETTER ALEF WITH MADDA ABOVE FINAL FORM
0xa3	0x00a3	#POUND SIGN
0xa4	0x00a4	#CURRENCY SIGN
0xa5	0xfe84	#ARABIC LETTER ALEF WITH HAMZA ABOVE FINAL FORM
0xa6		#UNDEFINED
0xa7	0x20ac  #EURO SIGN
0xa8	0xfe8e	#ARABIC LETTER ALEF FINAL FORM
0xa9	0xfe8f	#ARABIC LETTER BEH ISOLATED FORM
0xaa	0xfe95	#ARABIC LETTER TEH ISOLATED FORM
0xab	0xfe99	#ARABIC LETTER THEH ISOLATED FORM
0xac	0x060c	#ARABIC COMMA
0xad	0xfe9d	#ARABIC LETTER JEEM ISOLATED FORM
0xae	0xfea1	#ARABIC LETTER HAH ISOLATED FORM
Changes to win/tclWinInt.h.
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
typedef struct TclPipeThreadInfo {
    HANDLE evControl;		/* Auto-reset event used by the main thread to
				 * signal when the pipe thread should attempt
				 * to do read/write operation. Additionally
				 * used as signal to stop (state set to -1) */
    volatile LONG state;	/* Indicates current state of the thread */
    void *clientData;		/* Referenced data of the main thread */
    HANDLE evWakeUp;		/* Optional wake-up event worker set by shutdown */
} TclPipeThreadInfo;

/* If pipe-workers will use some tcl subsystem, we can use Tcl_Alloc without
 * more overhead for finalize thread (should be executed anyway)
 *
 * #define _PTI_USE_CKALLOC 1
 */







<







72
73
74
75
76
77
78

79
80
81
82
83
84
85
typedef struct TclPipeThreadInfo {
    HANDLE evControl;		/* Auto-reset event used by the main thread to
				 * signal when the pipe thread should attempt
				 * to do read/write operation. Additionally
				 * used as signal to stop (state set to -1) */
    volatile LONG state;	/* Indicates current state of the thread */
    void *clientData;		/* Referenced data of the main thread */

} TclPipeThreadInfo;

/* If pipe-workers will use some tcl subsystem, we can use Tcl_Alloc without
 * more overhead for finalize thread (should be executed anyway)
 *
 * #define _PTI_USE_CKALLOC 1
 */
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
    PTI_STATE_STOP = 2,		/* thread should stop work (owns TI structure) */
    PTI_STATE_END = 4,		/* thread should stop work (worker is busy) */
    PTI_STATE_DOWN = 8		/* worker is down */
};

MODULE_SCOPE
TclPipeThreadInfo *	TclPipeThreadCreateTI(TclPipeThreadInfo **pipeTIPtr,
			    void *clientData, HANDLE wakeEvent);
MODULE_SCOPE int	TclPipeThreadWaitForSignal(
			    TclPipeThreadInfo **pipeTIPtr);

static inline void
TclPipeThreadSignal(
    TclPipeThreadInfo **pipeTIPtr)
{







|







96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
    PTI_STATE_STOP = 2,		/* thread should stop work (owns TI structure) */
    PTI_STATE_END = 4,		/* thread should stop work (worker is busy) */
    PTI_STATE_DOWN = 8		/* worker is down */
};

MODULE_SCOPE
TclPipeThreadInfo *	TclPipeThreadCreateTI(TclPipeThreadInfo **pipeTIPtr,
			    void *clientData);
MODULE_SCOPE int	TclPipeThreadWaitForSignal(
			    TclPipeThreadInfo **pipeTIPtr);

static inline void
TclPipeThreadSignal(
    TclPipeThreadInfo **pipeTIPtr)
{
Changes to win/tclWinPipe.c.
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
    if (readFile != NULL) {
	/*
	 * Start the background reader thread.
	 */

	infoPtr->readable = CreateEventW(NULL, TRUE, TRUE, NULL);
	infoPtr->readThread = CreateThread(NULL, 256, PipeReaderThread,
	    TclPipeThreadCreateTI(&infoPtr->readTI, infoPtr, infoPtr->readable),
	    0, NULL);
	SetThreadPriority(infoPtr->readThread, THREAD_PRIORITY_HIGHEST);
	infoPtr->validMask |= TCL_READABLE;
    } else {
	infoPtr->readTI = NULL;
	infoPtr->readThread = 0;
    }
    if (writeFile != NULL) {
	/*
	 * Start the background writer thread.
	 */

	infoPtr->writable = CreateEventW(NULL, TRUE, TRUE, NULL);
	infoPtr->writeThread = CreateThread(NULL, 256, PipeWriterThread,
	    TclPipeThreadCreateTI(&infoPtr->writeTI, infoPtr, infoPtr->writable),
	    0, NULL);
	SetThreadPriority(infoPtr->writeThread, THREAD_PRIORITY_HIGHEST);
	infoPtr->validMask |= TCL_WRITABLE;
    } else {
	infoPtr->writeTI = NULL;
	infoPtr->writeThread = 0;
    }








|
<













|
<







1814
1815
1816
1817
1818
1819
1820
1821

1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835

1836
1837
1838
1839
1840
1841
1842
    if (readFile != NULL) {
	/*
	 * Start the background reader thread.
	 */

	infoPtr->readable = CreateEventW(NULL, TRUE, TRUE, NULL);
	infoPtr->readThread = CreateThread(NULL, 256, PipeReaderThread,
	    TclPipeThreadCreateTI(&infoPtr->readTI, infoPtr), 0, NULL);

	SetThreadPriority(infoPtr->readThread, THREAD_PRIORITY_HIGHEST);
	infoPtr->validMask |= TCL_READABLE;
    } else {
	infoPtr->readTI = NULL;
	infoPtr->readThread = 0;
    }
    if (writeFile != NULL) {
	/*
	 * Start the background writer thread.
	 */

	infoPtr->writable = CreateEventW(NULL, TRUE, TRUE, NULL);
	infoPtr->writeThread = CreateThread(NULL, 256, PipeWriterThread,
	    TclPipeThreadCreateTI(&infoPtr->writeTI, infoPtr), 0, NULL);

	SetThreadPriority(infoPtr->writeThread, THREAD_PRIORITY_HIGHEST);
	infoPtr->validMask |= TCL_WRITABLE;
    } else {
	infoPtr->writeTI = NULL;
	infoPtr->writeThread = 0;
    }

3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
 *
 *----------------------------------------------------------------------
 */

TclPipeThreadInfo *
TclPipeThreadCreateTI(
    TclPipeThreadInfo **pipeTIPtr,
    void *clientData,
    HANDLE wakeEvent)
{
    TclPipeThreadInfo *pipeTI;
#ifndef _PTI_USE_CKALLOC
    pipeTI = (TclPipeThreadInfo *)malloc(sizeof(TclPipeThreadInfo));
#else
    pipeTI = (TclPipeThreadInfo *)Tcl_Alloc(sizeof(TclPipeThreadInfo));
#endif /* !_PTI_USE_CKALLOC */
    pipeTI->evControl = CreateEventW(NULL, FALSE, FALSE, NULL);
    pipeTI->state = PTI_STATE_IDLE;
    pipeTI->clientData = clientData;
    pipeTI->evWakeUp = wakeEvent;
    return (*pipeTIPtr = pipeTI);
}

/*
 *----------------------------------------------------------------------
 *
 * TclPipeThreadWaitForSignal --







|
<










<







3295
3296
3297
3298
3299
3300
3301
3302

3303
3304
3305
3306
3307
3308
3309
3310
3311
3312

3313
3314
3315
3316
3317
3318
3319
 *
 *----------------------------------------------------------------------
 */

TclPipeThreadInfo *
TclPipeThreadCreateTI(
    TclPipeThreadInfo **pipeTIPtr,
    void *clientData)

{
    TclPipeThreadInfo *pipeTI;
#ifndef _PTI_USE_CKALLOC
    pipeTI = (TclPipeThreadInfo *)malloc(sizeof(TclPipeThreadInfo));
#else
    pipeTI = (TclPipeThreadInfo *)Tcl_Alloc(sizeof(TclPipeThreadInfo));
#endif /* !_PTI_USE_CKALLOC */
    pipeTI->evControl = CreateEventW(NULL, FALSE, FALSE, NULL);
    pipeTI->state = PTI_STATE_IDLE;
    pipeTI->clientData = clientData;

    return (*pipeTIPtr = pipeTI);
}

/*
 *----------------------------------------------------------------------
 *
 * TclPipeThreadWaitForSignal --
3337
3338
3339
3340
3341
3342
3343
3344
3345
3346
3347
3348
3349
3350
3351
3352
3353
3354
3355
3356
3357
3358
int
TclPipeThreadWaitForSignal(
    TclPipeThreadInfo **pipeTIPtr)
{
    TclPipeThreadInfo *pipeTI = *pipeTIPtr;
    LONG state;
    DWORD waitResult;
    HANDLE wakeEvent;

    if (!pipeTI) {
	return 0;
    }

    wakeEvent = pipeTI->evWakeUp;

    /*
     * Wait for the main thread to signal before attempting to do the work.
     */

    /*
     * Reset work state of thread (idle/waiting)
     */







<





<
<







3333
3334
3335
3336
3337
3338
3339

3340
3341
3342
3343
3344


3345
3346
3347
3348
3349
3350
3351
int
TclPipeThreadWaitForSignal(
    TclPipeThreadInfo **pipeTIPtr)
{
    TclPipeThreadInfo *pipeTI = *pipeTIPtr;
    LONG state;
    DWORD waitResult;


    if (!pipeTI) {
	return 0;
    }



    /*
     * Wait for the main thread to signal before attempting to do the work.
     */

    /*
     * Reset work state of thread (idle/waiting)
     */
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
  end:
    /*
     * End of work, check the owner of the TI structure.
     */

    if (state != PTI_STATE_STOP) {
	*pipeTIPtr = NULL;
    } else {
	pipeTI->evWakeUp = NULL;
    }
    if (wakeEvent) {
	SetEvent(wakeEvent);
    }
    return 0;
}

/*
 *----------------------------------------------------------------------
 *







<
<
<
<
<







3397
3398
3399
3400
3401
3402
3403





3404
3405
3406
3407
3408
3409
3410
  end:
    /*
     * End of work, check the owner of the TI structure.
     */

    if (state != PTI_STATE_STOP) {
	*pipeTIPtr = NULL;





    }
    return 0;
}

/*
 *----------------------------------------------------------------------
 *
3442
3443
3444
3445
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
    HANDLE evControl;
    int state;

    if (!pipeTI) {
	return 1;
    }
    evControl = pipeTI->evControl;
    pipeTI->evWakeUp = wakeEvent;
    state = InterlockedCompareExchange(&pipeTI->state, PTI_STATE_STOP,
	    PTI_STATE_IDLE);
    switch (state) {
    case PTI_STATE_IDLE:
	/*
	 * Thread was idle/waiting, notify it goes teardown
	 */







<







3430
3431
3432
3433
3434
3435
3436

3437
3438
3439
3440
3441
3442
3443
    HANDLE evControl;
    int state;

    if (!pipeTI) {
	return 1;
    }
    evControl = pipeTI->evControl;

    state = InterlockedCompareExchange(&pipeTI->state, PTI_STATE_STOP,
	    PTI_STATE_IDLE);
    switch (state) {
    case PTI_STATE_IDLE:
	/*
	 * Thread was idle/waiting, notify it goes teardown
	 */
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
    int state;

    if (!pipeTI) {
	return;
    }
    pipeTI = *pipeTIPtr;
    evControl = pipeTI->evControl;
    pipeTI->evWakeUp = NULL;

    /*
     * Try to sane stop the pipe worker, corresponding its current state
     */

    state = InterlockedCompareExchange(&pipeTI->state, PTI_STATE_STOP,
	    PTI_STATE_IDLE);







<







3493
3494
3495
3496
3497
3498
3499

3500
3501
3502
3503
3504
3505
3506
    int state;

    if (!pipeTI) {
	return;
    }
    pipeTI = *pipeTIPtr;
    evControl = pipeTI->evControl;


    /*
     * Try to sane stop the pipe worker, corresponding its current state
     */

    state = InterlockedCompareExchange(&pipeTI->state, PTI_STATE_STOP,
	    PTI_STATE_IDLE);
3658
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
3669
3670
3671
3672
3673
3674
		}
	    }
	}
    }

    *pipeTIPtr = NULL;
    if (pipeTI) {
	if (pipeTI->evWakeUp) {
	    SetEvent(pipeTI->evWakeUp);
	}
	CloseHandle(pipeTI->evControl);
#ifndef _PTI_USE_CKALLOC
	free(pipeTI);
#else
	Tcl_Free(pipeTI);
#endif /* !_PTI_USE_CKALLOC */
    }







<
<
<







3644
3645
3646
3647
3648
3649
3650



3651
3652
3653
3654
3655
3656
3657
		}
	    }
	}
    }

    *pipeTIPtr = NULL;
    if (pipeTI) {



	CloseHandle(pipeTI->evControl);
#ifndef _PTI_USE_CKALLOC
	free(pipeTI);
#else
	Tcl_Free(pipeTI);
#endif /* !_PTI_USE_CKALLOC */
    }
3709
3710
3711
3712
3713
3714
3715
3716
3717
3718
3719
3720
3721
3722
3723
3724
3725
    if (!pipeTI) {
	return;
    }
    *pipeTIPtr = NULL;
    state = InterlockedExchange(&pipeTI->state, PTI_STATE_DOWN);
    if (state == PTI_STATE_STOP) {
	CloseHandle(pipeTI->evControl);
	if (pipeTI->evWakeUp) {
	    SetEvent(pipeTI->evWakeUp);
	}
#ifndef _PTI_USE_CKALLOC
	free(pipeTI);
#else
	Tcl_Free(pipeTI);
	/* be sure all subsystems used are finalized */
	Tcl_FinalizeThread();
#endif /* !_PTI_USE_CKALLOC */







<
<
<







3692
3693
3694
3695
3696
3697
3698



3699
3700
3701
3702
3703
3704
3705
    if (!pipeTI) {
	return;
    }
    *pipeTIPtr = NULL;
    state = InterlockedExchange(&pipeTI->state, PTI_STATE_DOWN);
    if (state == PTI_STATE_STOP) {
	CloseHandle(pipeTI->evControl);



#ifndef _PTI_USE_CKALLOC
	free(pipeTI);
#else
	Tcl_Free(pipeTI);
	/* be sure all subsystems used are finalized */
	Tcl_FinalizeThread();
#endif /* !_PTI_USE_CKALLOC */
Changes to win/tclWinSerial.c.
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
	/*
	 * Initially the channel is writable and the writeThread is idle.
	 */

	infoPtr->osWrite.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
	infoPtr->evWritable = CreateEventW(NULL, TRUE, TRUE, NULL);
	infoPtr->writeThread = CreateThread(NULL, 256, SerialWriterThread,
		TclPipeThreadCreateTI(&infoPtr->writeTI, infoPtr,
			infoPtr->evWritable), 0, NULL);
    }

    Tcl_SetChannelOption(NULL, infoPtr->channel, "-translation", "auto");

    return infoPtr->channel;
}








|
<







1502
1503
1504
1505
1506
1507
1508
1509

1510
1511
1512
1513
1514
1515
1516
	/*
	 * Initially the channel is writable and the writeThread is idle.
	 */

	infoPtr->osWrite.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
	infoPtr->evWritable = CreateEventW(NULL, TRUE, TRUE, NULL);
	infoPtr->writeThread = CreateThread(NULL, 256, SerialWriterThread,
		TclPipeThreadCreateTI(&infoPtr->writeTI, infoPtr), 0, NULL);

    }

    Tcl_SetChannelOption(NULL, infoPtr->channel, "-translation", "auto");

    return infoPtr->channel;
}

Changes to win/tclWinSock.c.
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
	    PostMessageW(tsdPtr->hwnd, SOCKET_TERMINATE, 0, 0);

	    /*
	     * Wait for the thread to exit. This ensures that we are
	     * completely cleaned up before we leave this function.
	     */

	    WaitForSingleObject(tsdPtr->readyEvent, INFINITE);
	    tsdPtr->hwnd = NULL;
	}
	CloseHandle(tsdPtr->socketThread);
	tsdPtr->socketThread = NULL;
    }
    if (tsdPtr->readyEvent != NULL) {
	CloseHandle(tsdPtr->readyEvent);







|







513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
	    PostMessageW(tsdPtr->hwnd, SOCKET_TERMINATE, 0, 0);

	    /*
	     * Wait for the thread to exit. This ensures that we are
	     * completely cleaned up before we leave this function.
	     */

	    WaitForSingleObject(tsdPtr->socketThread, INFINITE);
	    tsdPtr->hwnd = NULL;
	}
	CloseHandle(tsdPtr->socketThread);
	tsdPtr->socketThread = NULL;
    }
    if (tsdPtr->readyEvent != NULL) {
	CloseHandle(tsdPtr->readyEvent);
2188
2189
2190
2191
2192
2193
2194

2195
2196
2197
2198
2199
2200
2201
	 * place to look for bugs.
	 */

	if (bind(sock, addrPtr->ai_addr,
		(socklen_t)addrPtr->ai_addrlen) == SOCKET_ERROR) {
	    Tcl_WinConvertError((DWORD) WSAGetLastError());
	    closesocket(sock);

	    continue;
	}
	if (port == 0 && chosenport == 0) {
	    address sockname;
	    socklen_t namelen = sizeof(sockname);

	    /*







>







2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
	 * place to look for bugs.
	 */

	if (bind(sock, addrPtr->ai_addr,
		(socklen_t)addrPtr->ai_addrlen) == SOCKET_ERROR) {
	    Tcl_WinConvertError((DWORD) WSAGetLastError());
	    closesocket(sock);
	    sock = INVALID_SOCKET; /* Bug [40b1814b93] */
	    continue;
	}
	if (port == 0 && chosenport == 0) {
	    address sockname;
	    socklen_t namelen = sizeof(sockname);

	    /*
2216
2217
2218
2219
2220
2221
2222

2223
2224
2225
2226
2227
2228
2229

	if (backlog < 0) {
	    backlog = SOMAXCONN;
	}
	if (listen(sock, backlog) == SOCKET_ERROR) {
	    Tcl_WinConvertError((DWORD) WSAGetLastError());
	    closesocket(sock);

	    continue;
	}

	if (statePtr == NULL) {
	    /*
	     * Add this socket to the global list of sockets.
	     */







>







2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231

	if (backlog < 0) {
	    backlog = SOMAXCONN;
	}
	if (listen(sock, backlog) == SOCKET_ERROR) {
	    Tcl_WinConvertError((DWORD) WSAGetLastError());
	    closesocket(sock);
	    sock = INVALID_SOCKET; /* Bug [40b1814b93] */
	    continue;
	}

	if (statePtr == NULL) {
	    /*
	     * Add this socket to the global list of sockets.
	     */