Check-in [a05795631f]
Not logged in

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

Overview
Comment:Merge main
Timelines: family | ancestors | descendants | both | tip-726
Files: files | file ages | folders
SHA3-256: a05795631f189755cd6c7f3e832ab83cc9cf53f6445b531c6efb84ff313b00ad
User & Date: apnadkarni 2025-08-28 07:18:16.889
Context
2025-08-28
07:52
Fix unsigned char* to char* conversion warning check-in: 04140a9eb7 user: apnadkarni tags: tip-726
07:18
Merge main check-in: a05795631f user: apnadkarni tags: tip-726
2025-08-27
11:58
Merge 9.0 check-in: 535e5cabd5 user: jan.nijtmans tags: trunk, main
2025-08-12
13:44
remove tclUniData.c and uniParse.tcl: not used any more check-in: b885c376e5 user: jan.nijtmans tags: tip-726
Changes
Unified Diff Ignore Whitespace Patch
Changes to .github/workflows/linux-build.yml.
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
      matrix: ${{ fromJson(needs.plan.outputs.gcc) }}
    defaults:
      run:
        shell: bash
        working-directory: unix
    steps:
      - name: Checkout
        uses: actions/checkout@v4
        timeout-minutes: 5
      - name: Install 32-bit dependencies if needed
        # Duplicated from above
        if: ${{ matrix.config == 'CFLAGS=-m32 CPPFLAGS=-m32 LDFLAGS=-m32 --disable-64bit' }}
        run: |
          sudo apt-get update
          sudo apt-get install gcc-multilib libc6-dev-i386







|







48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
      matrix: ${{ fromJson(needs.plan.outputs.gcc) }}
    defaults:
      run:
        shell: bash
        working-directory: unix
    steps:
      - name: Checkout
        uses: actions/checkout@v5
        timeout-minutes: 5
      - name: Install 32-bit dependencies if needed
        # Duplicated from above
        if: ${{ matrix.config == 'CFLAGS=-m32 CPPFLAGS=-m32 LDFLAGS=-m32 --disable-64bit' }}
        run: |
          sudo apt-get update
          sudo apt-get install gcc-multilib libc6-dev-i386
Changes to .github/workflows/mac-build.yml.
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
    runs-on: macos-15
    defaults:
      run:
        shell: bash
        working-directory: macosx
    steps:
      - name: Checkout
        uses: actions/checkout@v4
        timeout-minutes: 5
      - name: Prepare
        run: |
          touch tclStubInit.c tclOOStubInit.c tclOOScript.h
        working-directory: generic
      - name: Build
        run: make -j4 all







|







41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
    runs-on: macos-15
    defaults:
      run:
        shell: bash
        working-directory: macosx
    steps:
      - name: Checkout
        uses: actions/checkout@v5
        timeout-minutes: 5
      - name: Prepare
        run: |
          touch tclStubInit.c tclOOStubInit.c tclOOScript.h
        working-directory: generic
      - name: Build
        run: make -j4 all
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
      matrix: ${{ fromJson(needs.plan.outputs.clang) }}
    defaults:
      run:
        shell: bash
        working-directory: unix
    steps:
      - name: Checkout
        uses: actions/checkout@v4
        timeout-minutes: 5
      - name: Prepare
        run: |
          touch tclStubInit.c tclOOStubInit.c tclOOScript.h
          mkdir "$HOME/install dir"
        working-directory: generic
      - name: Configure ${{ matrix.config }}







|







69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
      matrix: ${{ fromJson(needs.plan.outputs.clang) }}
    defaults:
      run:
        shell: bash
        working-directory: unix
    steps:
      - name: Checkout
        uses: actions/checkout@v5
        timeout-minutes: 5
      - name: Prepare
        run: |
          touch tclStubInit.c tclOOStubInit.c tclOOScript.h
          mkdir "$HOME/install dir"
        working-directory: generic
      - name: Configure ${{ matrix.config }}
Changes to .github/workflows/onefiledist.yml.
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
    runs-on: ubuntu-24.04
    defaults:
      run:
        shell: bash
    timeout-minutes: 10
    steps:
      - name: Checkout
        uses: actions/checkout@v4
      - name: Prepare
        run: |
          touch generic/tclStubInit.c generic/tclOOStubInit.c
          mkdir 1dist
          echo "VER_PATH=$(cd tools; pwd)/addVerToFile.tcl" >> $GITHUB_ENV
        working-directory: .
      - name: Configure







|







14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
    runs-on: ubuntu-24.04
    defaults:
      run:
        shell: bash
    timeout-minutes: 10
    steps:
      - name: Checkout
        uses: actions/checkout@v5
      - name: Prepare
        run: |
          touch generic/tclStubInit.c generic/tclOOStubInit.c
          mkdir 1dist
          echo "VER_PATH=$(cd tools; pwd)/addVerToFile.tcl" >> $GITHUB_ENV
        working-directory: .
      - name: Configure
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
    runs-on: macos-13
    defaults:
      run:
        shell: bash
    timeout-minutes: 10
    steps:
      - name: Checkout
        uses: actions/checkout@v4
      - name: Checkout create-dmg
        uses: actions/checkout@v4
        with:
          repository: create-dmg/create-dmg
          ref: v1.0.8
          path: create-dmg
      - name: Prepare
        run: |
          mkdir 1dist







|

|







57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
    runs-on: macos-13
    defaults:
      run:
        shell: bash
    timeout-minutes: 10
    steps:
      - name: Checkout
        uses: actions/checkout@v5
      - name: Checkout create-dmg
        uses: actions/checkout@v5
        with:
          repository: create-dmg/create-dmg
          ref: v1.0.8
          path: create-dmg
      - name: Prepare
        run: |
          mkdir 1dist
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
    steps:
      - name: Install MSYS2
        uses: msys2/setup-msys2@v2
        with:
          msystem: UCRT64
          install: git mingw-w64-ucrt-x86_64-toolchain make zip
      - name: Checkout
        uses: actions/checkout@v4
      - name: Prepare
        run: |
          touch generic/tclStubInit.c generic/tclOOStubInit.c
          echo "VER_PATH=$(cd tools; pwd)/addVerToFile.tcl" >> $GITHUB_ENV
          mkdir 1dist
        working-directory: .
      - name: Configure







|







135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
    steps:
      - name: Install MSYS2
        uses: msys2/setup-msys2@v2
        with:
          msystem: UCRT64
          install: git mingw-w64-ucrt-x86_64-toolchain make zip
      - name: Checkout
        uses: actions/checkout@v5
      - name: Prepare
        run: |
          touch generic/tclStubInit.c generic/tclOOStubInit.c
          echo "VER_PATH=$(cd tools; pwd)/addVerToFile.tcl" >> $GITHUB_ENV
          mkdir 1dist
        working-directory: .
      - name: Configure
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
      # https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/store-information-in-variables
      REMOTE_PATH: ${{ vars.PUBLISH_DROP_PATH }}/data-${{ github.sha }}
    steps:
      - name: Make directory
        run: |
          mkdir data
      - name: Get Linux build
        uses: actions/download-artifact@v4
        with:
          path: data
          # Can't download by artifact ID; stupid missing feature!
          merge-multiple: true
      - name: Check data downloaded
        run: |
          ls -AlR







|







190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
      # https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/store-information-in-variables
      REMOTE_PATH: ${{ vars.PUBLISH_DROP_PATH }}/data-${{ github.sha }}
    steps:
      - name: Make directory
        run: |
          mkdir data
      - name: Get Linux build
        uses: actions/download-artifact@v5
        with:
          path: data
          # Can't download by artifact ID; stupid missing feature!
          merge-multiple: true
      - name: Check data downloaded
        run: |
          ls -AlR
Changes to .github/workflows/win-build.yml.
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
        shell: powershell
        working-directory: win
    strategy:
      matrix: ${{ fromJson(needs.plan.outputs.msvc) }}
    # Using powershell means we need to explicitly stop on failure
    steps:
      - name: Checkout
        uses: actions/checkout@v4
        timeout-minutes: 5
      - name: Init MSVC
        uses: ilammy/msvc-dev-cmd@v1
        timeout-minutes: 5
      - name: Build ${{ matrix.config }}
        run: |
          &nmake -f makefile.vc ${{ matrix.config }} all







|







63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
        shell: powershell
        working-directory: win
    strategy:
      matrix: ${{ fromJson(needs.plan.outputs.msvc) }}
    # Using powershell means we need to explicitly stop on failure
    steps:
      - name: Checkout
        uses: actions/checkout@v5
        timeout-minutes: 5
      - name: Init MSVC
        uses: ilammy/msvc-dev-cmd@v1
        timeout-minutes: 5
      - name: Build ${{ matrix.config }}
        run: |
          &nmake -f makefile.vc ${{ matrix.config }} all
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
      - name: Install MSYS2
        uses: msys2/setup-msys2@v2
        with:
          msystem: MINGW64
          install: git mingw-w64-x86_64-toolchain make
        timeout-minutes: 10
      - name: Checkout
        uses: actions/checkout@v4
        timeout-minutes: 5
      - name: Prepare
        run: |
          touch tclStubInit.c tclOOStubInit.c tclOOScript.h
          mkdir "${HOME}/install dir"
        working-directory: generic
      - name: Configure ${{ matrix.config }}







|







108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
      - name: Install MSYS2
        uses: msys2/setup-msys2@v2
        with:
          msystem: MINGW64
          install: git mingw-w64-x86_64-toolchain make
        timeout-minutes: 10
      - name: Checkout
        uses: actions/checkout@v5
        timeout-minutes: 5
      - name: Prepare
        run: |
          touch tclStubInit.c tclOOStubInit.c tclOOScript.h
          mkdir "${HOME}/install dir"
        working-directory: generic
      - name: Configure ${{ matrix.config }}
Changes to README.md.
1
2
3
4
5
6
7
8
9
10
# README:  Tcl

This is the **Tcl 9.1a0** source distribution.

You can get any source release of Tcl from [our distribution
site](https://sourceforge.net/projects/tcl/files/Tcl/).

9.1 (in development, daily build)
[![Build Status](https://github.com/tcltk/tcl/actions/workflows/linux-build.yml/badge.svg?branch=main)](https://github.com/tcltk/tcl/actions/workflows/linux-build.yml?query=branch%3Amain)
[![Build Status](https://github.com/tcltk/tcl/actions/workflows/win-build.yml/badge.svg?branch=main)](https://github.com/tcltk/tcl/actions/workflows/win-build.yml?query=branch%3Amain)


|







1
2
3
4
5
6
7
8
9
10
# README:  Tcl

This is the **Tcl 9.1a1** source distribution.

You can get any source release of Tcl from [our distribution
site](https://sourceforge.net/projects/tcl/files/Tcl/).

9.1 (in development, daily build)
[![Build Status](https://github.com/tcltk/tcl/actions/workflows/linux-build.yml/badge.svg?branch=main)](https://github.com/tcltk/tcl/actions/workflows/linux-build.yml?query=branch%3Amain)
[![Build Status](https://github.com/tcltk/tcl/actions/workflows/win-build.yml/badge.svg?branch=main)](https://github.com/tcltk/tcl/actions/workflows/win-build.yml?query=branch%3Amain)
Changes to changes.md.
1
2
3
4
5
6
7
8
9
10
11
12




13
14
15
16
17

18
19
20
21
22
23
24

The source code for Tcl is managed by fossil.  Tcl developers coordinate all
changes to the Tcl source code at

> [Tcl Source Code](https://core.tcl-lang.org/tcl/timeline)

Release Tcl 9.1a0 arises from the check-in with tag `core-9-1-a0`.

Highlighted differences between Tcl 9.1 and Tcl 9.0 are summarized below,
with focus on changes important to programmers using the Tcl library and
writing Tcl scripts.





# New public C API

- [Tcl\_IsEmpty checks if the string representation of a value would be the empty string](https://core.tcl-lang.org/tips/doc/trunk/tip/711.md)
- [Tcl\_GetEncodingNameForUser returns name of encoding from user settings](https://core.tcl-lang.org/tips/doc/trunk/tip/716.md)
- [Tcl\_AttemptCreateHashEntry - version of Tcl\_CreateHashEntry that returns NULL instead of panic'ing on memory allocation errors](https://core.tcl-lang.org/tips/doc/trunk/tip/717.md)


# Performance

- [Memory efficient internal representations](https://core.tcl-lang.org/tcl/wiki?name=New+abstract+list+representations)
for list operations on large lists.

# Bug fixes






|





>
>
>
>





>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

The source code for Tcl is managed by fossil.  Tcl developers coordinate all
changes to the Tcl source code at

> [Tcl Source Code](https://core.tcl-lang.org/tcl/timeline)

Release Tcl 9.1a1 arises from the check-in with tag `core-9-1-a1`.

Highlighted differences between Tcl 9.1 and Tcl 9.0 are summarized below,
with focus on changes important to programmers using the Tcl library and
writing Tcl scripts.

# New commands and options

- [New options -backslashes, -commands and -variables for subst command](https://core.tcl-lang.org/tips/doc/trunk/tip/712.md)

# New public C API

- [Tcl\_IsEmpty checks if the string representation of a value would be the empty string](https://core.tcl-lang.org/tips/doc/trunk/tip/711.md)
- [Tcl\_GetEncodingNameForUser returns name of encoding from user settings](https://core.tcl-lang.org/tips/doc/trunk/tip/716.md)
- [Tcl\_AttemptCreateHashEntry - version of Tcl\_CreateHashEntry that returns NULL instead of panic'ing on memory allocation errors](https://core.tcl-lang.org/tips/doc/trunk/tip/717.md)
- [Tcl\_ListObjRange, Tcl\_ListObjRepeat, Tcl\_TclListObjReverse - C API for new list operations](https://core.tcl-lang.org/tips/doc/trunk/tip/649.md)

# Performance

- [Memory efficient internal representations](https://core.tcl-lang.org/tcl/wiki?name=New+abstract+list+representations)
for list operations on large lists.

# Bug fixes
Changes to generic/tcl.h.
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
#   define TCL_MAJOR_VERSION	9
#endif
#if TCL_MAJOR_VERSION != 9
#   error "This header-file is for Tcl 9 only"
#endif
#define TCL_MINOR_VERSION   1
#define TCL_RELEASE_LEVEL   TCL_ALPHA_RELEASE
#define TCL_RELEASE_SERIAL  0

#define TCL_VERSION	    "9.1"
#define TCL_PATCH_LEVEL	    "9.1a0"

#if defined(RC_INVOKED)
/*
 * Utility macros: STRINGIFY takes an argument and wraps it in "" (double
 * quotation marks), JOIN joins two arguments.
 */








|


|







50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
#   define TCL_MAJOR_VERSION	9
#endif
#if TCL_MAJOR_VERSION != 9
#   error "This header-file is for Tcl 9 only"
#endif
#define TCL_MINOR_VERSION   1
#define TCL_RELEASE_LEVEL   TCL_ALPHA_RELEASE
#define TCL_RELEASE_SERIAL  1

#define TCL_VERSION	    "9.1"
#define TCL_PATCH_LEVEL	    "9.1a1"

#if defined(RC_INVOKED)
/*
 * Utility macros: STRINGIFY takes an argument and wraps it in "" (double
 * quotation marks), JOIN joins two arguments.
 */

Changes to generic/tclClock.c.
984
985
986
987
988
989
990

991



992
993
994
995
996
997
998
	    size_t lastTZEpoch = TzsetIfNecessary();

	    if (i < objc) {
		if (dataPtr->systemTimeZone != objv[i]) {
		    TclSetObjRef(dataPtr->systemTimeZone, objv[i]);
		    TclUnsetObjRef(dataPtr->systemSetupTZData);
		}

		dataPtr->lastTZEpoch = lastTZEpoch;



	    }
	    if (i + 1 >= objc && dataPtr->systemTimeZone != NULL
		    && dataPtr->lastTZEpoch == lastTZEpoch) {
		Tcl_SetObjResult(interp, dataPtr->systemTimeZone);
	    }
	    break;
	}







>
|
>
>
>







984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
	    size_t lastTZEpoch = TzsetIfNecessary();

	    if (i < objc) {
		if (dataPtr->systemTimeZone != objv[i]) {
		    TclSetObjRef(dataPtr->systemTimeZone, objv[i]);
		    TclUnsetObjRef(dataPtr->systemSetupTZData);
		}
		if (dataPtr->lastTZEpoch != lastTZEpoch) {
		    dataPtr->lastTZEpoch = lastTZEpoch;
		    /* TZ epoch changed - invalidate base-cache */
		    TclUnsetObjRef(dataPtr->lastBase.timezoneObj);
		}
	    }
	    if (i + 1 >= objc && dataPtr->systemTimeZone != NULL
		    && dataPtr->lastTZEpoch == lastTZEpoch) {
		Tcl_SetObjResult(interp, dataPtr->systemTimeZone);
	    }
	    break;
	}
Changes to generic/tclCompCmdsGR.c.
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534

    /*
     * Push all remaining words; there's definitely at least two.
     */

    Tcl_Token *tokenPtr = TokenAfter(varTokenPtr);
    for (i=2; i<numWords; i++, tokenPtr=TokenAfter(tokenPtr)) {
    	PUSH_TOKEN(		tokenPtr, i);
    }

    // Stack: varWords... idx1 idx2 values...
    //        {len=[0-2]} { len=numWords-2  }

    /*
     * Read the variable. This requires us to copy the varWords first (if there







|







1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534

    /*
     * Push all remaining words; there's definitely at least two.
     */

    Tcl_Token *tokenPtr = TokenAfter(varTokenPtr);
    for (i=2; i<numWords; i++, tokenPtr=TokenAfter(tokenPtr)) {
	PUSH_TOKEN(		tokenPtr, i);
    }

    // Stack: varWords... idx1 idx2 values...
    //        {len=[0-2]} { len=numWords-2  }

    /*
     * Read the variable. This requires us to copy the varWords first (if there
Changes to generic/tclCompCmdsSZ.c.
4370
4371
4372
4373
4374
4375
4376
4377
4378
4379
4380
4381
4382
4383
4384
    }

    tokenPtr = TokenAfter(parsePtr->tokenPtr);
    TclNewObj(objPtr);
    if (!TclWordKnownAtCompileTime(tokenPtr, objPtr)) {
	/*
	 * If the first argument isn't known at compile time, we can't know if
	 * it is a script fragment or a level descriptor. Punt. 
	 */
	Tcl_DecrRefCount(objPtr);
	return TCL_ERROR;
    }

    /*
     * Attempt to convert to a level reference. Note that TclObjGetFrame







|







4370
4371
4372
4373
4374
4375
4376
4377
4378
4379
4380
4381
4382
4383
4384
    }

    tokenPtr = TokenAfter(parsePtr->tokenPtr);
    TclNewObj(objPtr);
    if (!TclWordKnownAtCompileTime(tokenPtr, objPtr)) {
	/*
	 * If the first argument isn't known at compile time, we can't know if
	 * it is a script fragment or a level descriptor. Punt.
	 */
	Tcl_DecrRefCount(objPtr);
	return TCL_ERROR;
    }

    /*
     * Attempt to convert to a level reference. Note that TclObjGetFrame
Changes to generic/tclEncoding.c.
966
967
968
969
970
971
972


973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990

991
992
993
994




995
996
997

998
999




1000
1001
1002

1003
1004
1005


1006
1007
1008
1009
1010
1011
1012
 * Results:
 *	The return value is TCL_OK if the system encoding was successfully set
 *	to the encoding specified by name, TCL_ERROR otherwise. If TCL_ERROR
 *	is returned, an error message is left in interp's result object,
 *	unless interp was NULL.
 *
 * Side effects:


 *	The reference count of the new system encoding is incremented. The
 *	reference count of the old system encoding is decremented and it may
 *	be freed. All VFS cached information is invalidated.
 *
 *------------------------------------------------------------------------
 */

int
Tcl_SetSystemEncoding(
    Tcl_Interp *interp,		/* Interp for error reporting, if not NULL. */
    const char *name)		/* The name of the desired encoding, or NULL/""
				 * to reset to default encoding. */
{
    Tcl_Encoding encoding;
    Encoding *encodingPtr;

    if (!name || !*name) {
	Tcl_MutexLock(&encodingMutex);

	encoding = defaultEncoding;
	encodingPtr = (Encoding *) encoding;
	encodingPtr->refCount++;
	Tcl_MutexUnlock(&encodingMutex);




    } else {
	encoding = Tcl_GetEncoding(interp, name);
	if (encoding == NULL) {

	    return TCL_ERROR;
	}




    }

    Tcl_MutexLock(&encodingMutex);

    FreeEncoding(systemEncoding);
    systemEncoding = encoding;
    Tcl_MutexUnlock(&encodingMutex);


    Tcl_FSMountsChanged(NULL);

    return TCL_OK;
}

/*
 *---------------------------------------------------------------------------







>
>
|
|
|











<

<
|
>
|
<
<
|
>
>
>
>



>


>
>
>
>
|
|
|
>



>
>







966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988

989

990
991
992


993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
 * Results:
 *	The return value is TCL_OK if the system encoding was successfully set
 *	to the encoding specified by name, TCL_ERROR otherwise. If TCL_ERROR
 *	is returned, an error message is left in interp's result object,
 *	unless interp was NULL.
 *
 * Side effects:
 *	If the passed encoding is the same as the current system
 *	encoding, the call is effectively a no-op. Otherwise, the reference
 *	count of the new system encoding is incremented. The reference count
 *	of the old system encoding is decremented and it may be freed. All
 *	VFS cached information is invalidated.
 *
 *------------------------------------------------------------------------
 */

int
Tcl_SetSystemEncoding(
    Tcl_Interp *interp,		/* Interp for error reporting, if not NULL. */
    const char *name)		/* The name of the desired encoding, or NULL/""
				 * to reset to default encoding. */
{
    Tcl_Encoding encoding;



    Tcl_MutexLock(&encodingMutex);
    if (name == NULL || name[0] == '\0') {
	if (defaultEncoding == systemEncoding) {


	    Tcl_MutexUnlock(&encodingMutex);
	    return TCL_OK;
	}
	encoding = defaultEncoding;
	((Encoding *)encoding)->refCount += 1;
    } else {
	encoding = Tcl_GetEncoding(interp, name);
	if (encoding == NULL) {
	    Tcl_MutexUnlock(&encodingMutex);
	    return TCL_ERROR;
	}
	if (encoding == systemEncoding) {
	    FreeEncoding(encoding);
	    Tcl_MutexUnlock(&encodingMutex);
	    return TCL_OK;
	}
    }

    assert(encoding != systemEncoding);
    FreeEncoding(systemEncoding);
    systemEncoding = encoding;
    Tcl_MutexUnlock(&encodingMutex);

    /* Checks above ensure this is only called when system encoding changes */
    Tcl_FSMountsChanged(NULL);

    return TCL_OK;
}

/*
 *---------------------------------------------------------------------------
Changes to generic/tclExecute.c.
4657
4658
4659
4660
4661
4662
4663

4664
4665

4666
4667

4668
4669
4670
4671
4672
4673
4674
4675
4676
4677
4678
4679
4680
4681
4682
4683
4684
4685
	 */

    case INST_JUMP_TABLE_NUM:
	tblIdx = TclGetInt4AtPtr(pc + 1);
	JumptableNumInfo *jtnPtr = (JumptableNumInfo *)
		codePtr->auxDataArrayPtr[tblIdx].clientData;
	TRACE(("%u \"%.20s\" => ", tblIdx, O2S(OBJ_AT_TOS)));

	Tcl_WideInt key;
	if (Tcl_GetWideIntFromObj(NULL, OBJ_AT_TOS, &key) != TCL_OK) {

	    goto jumpTableNumFallthrough;
	}

	hPtr = Tcl_FindHashEntry(&jtnPtr->hashTable, INT2PTR(key));

    processJumpTableEntry:
	if (hPtr != NULL) {
	    Tcl_Size jumpOffset = PTR2INT(Tcl_GetHashValue(hPtr));

	    TRACE_APPEND(("found in table, new pc %" SIZEu "\n",
		    PC_REL + jumpOffset));
	    NEXT_INST_F0(jumpOffset, 1);
	}
    jumpTableNumFallthrough:
	TRACE_APPEND(("not found in table\n"));
	NEXT_INST_F0(5, 1);
    }

    /*
     * -----------------------------------------------------------------
     *	   Start of general introspector instructions.







>

|
>
|

>










<







4657
4658
4659
4660
4661
4662
4663
4664
4665
4666
4667
4668
4669
4670
4671
4672
4673
4674
4675
4676
4677
4678
4679
4680

4681
4682
4683
4684
4685
4686
4687
	 */

    case INST_JUMP_TABLE_NUM:
	tblIdx = TclGetInt4AtPtr(pc + 1);
	JumptableNumInfo *jtnPtr = (JumptableNumInfo *)
		codePtr->auxDataArrayPtr[tblIdx].clientData;
	TRACE(("%u \"%.20s\" => ", tblIdx, O2S(OBJ_AT_TOS)));
	DECACHE_STACK_INFO();
	Tcl_WideInt key;
	if (Tcl_GetWideIntFromObj(interp, OBJ_AT_TOS, &key) != TCL_OK) {
	    TRACE_ERROR(interp);
	    goto gotError;
	}
	CACHE_STACK_INFO();
	hPtr = Tcl_FindHashEntry(&jtnPtr->hashTable, INT2PTR(key));

    processJumpTableEntry:
	if (hPtr != NULL) {
	    Tcl_Size jumpOffset = PTR2INT(Tcl_GetHashValue(hPtr));

	    TRACE_APPEND(("found in table, new pc %" SIZEu "\n",
		    PC_REL + jumpOffset));
	    NEXT_INST_F0(jumpOffset, 1);
	}

	TRACE_APPEND(("not found in table\n"));
	NEXT_INST_F0(5, 1);
    }

    /*
     * -----------------------------------------------------------------
     *	   Start of general introspector instructions.
Changes to generic/tclFCmd.c.
25
26
27
28
29
30
31




























32
33
34
35
36
37
38
			    int objc, Tcl_Obj *const objv[], int copyFlag);
static int		FileForceOption(Tcl_Interp *interp,
			    int objc, Tcl_Obj *const objv[], int *forcePtr);

/*
 *---------------------------------------------------------------------------
 *




























 * TclFileRenameCmd
 *
 *	This function implements the "rename" subcommand of the "file"
 *	command. Filename arguments need to be translated to native format
 *	before being passed to platform-specific code that implements rename
 *	functionality.
 *







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







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
59
60
61
62
63
64
65
66
			    int objc, Tcl_Obj *const objv[], int copyFlag);
static int		FileForceOption(Tcl_Interp *interp,
			    int objc, Tcl_Obj *const objv[], int *forcePtr);

/*
 *---------------------------------------------------------------------------
 *
 * CheckFilenameEncodable
 *
 *	This checks if a filename can be encoded on the target platform,
 *	disallowing things like naked surrogates, etc.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	May update the interpreter result with an error message on failure.
 *
 *---------------------------------------------------------------------------
 */
static inline int
CheckFilenameEncodable(
    Tcl_Interp *interp,
    Tcl_Obj *fileName)
{
    Tcl_DString ds;
    int code = Tcl_UtfToExternalDStringEx(interp, TCLFSENCODING,
	    TclGetString(fileName), TCL_INDEX_NONE, 0, &ds, NULL);
    Tcl_DStringFree(&ds);
    return code == TCL_OK ? TCL_OK : TCL_ERROR;
}

/*
 *---------------------------------------------------------------------------
 *
 * TclFileRenameCmd
 *
 *	This function implements the "rename" subcommand of the "file"
 *	command. Filename arguments need to be translated to native format
 *	before being passed to platform-specific code that implements rename
 *	functionality.
 *
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
    Tcl_Obj *const objv[],	/* Argument strings passed to Tcl_FileCmd. */
    int copyFlag)		/* If non-zero, copy source(s). Otherwise,
				 * rename them. */
{
    int i, result, force;
    Tcl_StatBuf statBuf;
    Tcl_Obj *target;
    Tcl_DString ds;

    i = FileForceOption(interp, objc - 1, objv + 1, &force);
    if (i < 0) {
	return TCL_ERROR;
    }
    i++;
    if ((objc - i) < 2) {







<







137
138
139
140
141
142
143

144
145
146
147
148
149
150
    Tcl_Obj *const objv[],	/* Argument strings passed to Tcl_FileCmd. */
    int copyFlag)		/* If non-zero, copy source(s). Otherwise,
				 * rename them. */
{
    int i, result, force;
    Tcl_StatBuf statBuf;
    Tcl_Obj *target;


    i = FileForceOption(interp, objc - 1, objv + 1, &force);
    if (i < 0) {
	return TCL_ERROR;
    }
    i++;
    if ((objc - i) < 2) {
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
     * than 2 arguments is only valid if the target is an existing directory.
     */

    target = objv[objc - 1];
    if (Tcl_FSConvertToPathType(interp, target) != TCL_OK) {
	return TCL_ERROR;
    }
    if (Tcl_UtfToExternalDStringEx(interp, TCLFSENCODING, TclGetString(target),
	    TCL_INDEX_NONE, 0, &ds, NULL) != TCL_OK) {
	Tcl_DStringFree(&ds);
	return TCL_ERROR;
    }
    Tcl_DStringFree(&ds);

    result = TCL_OK;

    /*
     * Call Tcl_FSStat() so that if target is a symlink that points to a
     * directory we will put the sources in that directory instead of
     * overwriting the symlink.







<
|
<


<







158
159
160
161
162
163
164

165

166
167

168
169
170
171
172
173
174
     * than 2 arguments is only valid if the target is an existing directory.
     */

    target = objv[objc - 1];
    if (Tcl_FSConvertToPathType(interp, target) != TCL_OK) {
	return TCL_ERROR;
    }

    if (CheckFilenameEncodable(interp, target) != TCL_OK) {

	return TCL_ERROR;
    }


    result = TCL_OK;

    /*
     * Call Tcl_FSStat() so that if target is a symlink that points to a
     * directory we will put the sources in that directory instead of
     * overwriting the symlink.
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
{
    Tcl_Obj *errfile = NULL;
    int result, i;
    Tcl_Size j, pobjc;
    Tcl_Obj *split = NULL;
    Tcl_Obj *target = NULL;
    Tcl_StatBuf statBuf;
    Tcl_DString ds;

    result = TCL_OK;
    for (i = 1; i < objc; i++) {
	if (Tcl_FSConvertToPathType(interp, objv[i]) != TCL_OK) {
	    result = TCL_ERROR;
	    break;
	}
	if (Tcl_UtfToExternalDStringEx(interp, TCLFSENCODING, TclGetString(objv[i]),
		TCL_INDEX_NONE, 0, &ds, NULL) != TCL_OK) {
	    Tcl_DStringFree(&ds);
	    result = TCL_ERROR;
	    break;
	}
	Tcl_DStringFree(&ds);

	split = Tcl_FSSplitPath(objv[i], &pobjc);
	Tcl_IncrRefCount(split);
	if (pobjc == 0) {
	    errno = ENOENT;
	    errfile = objv[i];
	    break;







<







<
|
<



<







252
253
254
255
256
257
258

259
260
261
262
263
264
265

266

267
268
269

270
271
272
273
274
275
276
{
    Tcl_Obj *errfile = NULL;
    int result, i;
    Tcl_Size j, pobjc;
    Tcl_Obj *split = NULL;
    Tcl_Obj *target = NULL;
    Tcl_StatBuf statBuf;


    result = TCL_OK;
    for (i = 1; i < objc; i++) {
	if (Tcl_FSConvertToPathType(interp, objv[i]) != TCL_OK) {
	    result = TCL_ERROR;
	    break;
	}

	if (CheckFilenameEncodable(interp, objv[i]) != TCL_OK) {

	    result = TCL_ERROR;
	    break;
	}


	split = Tcl_FSSplitPath(objv[i], &pobjc);
	Tcl_IncrRefCount(split);
	if (pobjc == 0) {
	    errno = ENOENT;
	    errfile = objv[i];
	    break;
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
    Tcl_Interp *interp,		/* Used for error reporting */
    int objc,			/* Number of arguments */
    Tcl_Obj *const objv[])	/* Argument strings passed to Tcl_FileCmd. */
{
    int i, force, result;
    Tcl_Obj *errfile;
    Tcl_Obj *errorBuffer = NULL;
    Tcl_DString ds;

    i = FileForceOption(interp, objc - 1, objv + 1, &force);
    if (i < 0) {
	return TCL_ERROR;
    }

    errfile = NULL;
    result = TCL_OK;

    for (i++ ; i < objc; i++) {
	Tcl_StatBuf statBuf;

	errfile = objv[i];
	if (Tcl_FSConvertToPathType(interp, objv[i]) != TCL_OK) {
	    result = TCL_ERROR;
	    goto done;
	}
	if (Tcl_UtfToExternalDStringEx(interp, TCLFSENCODING, TclGetString(objv[i]),
		TCL_INDEX_NONE, 0, &ds, NULL) != TCL_OK) {
	    Tcl_DStringFree(&ds);
	    result = TCL_ERROR;
	    goto done;
	}
	Tcl_DStringFree(&ds);

	/*
	 * Call lstat() to get info so can delete symbolic link itself.
	 */

	if (Tcl_FSLstat(objv[i], &statBuf) != 0) {
	    result = TCL_ERROR;







<

















<
|
<



<







378
379
380
381
382
383
384

385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401

402

403
404
405

406
407
408
409
410
411
412
    Tcl_Interp *interp,		/* Used for error reporting */
    int objc,			/* Number of arguments */
    Tcl_Obj *const objv[])	/* Argument strings passed to Tcl_FileCmd. */
{
    int i, force, result;
    Tcl_Obj *errfile;
    Tcl_Obj *errorBuffer = NULL;


    i = FileForceOption(interp, objc - 1, objv + 1, &force);
    if (i < 0) {
	return TCL_ERROR;
    }

    errfile = NULL;
    result = TCL_OK;

    for (i++ ; i < objc; i++) {
	Tcl_StatBuf statBuf;

	errfile = objv[i];
	if (Tcl_FSConvertToPathType(interp, objv[i]) != TCL_OK) {
	    result = TCL_ERROR;
	    goto done;
	}

	if (CheckFilenameEncodable(interp, objv[i]) != TCL_OK) {

	    result = TCL_ERROR;
	    goto done;
	}


	/*
	 * Call lstat() to get info so can delete symbolic link itself.
	 */

	if (Tcl_FSLstat(objv[i], &statBuf) != 0) {
	    result = TCL_ERROR;
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
				 * exists. */
{
    int result;
    Tcl_Obj *errfile, *errorBuffer;
    Tcl_Obj *actualSource=NULL;	/* If source is a link, then this is the real
				 * file/directory. */
    Tcl_StatBuf sourceStatBuf, targetStatBuf;
    Tcl_DString ds;

    if (Tcl_FSConvertToPathType(interp, source) != TCL_OK) {
	return TCL_ERROR;
    }
    if (Tcl_UtfToExternalDStringEx(interp, TCLFSENCODING, TclGetString(source),
	    TCL_INDEX_NONE, 0, &ds, NULL) != TCL_OK) {
	Tcl_DStringFree(&ds);
	return TCL_ERROR;
    }
    Tcl_DStringFree(&ds);
    if (Tcl_FSConvertToPathType(interp, target) != TCL_OK) {
	return TCL_ERROR;
    }
    if (Tcl_UtfToExternalDStringEx(interp, TCLFSENCODING, TclGetString(target),
	    TCL_INDEX_NONE, 0, &ds, NULL) != TCL_OK) {
	Tcl_DStringFree(&ds);
	return TCL_ERROR;
    }
    Tcl_DStringFree(&ds);

    errfile = NULL;
    errorBuffer = NULL;
    result = TCL_ERROR;

    /*
     * We want to copy/rename links and not the files they point to, so we use







<




<
|
<


<



<
|
<


<







518
519
520
521
522
523
524

525
526
527
528

529

530
531

532
533
534

535

536
537

538
539
540
541
542
543
544
				 * exists. */
{
    int result;
    Tcl_Obj *errfile, *errorBuffer;
    Tcl_Obj *actualSource=NULL;	/* If source is a link, then this is the real
				 * file/directory. */
    Tcl_StatBuf sourceStatBuf, targetStatBuf;


    if (Tcl_FSConvertToPathType(interp, source) != TCL_OK) {
	return TCL_ERROR;
    }

    if (CheckFilenameEncodable(interp, source) != TCL_OK) {

	return TCL_ERROR;
    }

    if (Tcl_FSConvertToPathType(interp, target) != TCL_OK) {
	return TCL_ERROR;
    }

    if (CheckFilenameEncodable(interp, target) != TCL_OK) {

	return TCL_ERROR;
    }


    errfile = NULL;
    errorBuffer = NULL;
    result = TCL_ERROR;

    /*
     * We want to copy/rename links and not the files they point to, so we use
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
{
    int result;
    const char *const *attributeStrings;
    const char **attributeStringsAllocated = NULL;
    Tcl_Obj *objStrings = NULL;
    Tcl_Size numObjStrings = TCL_INDEX_NONE;
    Tcl_Obj *filePtr;
    Tcl_DString ds;

    if (objc < 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "name ?-option value ...?");
	return TCL_ERROR;
    }

    filePtr = objv[1];
    if (Tcl_FSConvertToPathType(interp, filePtr) != TCL_OK) {
	return TCL_ERROR;
    }
    if (Tcl_UtfToExternalDStringEx(interp, TCLFSENCODING, TclGetString(filePtr),
	    TCL_INDEX_NONE, 0, &ds, NULL) != TCL_OK) {
	Tcl_DStringFree(&ds);
	return TCL_ERROR;
    }
    Tcl_DStringFree(&ds);

    objc -= 2;
    objv += 2;
    result = TCL_ERROR;
    Tcl_SetErrno(0);

    /*







<










<
|
<


<







990
991
992
993
994
995
996

997
998
999
1000
1001
1002
1003
1004
1005
1006

1007

1008
1009

1010
1011
1012
1013
1014
1015
1016
{
    int result;
    const char *const *attributeStrings;
    const char **attributeStringsAllocated = NULL;
    Tcl_Obj *objStrings = NULL;
    Tcl_Size numObjStrings = TCL_INDEX_NONE;
    Tcl_Obj *filePtr;


    if (objc < 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "name ?-option value ...?");
	return TCL_ERROR;
    }

    filePtr = objv[1];
    if (Tcl_FSConvertToPathType(interp, filePtr) != TCL_OK) {
	return TCL_ERROR;
    }

    if (CheckFilenameEncodable(interp, filePtr) != TCL_OK) {

	return TCL_ERROR;
    }


    objc -= 2;
    objv += 2;
    result = TCL_ERROR;
    Tcl_SetErrno(0);

    /*
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Tcl_Obj *contents;
    int index;
    Tcl_DString ds;

    if (objc < 2 || objc > 4) {
	Tcl_WrongNumArgs(interp, 1, objv, "?-linktype? linkname ?target?");
	return TCL_ERROR;
    }

    /*







<







1205
1206
1207
1208
1209
1210
1211

1212
1213
1214
1215
1216
1217
1218
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Tcl_Obj *contents;
    int index;


    if (objc < 2 || objc > 4) {
	Tcl_WrongNumArgs(interp, 1, objv, "?-linktype? linkname ?target?");
	return TCL_ERROR;
    }

    /*
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
	    }
	} else {
	    linkAction = TCL_CREATE_SYMBOLIC_LINK | TCL_CREATE_HARD_LINK;
	}
	if (Tcl_FSConvertToPathType(interp, objv[index]) != TCL_OK) {
	    return TCL_ERROR;
	}
	if (Tcl_UtfToExternalDStringEx(interp, TCLFSENCODING, TclGetString(objv[index]),
		TCL_INDEX_NONE, 0, &ds, NULL) != TCL_OK) {
	    Tcl_DStringFree(&ds);
	    return TCL_ERROR;
	}
	Tcl_DStringFree(&ds);

	/*
	 * Create link from source to target.
	 */

	contents = Tcl_FSLink(objv[index], objv[index+1], linkAction);
	if (contents == NULL) {







<
|
<


<







1247
1248
1249
1250
1251
1252
1253

1254

1255
1256

1257
1258
1259
1260
1261
1262
1263
	    }
	} else {
	    linkAction = TCL_CREATE_SYMBOLIC_LINK | TCL_CREATE_HARD_LINK;
	}
	if (Tcl_FSConvertToPathType(interp, objv[index]) != TCL_OK) {
	    return TCL_ERROR;
	}

	if (CheckFilenameEncodable(interp, objv[index]) != TCL_OK) {

	    return TCL_ERROR;
	}


	/*
	 * Create link from source to target.
	 */

	contents = Tcl_FSLink(objv[index], objv[index+1], linkAction);
	if (contents == NULL) {
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
	    }
	    return TCL_ERROR;
	}
    } else {
	if (Tcl_FSConvertToPathType(interp, objv[index]) != TCL_OK) {
	    return TCL_ERROR;
	}
	if (Tcl_UtfToExternalDStringEx(interp, TCLFSENCODING, TclGetString(objv[index]),
		TCL_INDEX_NONE, 0, &ds, NULL) != TCL_OK) {
	    Tcl_DStringFree(&ds);
	    return TCL_ERROR;
	}
	Tcl_DStringFree(&ds);

	/*
	 * Read link
	 */

	contents = Tcl_FSLink(objv[index], NULL, 0);
	if (contents == NULL) {







<
|
<


<







1307
1308
1309
1310
1311
1312
1313

1314

1315
1316

1317
1318
1319
1320
1321
1322
1323
	    }
	    return TCL_ERROR;
	}
    } else {
	if (Tcl_FSConvertToPathType(interp, objv[index]) != TCL_OK) {
	    return TCL_ERROR;
	}

	if (CheckFilenameEncodable(interp, objv[index]) != TCL_OK) {

	    return TCL_ERROR;
	}


	/*
	 * Read link
	 */

	contents = Tcl_FSLink(objv[index], NULL, 0);
	if (contents == NULL) {
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
TclFileReadLinkCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Tcl_Obj *contents;
    Tcl_DString ds;

    if (objc != 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "name");
	return TCL_ERROR;
    }

    if (Tcl_FSConvertToPathType(interp, objv[1]) != TCL_OK) {
	return TCL_ERROR;
    }
    if (Tcl_UtfToExternalDStringEx(interp, TCLFSENCODING, TclGetString(objv[1]),
	    TCL_INDEX_NONE, 0, &ds, NULL) != TCL_OK) {
	Tcl_DStringFree(&ds);
	return TCL_ERROR;
    }
    Tcl_DStringFree(&ds);

    contents = Tcl_FSLink(objv[1], NULL, 0);

    if (contents == NULL) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"could not read link \"%s\": %s",
		TclGetString(objv[1]), Tcl_PosixError(interp)));







<









<
|
<


<







1361
1362
1363
1364
1365
1366
1367

1368
1369
1370
1371
1372
1373
1374
1375
1376

1377

1378
1379

1380
1381
1382
1383
1384
1385
1386
TclFileReadLinkCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const objv[])
{
    Tcl_Obj *contents;


    if (objc != 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "name");
	return TCL_ERROR;
    }

    if (Tcl_FSConvertToPathType(interp, objv[1]) != TCL_OK) {
	return TCL_ERROR;
    }

    if (CheckFilenameEncodable(interp, objv[1]) != TCL_OK) {

	return TCL_ERROR;
    }


    contents = Tcl_FSLink(objv[1], NULL, 0);

    if (contents == NULL) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"could not read link \"%s\": %s",
		TclGetString(objv[1]), Tcl_PosixError(interp)));
Changes to generic/tclIOUtil.c.
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
	return TCL_ERROR;
    }

#ifndef _WIN32
    /*
     * It might be necessary on some systems to set the appropriate permissions
     * on the file.  On Unix we could loop over the file attributes and set any
     * that are called "-permissions" to 0700, but just do it directly instead:
     */

    {
	Tcl_Size index;
	Tcl_Obj *perm;

	TclNewLiteralStringObj(perm, "0700");
	Tcl_IncrRefCount(perm);
	if (TclFSFileAttrIndex(copyToPtr, "-permissions", &index) == TCL_OK) {
	    Tcl_FSFileAttrsSet(NULL, index, copyToPtr, perm);
	}
	Tcl_DecrRefCount(perm);
    }
#endif







|






|







3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
3325
	return TCL_ERROR;
    }

#ifndef _WIN32
    /*
     * It might be necessary on some systems to set the appropriate permissions
     * on the file.  On Unix we could loop over the file attributes and set any
     * that are called "-permissions" to 0o700, but just do it directly instead:
     */

    {
	Tcl_Size index;
	Tcl_Obj *perm;

	TclNewLiteralStringObj(perm, "0o700");
	Tcl_IncrRefCount(perm);
	if (TclFSFileAttrIndex(copyToPtr, "-permissions", &index) == TCL_OK) {
	    Tcl_FSFileAttrsSet(NULL, index, copyToPtr, perm);
	}
	Tcl_DecrRefCount(perm);
    }
#endif
Changes to generic/tclInt.h.
3278
3279
3280
3281
3282
3283
3284




3285
3286
3287
3288
3289
3290
3291
 *----------------------------------------------------------------
 */

MODULE_SCOPE void	TclAdvanceContinuations(int *line, Tcl_Size **next,
			    Tcl_Size loc);
MODULE_SCOPE void	TclAdvanceLines(int *line, const char *start,
			    const char *end);




MODULE_SCOPE void	TclAppendBytesToByteArray(Tcl_Obj *objPtr,
			    const unsigned char *bytes, Tcl_Size len);
MODULE_SCOPE void	TclAppendUtfToUtf(Tcl_Obj *objPtr,
			    const char *bytes, Tcl_Size numBytes);
MODULE_SCOPE void	TclArgumentEnter(Tcl_Interp *interp,
			    Tcl_Obj *objv[], Tcl_Size objc, CmdFrame *cf);
MODULE_SCOPE void	TclArgumentRelease(Tcl_Interp *interp,







>
>
>
>







3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
 *----------------------------------------------------------------
 */

MODULE_SCOPE void	TclAdvanceContinuations(int *line, Tcl_Size **next,
			    Tcl_Size loc);
MODULE_SCOPE void	TclAdvanceLines(int *line, const char *start,
			    const char *end);
MODULE_SCOPE int	TclAliasCreate(Tcl_Interp *interp,
			    Tcl_Interp *childInterp, Tcl_Interp *parentInterp,
			    Tcl_Obj *namePtr, Tcl_Obj *targetPtr, Tcl_Size objc,
			    Tcl_Obj *const objv[]);
MODULE_SCOPE void	TclAppendBytesToByteArray(Tcl_Obj *objPtr,
			    const unsigned char *bytes, Tcl_Size len);
MODULE_SCOPE void	TclAppendUtfToUtf(Tcl_Obj *objPtr,
			    const char *bytes, Tcl_Size numBytes);
MODULE_SCOPE void	TclArgumentEnter(Tcl_Interp *interp,
			    Tcl_Obj *objv[], Tcl_Size objc, CmdFrame *cf);
MODULE_SCOPE void	TclArgumentRelease(Tcl_Interp *interp,
3693
3694
3695
3696
3697
3698
3699

3700
3701
3702
3703
3704
3705
3706
MODULE_SCOPE void *	TclpThreadGetGlobalTSD(void *tsdKeyPtr);
MODULE_SCOPE void	TclErrorStackResetIf(Tcl_Interp *interp,
			    const char *msg, Tcl_Size length);
/* Tip 430 */
MODULE_SCOPE int	TclZipfs_Init(Tcl_Interp *interp);
MODULE_SCOPE int	TclIsZipfsPath(const char *path);
MODULE_SCOPE void	TclZipfsFinalize(void);


/*
 * Many parsing tasks need a common definition of whitespace.
 * Use this routine and macro to achieve that and place
 * optimization (fragile on changes) in one place.
 */








>







3697
3698
3699
3700
3701
3702
3703
3704
3705
3706
3707
3708
3709
3710
3711
MODULE_SCOPE void *	TclpThreadGetGlobalTSD(void *tsdKeyPtr);
MODULE_SCOPE void	TclErrorStackResetIf(Tcl_Interp *interp,
			    const char *msg, Tcl_Size length);
/* Tip 430 */
MODULE_SCOPE int	TclZipfs_Init(Tcl_Interp *interp);
MODULE_SCOPE int	TclIsZipfsPath(const char *path);
MODULE_SCOPE void	TclZipfsFinalize(void);
MODULE_SCOPE int	TclZipfsLocateTclLibrary(void);

/*
 * Many parsing tasks need a common definition of whitespace.
 * Use this routine and macro to achieve that and place
 * optimization (fragile on changes) in one place.
 */

Changes to generic/tclInterp.c.
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
#define INTERP_INFO(interp) \
	((InterpInfo *) ((Interp *) (interp))->interpInfo)

/*
 * Prototypes for local static functions:
 */

static int		AliasCreate(Tcl_Interp *interp,
			    Tcl_Interp *childInterp, Tcl_Interp *parentInterp,
			    Tcl_Obj *namePtr, Tcl_Obj *targetPtr, Tcl_Size objc,
			    Tcl_Obj *const objv[]);
static int		AliasDelete(Tcl_Interp *interp,
			    Tcl_Interp *childInterp, Tcl_Obj *namePtr);
static int		AliasDescribe(Tcl_Interp *interp,
			    Tcl_Interp *childInterp, Tcl_Obj *objPtr);
static int		AliasList(Tcl_Interp *interp, Tcl_Interp *childInterp);
static Tcl_ObjCmdProc	AliasNRCmd;
static Tcl_CmdDeleteProc AliasObjCmdDeleteProc;







<
<
<
<







217
218
219
220
221
222
223




224
225
226
227
228
229
230
#define INTERP_INFO(interp) \
	((InterpInfo *) ((Interp *) (interp))->interpInfo)

/*
 * Prototypes for local static functions:
 */





static int		AliasDelete(Tcl_Interp *interp,
			    Tcl_Interp *childInterp, Tcl_Obj *namePtr);
static int		AliasDescribe(Tcl_Interp *interp,
			    Tcl_Interp *childInterp, Tcl_Obj *objPtr);
static int		AliasList(Tcl_Interp *interp, Tcl_Interp *childInterp);
static Tcl_ObjCmdProc	AliasNRCmd;
static Tcl_CmdDeleteProc AliasObjCmdDeleteProc;
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
	}
	if (objc > 5) {
	    parentInterp = GetInterp(interp, objv[4]);
	    if (parentInterp == NULL) {
		return TCL_ERROR;
	    }

	    return AliasCreate(interp, childInterp, parentInterp, objv[3],
		    objv[5], objc - 6, objv + 6);
	}

    aliasArgs:
	Tcl_WrongNumArgs(interp, 2, objv,
		"childPath childCmd ?parentPath parentCmd? ?arg ...?");
	return TCL_ERROR;







|







693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
	}
	if (objc > 5) {
	    parentInterp = GetInterp(interp, objv[4]);
	    if (parentInterp == NULL) {
		return TCL_ERROR;
	    }

	    return TclAliasCreate(interp, childInterp, parentInterp, objv[3],
		    objv[5], objc - 6, objv + 6);
	}

    aliasArgs:
	Tcl_WrongNumArgs(interp, 2, objv,
		"childPath childCmd ?parentPath parentCmd? ?arg ...?");
	return TCL_ERROR;
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242

    childObjPtr = Tcl_NewStringObj(childCmd, -1);
    Tcl_IncrRefCount(childObjPtr);

    targetObjPtr = Tcl_NewStringObj(targetCmd, -1);
    Tcl_IncrRefCount(targetObjPtr);

    result = AliasCreate(childInterp, childInterp, targetInterp, childObjPtr,
	    targetObjPtr, argc, objv);

    for (i = 0; i < argc; i++) {
	Tcl_DecrRefCount(objv[i]);
    }
    TclStackFree(childInterp, objv);
    Tcl_DecrRefCount(targetObjPtr);







|







1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238

    childObjPtr = Tcl_NewStringObj(childCmd, -1);
    Tcl_IncrRefCount(childObjPtr);

    targetObjPtr = Tcl_NewStringObj(targetCmd, -1);
    Tcl_IncrRefCount(targetObjPtr);

    result = TclAliasCreate(childInterp, childInterp, targetInterp, childObjPtr,
	    targetObjPtr, argc, objv);

    for (i = 0; i < argc; i++) {
	Tcl_DecrRefCount(objv[i]);
    }
    TclStackFree(childInterp, objv);
    Tcl_DecrRefCount(targetObjPtr);
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289

    childObjPtr = Tcl_NewStringObj(childCmd, -1);
    Tcl_IncrRefCount(childObjPtr);

    targetObjPtr = Tcl_NewStringObj(targetCmd, -1);
    Tcl_IncrRefCount(targetObjPtr);

    result = AliasCreate(childInterp, childInterp, targetInterp, childObjPtr,
	    targetObjPtr, objc, objv);

    Tcl_DecrRefCount(childObjPtr);
    Tcl_DecrRefCount(targetObjPtr);
    return result;
}








|







1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285

    childObjPtr = Tcl_NewStringObj(childCmd, -1);
    Tcl_IncrRefCount(childObjPtr);

    targetObjPtr = Tcl_NewStringObj(targetCmd, -1);
    Tcl_IncrRefCount(targetObjPtr);

    result = TclAliasCreate(childInterp, childInterp, targetInterp, childObjPtr,
	    targetObjPtr, objc, objv);

    Tcl_DecrRefCount(childObjPtr);
    Tcl_DecrRefCount(targetObjPtr);
    return result;
}

1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
	nextAliasPtr = (Alias *) aliasCmdPtr->objClientData;
    }
}

/*
 *----------------------------------------------------------------------
 *
 * AliasCreate --
 *
 *	Helper function to do the work to actually create an alias.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	An alias command is created and entered into the alias table for the
 *	child interpreter.
 *
 *----------------------------------------------------------------------
 */

static int
AliasCreate(
    Tcl_Interp *interp,		/* Interp for error reporting. */
    Tcl_Interp *childInterp,	/* Interp where alias cmd will live or from
				 * which alias will be deleted. */
    Tcl_Interp *parentInterp,	/* Interp in which target command will be
				 * invoked. */
    Tcl_Obj *namePtr,		/* Name of alias cmd. */
    Tcl_Obj *targetCmdPtr,	/* Name of target cmd. */







|













|
|







1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
	nextAliasPtr = (Alias *) aliasCmdPtr->objClientData;
    }
}

/*
 *----------------------------------------------------------------------
 *
 * TclAliasCreate --
 *
 *	Helper function to do the work to actually create an alias.
 *
 * Results:
 *	A standard Tcl result.
 *
 * Side effects:
 *	An alias command is created and entered into the alias table for the
 *	child interpreter.
 *
 *----------------------------------------------------------------------
 */

int
TclAliasCreate(
    Tcl_Interp *interp,		/* Interp for error reporting. */
    Tcl_Interp *childInterp,	/* Interp where alias cmd will live or from
				 * which alias will be deleted. */
    Tcl_Interp *parentInterp,	/* Interp in which target command will be
				 * invoked. */
    Tcl_Obj *namePtr,		/* Name of alias cmd. */
    Tcl_Obj *targetCmdPtr,	/* Name of target cmd. */
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478

    if (safe) {
	Tcl_Obj *clockObj;
	int status;

	TclNewLiteralStringObj(clockObj, "clock");
	Tcl_IncrRefCount(clockObj);
	status = AliasCreate(interp, childInterp, parentInterp, clockObj,
		clockObj, 0, NULL);
	Tcl_DecrRefCount(clockObj);
	if (status != TCL_OK) {
	    goto error2;
	}
    }








|







2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474

    if (safe) {
	Tcl_Obj *clockObj;
	int status;

	TclNewLiteralStringObj(clockObj, "clock");
	Tcl_IncrRefCount(clockObj);
	status = TclAliasCreate(interp, childInterp, parentInterp, clockObj,
		clockObj, 0, NULL);
	Tcl_DecrRefCount(clockObj);
	if (status != TCL_OK) {
	    goto error2;
	}
    }

2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
		return AliasDescribe(interp, childInterp, objv[2]);
	    }
	    if (TclGetString(objv[3])[0] == '\0') {
		if (objc == 4) {
		    return AliasDelete(interp, childInterp, objv[2]);
		}
	    } else {
		return AliasCreate(interp, childInterp, interp, objv[2],
			objv[3], objc - 4, objv + 4);
	    }
	}
	Tcl_WrongNumArgs(interp, 2, objv, "aliasName ?targetName? ?arg ...?");
	return TCL_ERROR;
    case OPT_ALIASES:
	if (objc != 2) {







|







2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
		return AliasDescribe(interp, childInterp, objv[2]);
	    }
	    if (TclGetString(objv[3])[0] == '\0') {
		if (objc == 4) {
		    return AliasDelete(interp, childInterp, objv[2]);
		}
	    } else {
		return TclAliasCreate(interp, childInterp, interp, objv[2],
			objv[3], objc - 4, objv + 4);
	    }
	}
	Tcl_WrongNumArgs(interp, 2, objv, "aliasName ?targetName? ?arg ...?");
	return TCL_ERROR;
    case OPT_ALIASES:
	if (objc != 2) {
Changes to generic/tclNotify.c.
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
 *
 *----------------------------------------------------------------------
 */

void
Tcl_QueueEvent(
    Tcl_Event *evPtr,		/* Event to add to queue. The storage space
				 * must have been allocated the caller with
				 * malloc (Tcl_Alloc), and it becomes the
				 * property of the event queue. It will be
				 * freed after the event has been handled. */
    int position)		/* One of TCL_QUEUE_TAIL, TCL_QUEUE_HEAD, TCL_QUEUE_MARK,
				 * possibly combined with TCL_QUEUE_ALERT_IF_EMPTY. */
{
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);







|







386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
 *
 *----------------------------------------------------------------------
 */

void
Tcl_QueueEvent(
    Tcl_Event *evPtr,		/* Event to add to queue. The storage space
				 * must have been allocated by the caller with
				 * malloc (Tcl_Alloc), and it becomes the
				 * property of the event queue. It will be
				 * freed after the event has been handled. */
    int position)		/* One of TCL_QUEUE_TAIL, TCL_QUEUE_HEAD, TCL_QUEUE_MARK,
				 * possibly combined with TCL_QUEUE_ALERT_IF_EMPTY. */
{
    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);
Changes to generic/tclOO.c.
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
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "tclInt.h"
#include "tclOOInt.h"




























/*
 * Commands in oo::define and oo::objdefine.
 */

static const struct {
    const char *name;
    Tcl_ObjCmdProc *objProc;
    int flag;
} defineCmds[] = {

    {"constructor", TclOODefineConstructorObjCmd, 0},
    {"definitionnamespace", TclOODefineDefnNsObjCmd, 0},
    {"deletemethod", TclOODefineDeleteMethodObjCmd, 0},
    {"destructor", TclOODefineDestructorObjCmd, 0},
    {"export", TclOODefineExportObjCmd, 0},
    {"forward", TclOODefineForwardObjCmd, 0},


    {"method", TclOODefineMethodObjCmd, 0},
    {"private", TclOODefinePrivateObjCmd, 0},
    {"renamemethod", TclOODefineRenameMethodObjCmd, 0},
    {"self", TclOODefineSelfObjCmd, 0},
    {"unexport", TclOODefineUnexportObjCmd, 0},
    {NULL, NULL, 0}
}, objdefCmds[] = {
    {"class", TclOODefineClassObjCmd, 1},
    {"deletemethod", TclOODefineDeleteMethodObjCmd, 1},
    {"export", TclOODefineExportObjCmd, 1},
    {"forward", TclOODefineForwardObjCmd, 1},
    {"method", TclOODefineMethodObjCmd, 1},
    {"private", TclOODefinePrivateObjCmd, 1},
    {"renamemethod", TclOODefineRenameMethodObjCmd, 1},
    {"self", TclOODefineObjSelfObjCmd, 0},
    {"unexport", TclOODefineUnexportObjCmd, 1},
    {NULL, NULL, 0}
};

/*
 * What sort of size of things we like to allocate.
 */

#define ALLOC_CHUNK 8

/*
 * Function declarations for things defined in this file.
 */

static Object *		AllocObject(Tcl_Interp *interp, const char *nameStr,
			    Namespace *nsPtr, const char *nsNameStr);
static int		CloneClassMethod(Tcl_Interp *interp, Class *clsPtr,
			    Method *mPtr, Tcl_Obj *namePtr,
			    Method **newMPtrPtr);
static int		CloneObjectMethod(Tcl_Interp *interp, Object *oPtr,
			    Method *mPtr, Tcl_Obj *namePtr);
static void		DeletedHelpersNamespace(void *clientData);
static Tcl_NRPostProc	FinalizeAlloc;
static Tcl_NRPostProc	FinalizeNext;
static Tcl_NRPostProc	FinalizeObjectCall;
static inline void	InitClassPath(Tcl_Interp * interp, Class *clsPtr);
static void		InitClassSystemRoots(Tcl_Interp *interp,
			    Foundation *fPtr);
static int		InitFoundation(Tcl_Interp *interp);
static Tcl_InterpDeleteProc	KillFoundation;
static void		MyDeleted(void *clientData);
static void		ObjectNamespaceDeleted(void *clientData);
static Tcl_CommandTraceProc	ObjectRenamedTrace;
static inline void	RemoveClass(Class **list, size_t num, size_t idx);
static inline void	RemoveObject(Object **list, size_t num, size_t idx);
static inline void	SquelchCachedName(Object *oPtr);

static int		PublicNRObjectCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const *objv);
static int		PrivateNRObjectCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const *objv);
static int		MyClassNRObjCmd(void *clientData,
			    Tcl_Interp *interp, int objc,
			    Tcl_Obj *const *objv);
static void		MyClassDeleted(void *clientData);

/*
 * Methods in the oo::object and oo::class classes. First, we define a helper
 * macro that makes building the method type declaration structure a lot
 * easier. No point in making life harder than it has to be!
 *
 * Note that the core methods don't need clone or free proc callbacks.







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




|




>
|

|
|
|
|
>
>
|
|
|
|
|


|
|
|
|
|
|
|
|
|




















|








|
|





|
<
<
|
<
<
|
<
<
|







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
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116


117


118


119
120
121
122
123
124
125
126

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "tclInt.h"
#include "tclOOInt.h"

/*
 * Commands in oo and oo::Helpers.
 */

static const struct StdCommands {
    const char *name;
    Tcl_ObjCmdProc *objProc;
    Tcl_ObjCmdProc *nreProc;
    CompileProc *compileProc;
    int flags;
} ooCmds[] = {
    {"define",		TclOODefineObjCmd, NULL, NULL, 0},
    {"objdefine",	TclOOObjDefObjCmd, NULL, NULL, 0},
    {"copy",		TclOOCopyObjectCmd, NULL, NULL, 0},
    {"DelegateName",	TclOODelegateNameObjCmd, NULL, NULL, 0},
    {NULL, NULL, NULL, NULL, 0}
}, helpCmds[] = {
    {"callback",	TclOOCallbackObjCmd, NULL, NULL, 0},
    {"mymethod",	TclOOCallbackObjCmd, NULL, NULL, 0},
    {"classvariable",	TclOOClassVariableObjCmd, NULL, NULL, 0},
    {"link",		TclOOLinkObjCmd, NULL, NULL, 0},
    {"next",		NULL, TclOONextObjCmd, TclCompileObjectNextCmd, CMD_COMPILES_EXPANDED},
    {"nextto",		NULL, TclOONextToObjCmd, TclCompileObjectNextToCmd, CMD_COMPILES_EXPANDED},
    {"self",		TclOOSelfObjCmd, NULL, TclCompileObjectSelfCmd, 0},
    {NULL, NULL, NULL, NULL, 0}
};

/*
 * Commands in oo::define and oo::objdefine.
 */

static const struct DefineCommands {
    const char *name;
    Tcl_ObjCmdProc *objProc;
    int flag;
} defineCmds[] = {
    {"classmethod",	TclOODefineClassMethodObjCmd, 0},
    {"constructor",	TclOODefineConstructorObjCmd, 0},
    {"definitionnamespace", TclOODefineDefnNsObjCmd, 0},
    {"deletemethod",	TclOODefineDeleteMethodObjCmd, 0},
    {"destructor",	TclOODefineDestructorObjCmd, 0},
    {"export",		TclOODefineExportObjCmd, 0},
    {"forward",		TclOODefineForwardObjCmd, 0},
    {"initialise",	TclOODefineInitialiseObjCmd, 0},
    {"initialize",	TclOODefineInitialiseObjCmd, 0},
    {"method",		TclOODefineMethodObjCmd, 0},
    {"private",		TclOODefinePrivateObjCmd, 0},
    {"renamemethod",	TclOODefineRenameMethodObjCmd, 0},
    {"self",		TclOODefineSelfObjCmd, 0},
    {"unexport",	TclOODefineUnexportObjCmd, 0},
    {NULL, NULL, 0}
}, objdefCmds[] = {
    {"class",		TclOODefineClassObjCmd, 1},
    {"deletemethod",	TclOODefineDeleteMethodObjCmd, 1},
    {"export",		TclOODefineExportObjCmd, 1},
    {"forward",		TclOODefineForwardObjCmd, 1},
    {"method",		TclOODefineMethodObjCmd, 1},
    {"private",		TclOODefinePrivateObjCmd, 1},
    {"renamemethod",	TclOODefineRenameMethodObjCmd, 1},
    {"self",		TclOODefineObjSelfObjCmd, 0},
    {"unexport",	TclOODefineUnexportObjCmd, 1},
    {NULL, NULL, 0}
};

/*
 * What sort of size of things we like to allocate.
 */

#define ALLOC_CHUNK 8

/*
 * Function declarations for things defined in this file.
 */

static Object *		AllocObject(Tcl_Interp *interp, const char *nameStr,
			    Namespace *nsPtr, const char *nsNameStr);
static int		CloneClassMethod(Tcl_Interp *interp, Class *clsPtr,
			    Method *mPtr, Tcl_Obj *namePtr,
			    Method **newMPtrPtr);
static int		CloneObjectMethod(Tcl_Interp *interp, Object *oPtr,
			    Method *mPtr, Tcl_Obj *namePtr);
static Tcl_NamespaceDeleteProc	DeletedHelpersNamespace;
static Tcl_NRPostProc	FinalizeAlloc;
static Tcl_NRPostProc	FinalizeNext;
static Tcl_NRPostProc	FinalizeObjectCall;
static inline void	InitClassPath(Tcl_Interp * interp, Class *clsPtr);
static void		InitClassSystemRoots(Tcl_Interp *interp,
			    Foundation *fPtr);
static int		InitFoundation(Tcl_Interp *interp);
static Tcl_InterpDeleteProc	KillFoundation;
static Tcl_CmdDeleteProc	MyDeleted;
static Tcl_NamespaceDeleteProc	ObjectNamespaceDeleted;
static Tcl_CommandTraceProc	ObjectRenamedTrace;
static inline void	RemoveClass(Class **list, size_t num, size_t idx);
static inline void	RemoveObject(Object **list, size_t num, size_t idx);
static inline void	SquelchCachedName(Object *oPtr);

static Tcl_ObjCmdProc	PublicNRObjectCmd;


static Tcl_ObjCmdProc	PrivateNRObjectCmd;


static Tcl_ObjCmdProc	MyClassNRObjCmd;


static Tcl_CmdDeleteProc	MyClassDeleted;

/*
 * Methods in the oo::object and oo::class classes. First, we define a helper
 * macro that makes building the method type declaration structure a lot
 * easier. No point in making life harder than it has to be!
 *
 * Note that the core methods don't need clone or free proc callbacks.
139
140
141
142
143
144
145
146
147

148
149
150
151
152
153
154
 */

static const char initScript[] =
#ifndef TCL_NO_DEPRECATED
"package ifneeded TclOO " TCLOO_PATCHLEVEL " {# Already present, OK?};"
#endif
"package ifneeded tcl::oo " TCLOO_PATCHLEVEL " {# Already present, OK?};"
"namespace eval ::oo { variable version " TCLOO_VERSION " };"
"namespace eval ::oo { variable patchlevel " TCLOO_PATCHLEVEL " };";

/* "tcl_findLibrary tcloo $oo::version $oo::version" */
/* " tcloo.tcl OO_LIBRARY oo::library;"; */

/*
 * The scripted part of the definitions of TclOO.
 */








|
|
>







163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
 */

static const char initScript[] =
#ifndef TCL_NO_DEPRECATED
"package ifneeded TclOO " TCLOO_PATCHLEVEL " {# Already present, OK?};"
#endif
"package ifneeded tcl::oo " TCLOO_PATCHLEVEL " {# Already present, OK?};"
"namespace eval ::oo {"
"    variable version " TCLOO_VERSION " patchlevel " TCLOO_PATCHLEVEL
"};";
/* "tcl_findLibrary tcloo $oo::version $oo::version" */
/* " tcloo.tcl OO_LIBRARY oo::library;"; */

/*
 * The scripted part of the definitions of TclOO.
 */

364
365
366
367
368
369
370
371



372
373
374
375
376
377
378



379
380
381
382
383
384
385

    TclNewLiteralStringObj(fPtr->unknownMethodNameObj, "unknown");
    TclNewLiteralStringObj(fPtr->constructorName, "<constructor>");
    TclNewLiteralStringObj(fPtr->destructorName, "<destructor>");
    TclNewLiteralStringObj(fPtr->clonedName, "<cloned>");
    TclNewLiteralStringObj(fPtr->defineName, "::oo::define");
    TclNewLiteralStringObj(fPtr->myName, "my");
    TclNewLiteralStringObj(fPtr->mcdName, "::oo::MixinClassDelegates");



    Tcl_IncrRefCount(fPtr->unknownMethodNameObj);
    Tcl_IncrRefCount(fPtr->constructorName);
    Tcl_IncrRefCount(fPtr->destructorName);
    Tcl_IncrRefCount(fPtr->clonedName);
    Tcl_IncrRefCount(fPtr->defineName);
    Tcl_IncrRefCount(fPtr->myName);
    Tcl_IncrRefCount(fPtr->mcdName);




    TclCreateObjCommandInNs(interp, "UnknownDefinition", fPtr->ooNs,
	    TclOOUnknownDefinition, NULL, NULL);
    TclNewLiteralStringObj(namePtr, "::oo::UnknownDefinition");
    Tcl_SetNamespaceUnknownHandler(interp, define, namePtr);
    Tcl_SetNamespaceUnknownHandler(interp, objdef, namePtr);
    Tcl_BounceRefCount(namePtr);







|
>
>
>






|
>
>
>







389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416

    TclNewLiteralStringObj(fPtr->unknownMethodNameObj, "unknown");
    TclNewLiteralStringObj(fPtr->constructorName, "<constructor>");
    TclNewLiteralStringObj(fPtr->destructorName, "<destructor>");
    TclNewLiteralStringObj(fPtr->clonedName, "<cloned>");
    TclNewLiteralStringObj(fPtr->defineName, "::oo::define");
    TclNewLiteralStringObj(fPtr->myName, "my");
    TclNewLiteralStringObj(fPtr->slotGetName, "Get");
    TclNewLiteralStringObj(fPtr->slotSetName, "Set");
    TclNewLiteralStringObj(fPtr->slotResolveName, "Resolve");
    TclNewLiteralStringObj(fPtr->slotDefOpName, "--default-operation");
    Tcl_IncrRefCount(fPtr->unknownMethodNameObj);
    Tcl_IncrRefCount(fPtr->constructorName);
    Tcl_IncrRefCount(fPtr->destructorName);
    Tcl_IncrRefCount(fPtr->clonedName);
    Tcl_IncrRefCount(fPtr->defineName);
    Tcl_IncrRefCount(fPtr->myName);
    Tcl_IncrRefCount(fPtr->slotGetName);
    Tcl_IncrRefCount(fPtr->slotSetName);
    Tcl_IncrRefCount(fPtr->slotResolveName);
    Tcl_IncrRefCount(fPtr->slotDefOpName);

    TclCreateObjCommandInNs(interp, "UnknownDefinition", fPtr->ooNs,
	    TclOOUnknownDefinition, NULL, NULL);
    TclNewLiteralStringObj(namePtr, "::oo::UnknownDefinition");
    Tcl_SetNamespaceUnknownHandler(interp, define, namePtr);
    Tcl_SetNamespaceUnknownHandler(interp, objdef, namePtr);
    Tcl_BounceRefCount(namePtr);
426
427
428
429
430
431
432
433
434
435
436
437

438
439

440

441
442

443
444
445
446
447
448
449
	    (Tcl_Class) fPtr->classCls, NULL, 0, &classConstructor, NULL);

    /*
     * Create non-object commands and plug ourselves into the Tcl [info]
     * ensemble.
     */

    CreateCmdInNS(interp, fPtr->helpersNs, "next",
	    NULL, TclOONextObjCmd, TclCompileObjectNextCmd, CMD_COMPILES_EXPANDED);
    CreateCmdInNS(interp, fPtr->helpersNs, "nextto",
	    NULL, TclOONextToObjCmd, TclCompileObjectNextToCmd, CMD_COMPILES_EXPANDED);
    CreateCmdInNS(interp, fPtr->helpersNs, "self",

	    TclOOSelfObjCmd, NULL, TclCompileObjectSelfCmd, 0);


    CreateCmdInNS(interp, fPtr->ooNs, "define", TclOODefineObjCmd, NULL, NULL, 0);

    CreateCmdInNS(interp, fPtr->ooNs, "objdefine", TclOOObjDefObjCmd, NULL, NULL, 0);
    CreateCmdInNS(interp, fPtr->ooNs, "copy", TclOOCopyObjectCmd, NULL, NULL, 0);


    TclOOInitInfo(interp);

    /*
     * Now make the class of slots.
     */








|
<
|
<
<
>
|
|
>
|
>
|
<
>







457
458
459
460
461
462
463
464

465


466
467
468
469
470
471
472

473
474
475
476
477
478
479
480
	    (Tcl_Class) fPtr->classCls, NULL, 0, &classConstructor, NULL);

    /*
     * Create non-object commands and plug ourselves into the Tcl [info]
     * ensemble.
     */

    for (i = 0 ; helpCmds[i].name ; i++) {

	CreateCmdInNS(interp, fPtr->helpersNs, helpCmds[i].name,


		helpCmds[i].objProc, helpCmds[i].nreProc,
		helpCmds[i].compileProc, helpCmds[i].flags);
    }
    for (i = 0 ; ooCmds[i].name ; i++) {
	CreateCmdInNS(interp, fPtr->ooNs, ooCmds[i].name,
		ooCmds[i].objProc, ooCmds[i].nreProc,
		ooCmds[i].compileProc, ooCmds[i].flags);

    }

    TclOOInitInfo(interp);

    /*
     * Now make the class of slots.
     */

610
611
612
613
614
615
616
617



618
619
620
621
622
623
624

    TclDecrRefCount(fPtr->unknownMethodNameObj);
    TclDecrRefCount(fPtr->constructorName);
    TclDecrRefCount(fPtr->destructorName);
    TclDecrRefCount(fPtr->clonedName);
    TclDecrRefCount(fPtr->defineName);
    TclDecrRefCount(fPtr->myName);
    TclDecrRefCount(fPtr->mcdName);



    TclOODecrRefCount(fPtr->objectCls->thisPtr);
    TclOODecrRefCount(fPtr->classCls->thisPtr);

    Tcl_Free(fPtr);

    /*
     * Don't leave the interpreter field pointing to freed data.







|
>
>
>







641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658

    TclDecrRefCount(fPtr->unknownMethodNameObj);
    TclDecrRefCount(fPtr->constructorName);
    TclDecrRefCount(fPtr->destructorName);
    TclDecrRefCount(fPtr->clonedName);
    TclDecrRefCount(fPtr->defineName);
    TclDecrRefCount(fPtr->myName);
    TclDecrRefCount(fPtr->slotGetName);
    TclDecrRefCount(fPtr->slotSetName);
    TclDecrRefCount(fPtr->slotResolveName);
    TclDecrRefCount(fPtr->slotDefOpName);
    TclOODecrRefCount(fPtr->objectCls->thisPtr);
    TclOODecrRefCount(fPtr->classCls->thisPtr);

    Tcl_Free(fPtr);

    /*
     * Don't leave the interpreter field pointing to freed data.
794
795
796
797
798
799
800

801
802
803
804
805
806
807
    tracePtr->refCount = 1;

    oPtr->myCommand = TclNRCreateCommandInNs(interp, "my", oPtr->namespacePtr,
	    TclOOPrivateObjectCmd, PrivateNRObjectCmd, oPtr, MyDeleted);
    oPtr->myclassCommand = TclNRCreateCommandInNs(interp, "myclass",
	    oPtr->namespacePtr, TclOOMyClassObjCmd, MyClassNRObjCmd, oPtr,
	    MyClassDeleted);

    return oPtr;
}

/*
 * ----------------------------------------------------------------------
 *
 * SquelchCachedName --







>







828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
    tracePtr->refCount = 1;

    oPtr->myCommand = TclNRCreateCommandInNs(interp, "my", oPtr->namespacePtr,
	    TclOOPrivateObjectCmd, PrivateNRObjectCmd, oPtr, MyDeleted);
    oPtr->myclassCommand = TclNRCreateCommandInNs(interp, "myclass",
	    oPtr->namespacePtr, TclOOMyClassObjCmd, MyClassNRObjCmd, oPtr,
	    MyClassDeleted);
    oPtr->linkedCmdsList = NULL;
    return oPtr;
}

/*
 * ----------------------------------------------------------------------
 *
 * SquelchCachedName --
838
839
840
841
842
843
844











845
846
847
848
849
850
851
static void
MyDeleted(
    void *clientData)		/* Reference to the object whose [my] has been
				 * squelched. */
{
    Object *oPtr = (Object *) clientData;












    oPtr->myCommand = NULL;
}

static void
MyClassDeleted(
    void *clientData)
{







>
>
>
>
>
>
>
>
>
>
>







873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
static void
MyDeleted(
    void *clientData)		/* Reference to the object whose [my] has been
				 * squelched. */
{
    Object *oPtr = (Object *) clientData;

    if (oPtr->linkedCmdsList) {
	Tcl_Size linkc, i;
	Tcl_Obj **linkv;
	TclListObjGetElements(NULL, oPtr->linkedCmdsList, &linkc, &linkv);
	for (i=0 ; i<linkc ; i++) {
	    Tcl_Obj *link = linkv[i];
	    (void) Tcl_DeleteCommand(oPtr->fPtr->interp, TclGetString(link));
	}
	Tcl_DecrRefCount(oPtr->linkedCmdsList);
	oPtr->linkedCmdsList = NULL;
    }
    oPtr->myCommand = NULL;
}

static void
MyClassDeleted(
    void *clientData)
{
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
    /*
     * Instruct everyone to no longer use any allocated fields of the object.
     * Also delete the command that refers to the object at this point (if it
     * still exists) because otherwise its pointer to the object points into
     * freed memory.
     */

    if (((Command *) oPtr->command)->flags && CMD_DYING) {
	/*
	 * Something has already started the command deletion process. We can
	 * go ahead and clean up the namespace,
	 */
    } else {
	/*
	 * The namespace must have been deleted directly.  Delete the command







|







1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
    /*
     * Instruct everyone to no longer use any allocated fields of the object.
     * Also delete the command that refers to the object at this point (if it
     * still exists) because otherwise its pointer to the object points into
     * freed memory.
     */

    if (((Command *) oPtr->command)->flags & CMD_DYING) {
	/*
	 * Something has already started the command deletion process. We can
	 * go ahead and clean up the namespace,
	 */
    } else {
	/*
	 * The namespace must have been deleted directly.  Delete the command
3115
3116
3117
3118
3119
3120
3121
























3122
3123
3124
3125
3126
3127
3128
Tcl_Obj *
Tcl_GetObjectName(
    Tcl_Interp *interp,
    Tcl_Object object)
{
    return TclOOObjectName(interp, (Object *) object);
}

























/*
 * ----------------------------------------------------------------------
 *
 * assorted trivial 'getter' functions
 *
 * ----------------------------------------------------------------------







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







3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
Tcl_Obj *
Tcl_GetObjectName(
    Tcl_Interp *interp,
    Tcl_Object object)
{
    return TclOOObjectName(interp, (Object *) object);
}

/*
 * ----------------------------------------------------------------------
 *
 * TclOOObjectMyName --
 *
 *	Utility function that returns the name of the object's [my], or NULL
 *	if it has been deleted (or otherwise doesn't exist).
 *
 * ----------------------------------------------------------------------
 */
Tcl_Obj *
TclOOObjectMyName(
    Tcl_Interp *interp,
    Object *oPtr)
{
    if (!oPtr->myCommand) {
	return NULL;
    }
    Tcl_Obj *namePtr;
    TclNewObj(namePtr);
    Tcl_GetCommandFullName(interp, oPtr->myCommand, namePtr);
    return namePtr;
}

/*
 * ----------------------------------------------------------------------
 *
 * assorted trivial 'getter' functions
 *
 * ----------------------------------------------------------------------
Changes to generic/tclOOBasic.c.
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#endif
#include "tclInt.h"
#include "tclOOInt.h"
#include "tclTomMath.h"

static inline Tcl_Object *AddConstructionFinalizer(Tcl_Interp *interp);
static Tcl_NRPostProc	AfterNRDestructor;
static Tcl_NRPostProc	DecrRefsPostClassConstructor;
static Tcl_NRPostProc	FinalizeConstruction;
static Tcl_NRPostProc	FinalizeEval;
static Tcl_NRPostProc	NextRestoreFrame;

/*
 * ----------------------------------------------------------------------
 *







|







15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#endif
#include "tclInt.h"
#include "tclOOInt.h"
#include "tclTomMath.h"

static inline Tcl_Object *AddConstructionFinalizer(Tcl_Interp *interp);
static Tcl_NRPostProc	AfterNRDestructor;
static Tcl_NRPostProc	PostClassConstructor;
static Tcl_NRPostProc	FinalizeConstruction;
static Tcl_NRPostProc	FinalizeEval;
static Tcl_NRPostProc	NextRestoreFrame;

/*
 * ----------------------------------------------------------------------
 *
64
65
66
67
68
69
70

















































































































71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105

106
107
108
109
110
111
112
113
114



115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145




146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172



173
174
175
176
177
178
179
    Tcl_SetObjResult(interp, TclOOObjectName(interp, oPtr));
    return TCL_OK;
}

/*
 * ----------------------------------------------------------------------
 *

















































































































 * TclOO_Class_Constructor --
 *
 *	Implementation for oo::class constructor.
 *
 * ----------------------------------------------------------------------
 */

int
TclOO_Class_Constructor(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    Tcl_ObjectContext context,
    int objc,
    Tcl_Obj *const *objv)
{
    Object *oPtr = (Object *) Tcl_ObjectContextObject(context);
    Tcl_Obj **invoke, *nameObj;

    size_t skip = Tcl_ObjectContextSkippedArgs(context);
    if ((size_t) objc > skip + 1) {
	Tcl_WrongNumArgs(interp, skip, objv,
		"?definitionScript?");
	return TCL_ERROR;
    }

    /*
     * Make the class definition delegate. This is special; it doesn't reenter
     * here (and the class definition delegate doesn't run any constructors).
     *
     * This needs to be done before consideration of whether to pass the script
     * argument to [oo::define]. [Bug 680503]
     */

    nameObj = Tcl_ObjPrintf("%s:: oo ::delegate",
	    oPtr->namespacePtr->fullName);

    Tcl_NewObjectInstance(interp, (Tcl_Class) oPtr->fPtr->classCls,
	    TclGetString(nameObj), NULL, TCL_INDEX_NONE, NULL, 0);
    Tcl_BounceRefCount(nameObj);

    /*
     * If there's nothing else to do, we're done.
     */

    if ((size_t) objc == skip) {



	return TCL_OK;
    }

    /*
     * Delegate to [oo::define] to do the work.
     */

    invoke = (Tcl_Obj **) TclStackAlloc(interp, 3 * sizeof(Tcl_Obj *));
    invoke[0] = oPtr->fPtr->defineName;
    invoke[1] = TclOOObjectName(interp, oPtr);
    invoke[2] = objv[objc - 1];

    /*
     * Must add references or errors in configuration script will cause
     * trouble.
     */

    Tcl_IncrRefCount(invoke[0]);
    Tcl_IncrRefCount(invoke[1]);
    Tcl_IncrRefCount(invoke[2]);
    TclNRAddCallback(interp, DecrRefsPostClassConstructor,
	    invoke, oPtr, NULL, NULL);

    /*
     * Tricky point: do not want the extra reported level in the Tcl stack
     * trace, so use TCL_EVAL_NOERR.
     */

    return TclNREvalObjv(interp, 3, invoke, TCL_EVAL_NOERR, NULL);
}





static int
DecrRefsPostClassConstructor(
    void *data[],
    Tcl_Interp *interp,
    int result)
{
    Tcl_Obj **invoke = (Tcl_Obj **) data[0];
    Object *oPtr = (Object *) data[1];
    Tcl_InterpState saved;
    int code;

    TclDecrRefCount(invoke[0]);
    TclDecrRefCount(invoke[1]);
    TclDecrRefCount(invoke[2]);
    invoke[0] = oPtr->fPtr->mcdName;
    invoke[1] = TclOOObjectName(interp, oPtr);
    Tcl_IncrRefCount(invoke[0]);
    Tcl_IncrRefCount(invoke[1]);
    saved = Tcl_SaveInterpState(interp, result);
    code = Tcl_EvalObjv(interp, 2, invoke, 0);
    TclDecrRefCount(invoke[0]);
    TclDecrRefCount(invoke[1]);
    TclStackFree(interp, invoke);
    if (code != TCL_OK) {
	Tcl_DiscardInterpState(saved);
	return code;
    }



    return Tcl_RestoreInterpState(interp, saved);
}

/*
 * ----------------------------------------------------------------------
 *
 * TclOO_Class_Create --







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
















<
















|

>

|
<






>
>
>
|






|












|
|









>
>
>
>

|






|
<




<
<
<
<
<
<
<
<

<
<
<
|
>
>
>







64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199

200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220

221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
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
    Tcl_SetObjResult(interp, TclOOObjectName(interp, oPtr));
    return TCL_OK;
}

/*
 * ----------------------------------------------------------------------
 *
 * MixinClassDelegates --
 *
 *	Internal utility for setting up the class delegate.
 *	Runs after the class has called [oo::define] on its argument.
 *
 * ----------------------------------------------------------------------
 */

// Look up the delegate for a class.
static inline Class *
GetClassDelegate(
    Tcl_Interp *interp,
    Class *clsPtr)
{
    Tcl_Obj *delegateName = Tcl_ObjPrintf("%s:: oo ::delegate",
	    clsPtr->thisPtr->namespacePtr->fullName);
    Class *delegatePtr = TclOOGetClassFromObj(interp, delegateName);
    Tcl_DecrRefCount(delegateName);
    return delegatePtr;
}

/*
 * Patches in the appropriate class delegates' superclasses.
 * Sonewhat messy because the list of superclasses isn't modified frequently.
 */
static inline void
SetDelegateSuperclasses(
    Tcl_Interp *interp,
    Class *clsPtr,
    Class *delegatePtr)
{
    // Build new list of superclasses
    int i, j = delegatePtr->superclasses.num, k;
    Class *superPtr, **supers = (Class **) Tcl_Alloc(sizeof(Class *) *
	    (delegatePtr->superclasses.num + clsPtr->superclasses.num));
    if (delegatePtr->superclasses.num) {
	memcpy(supers, delegatePtr->superclasses.list,
		sizeof(Class *) * delegatePtr->superclasses.num);
    }
    FOREACH(superPtr, clsPtr->superclasses) {
	Class *superDelegatePtr = GetClassDelegate(interp, superPtr);
	if (!superDelegatePtr) {
	    continue;
	}
	for (k=0 ; k<=j ; k++) {
	    if (k == j) {
		supers[j++] = superDelegatePtr;
		TclOOAddToSubclasses(delegatePtr, superDelegatePtr);
		AddRef(superDelegatePtr->thisPtr);
		break;
	    } else if (supers[k] == superDelegatePtr) {
		break;
	    }
	}
    }

    // Install new list of superclasses;
    if (delegatePtr->superclasses.num) {
	Tcl_Free(delegatePtr->superclasses.list);
    }
    delegatePtr->superclasses.list = supers;
    delegatePtr->superclasses.num = j;

    // Definitely don't need to bump any epoch here
}

/*
 * Mixes the delegate into its controlling class.
 */
static inline void
InstallDelegateAsMixin(
    Tcl_Interp *interp,
    Class *clsPtr,
    Class *delegatePtr)
{
    if (clsPtr->thisPtr->mixins.num == 0) {
	TclOOObjectSetMixins(clsPtr->thisPtr, 1, &delegatePtr);
	return;
    }
    Class **mixins = (Class **) TclStackAlloc(interp,
	    sizeof(Class *) * (clsPtr->thisPtr->mixins.num + 1));
    for (int i = 0; i < clsPtr->thisPtr->mixins.num; i++) {
	mixins[i] = clsPtr->thisPtr->mixins.list[i];
	if (mixins[i] == delegatePtr) {
	    TclStackFree(interp, (void *) mixins);
	    return;
	}
    }
    mixins[clsPtr->thisPtr->mixins.num] = delegatePtr;
    TclOOObjectSetMixins(clsPtr->thisPtr, clsPtr->thisPtr->mixins.num + 1, mixins);
    TclStackFree(interp, mixins);
}

// Patches in the appropriate class delegates.
static void
MixinClassDelegates(
    Tcl_Interp *interp,
    Object *oPtr,
    Tcl_Obj *delegateName)
{
    Class *clsPtr = oPtr->classPtr;
    if (clsPtr) {
	Class *delegatePtr = TclOOGetClassFromObj(interp, delegateName);
	if (delegatePtr) {
	    SetDelegateSuperclasses(interp, clsPtr, delegatePtr);
	    InstallDelegateAsMixin(interp, clsPtr, delegatePtr);
	}
    }
}

/*
 * ----------------------------------------------------------------------
 *
 * TclOO_Class_Constructor --
 *
 *	Implementation for oo::class constructor.
 *
 * ----------------------------------------------------------------------
 */

int
TclOO_Class_Constructor(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    Tcl_ObjectContext context,
    int objc,
    Tcl_Obj *const *objv)
{
    Object *oPtr = (Object *) Tcl_ObjectContextObject(context);


    size_t skip = Tcl_ObjectContextSkippedArgs(context);
    if ((size_t) objc > skip + 1) {
	Tcl_WrongNumArgs(interp, skip, objv,
		"?definitionScript?");
	return TCL_ERROR;
    }

    /*
     * Make the class definition delegate. This is special; it doesn't reenter
     * here (and the class definition delegate doesn't run any constructors).
     *
     * This needs to be done before consideration of whether to pass the script
     * argument to [oo::define]. [Bug 680503]
     */

    Tcl_Obj *delegateName = Tcl_ObjPrintf("%s:: oo ::delegate",
	    oPtr->namespacePtr->fullName);
    Tcl_IncrRefCount(delegateName);
    Tcl_NewObjectInstance(interp, (Tcl_Class) oPtr->fPtr->classCls,
	    TclGetString(delegateName), NULL, TCL_INDEX_NONE, NULL, 0);


    /*
     * If there's nothing else to do, we're done.
     */

    if ((size_t) objc == skip) {
	Tcl_InterpState saved = Tcl_SaveInterpState(interp, TCL_OK);
	MixinClassDelegates(interp, oPtr, delegateName);
	Tcl_DecrRefCount(delegateName);
	return Tcl_RestoreInterpState(interp, saved);
    }

    /*
     * Delegate to [oo::define] to do the work.
     */

    Tcl_Obj **invoke = (Tcl_Obj **) TclStackAlloc(interp, 3 * sizeof(Tcl_Obj *));
    invoke[0] = oPtr->fPtr->defineName;
    invoke[1] = TclOOObjectName(interp, oPtr);
    invoke[2] = objv[objc - 1];

    /*
     * Must add references or errors in configuration script will cause
     * trouble.
     */

    Tcl_IncrRefCount(invoke[0]);
    Tcl_IncrRefCount(invoke[1]);
    Tcl_IncrRefCount(invoke[2]);
    TclNRAddCallback(interp, PostClassConstructor,
	    invoke, oPtr, delegateName, NULL);

    /*
     * Tricky point: do not want the extra reported level in the Tcl stack
     * trace, so use TCL_EVAL_NOERR.
     */

    return TclNREvalObjv(interp, 3, invoke, TCL_EVAL_NOERR, NULL);
}

/*
 *	Called *after* [oo::define] inside the constructor of a class.
 *	Cleans up some temporary storage and sets up the delegate.
 */
static int
PostClassConstructor(
    void *data[],
    Tcl_Interp *interp,
    int result)
{
    Tcl_Obj **invoke = (Tcl_Obj **) data[0];
    Object *oPtr = (Object *) data[1];
    Tcl_Obj *delegateName = (Tcl_Obj *) data[2];


    TclDecrRefCount(invoke[0]);
    TclDecrRefCount(invoke[1]);
    TclDecrRefCount(invoke[2]);








    TclStackFree(interp, invoke);




    Tcl_InterpState saved = Tcl_SaveInterpState(interp, result);
    MixinClassDelegates(interp, oPtr, delegateName);
    Tcl_DecrRefCount(delegateName);
    return Tcl_RestoreInterpState(interp, saved);
}

/*
 * ----------------------------------------------------------------------
 *
 * TclOO_Class_Create --
900
901
902
903
904
905
906




























































































907
908
909
910
911
912
913
    Tcl_SetObjResult(interp, varNamePtr);
    return TCL_OK;
}

/*
 * ----------------------------------------------------------------------
 *




























































































 * TclOONextObjCmd, TclOONextToObjCmd --
 *
 *	Implementation of the [next] and [nextto] commands. Note that these
 *	commands are only ever to be used inside the body of a procedure-like
 *	method.
 *
 * ----------------------------------------------------------------------







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







1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
    Tcl_SetObjResult(interp, varNamePtr);
    return TCL_OK;
}

/*
 * ----------------------------------------------------------------------
 *
 * TclOOLinkObjCmd --
 *
 *	Implementation of the [link] command, that makes a command that
 *	invokes a method on the current object. The name of the command and
 *	the name of the method match by default. Note that this command is
 *	only ever to be used inside the body of a procedure-like method,
 *	and is typically intended for constructors.
 *
 * ----------------------------------------------------------------------
 */
int
TclOOLinkObjCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    // Set up common bits.
    CallFrame *framePtr = ((Interp *) interp)->varFramePtr;
    if (framePtr == NULL || !(framePtr->isProcCallFrame & FRAME_IS_METHOD)) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"%s may only be called from inside a method",
		TclGetString(objv[0])));
	OO_ERROR(interp, CONTEXT_REQUIRED);
	return TCL_ERROR;
    }
    CallContext *context = (CallContext *) framePtr->clientData;
    Object *oPtr = context->oPtr;
    if (!oPtr->myCommand) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"cannot link to non-existent callback handle"));
	OO_ERROR(interp, MY_GONE);
	return TCL_ERROR;
    }
    Tcl_Obj *myCmd = Tcl_NewObj();
    Tcl_GetCommandFullName(interp, oPtr->myCommand, myCmd);
    if (!oPtr->linkedCmdsList) {
	oPtr->linkedCmdsList = Tcl_NewListObj(0, NULL);
	Tcl_IncrRefCount(oPtr->linkedCmdsList);
    }

    // For each argument
    for (int i=1; i<objc; i++) {
	Tcl_Size linkc;
	Tcl_Obj **linkv, *src, *dst;

	// Parse as list of (one or) two items: source and destination names
	if (TclListObjGetElements(interp, objv[i], &linkc, &linkv) != TCL_OK) {
	    Tcl_BounceRefCount(myCmd);
	    return TCL_ERROR;
	}
	switch (linkc) {
	case 1:
	    // Degenerate case
	    src = dst = linkv[0];
	    break;
	case 2:
	    src = linkv[0];
	    dst = linkv[1];
	    break;
	default:
	    Tcl_BounceRefCount(myCmd);
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "bad link description; must only have one or two elements"));
	    OO_ERROR(interp, CMDLINK_FORMAT);
	    return TCL_ERROR;
	}

	// Qualify the source if necessary
	const char *srcStr = TclGetString(src);
	if (srcStr[0] != ':' || srcStr[1] != ':') {
	    src = Tcl_ObjPrintf("%s::%s",
		    context->oPtr->namespacePtr->fullName, srcStr);
	}

	// Make the alias command
	if (TclAliasCreate(interp, interp, interp, src, myCmd, 1, &dst) != TCL_OK) {
	    Tcl_BounceRefCount(myCmd);
	    Tcl_BounceRefCount(src);
	    return TCL_ERROR;
	}

	// Remember the alias for cleanup if necessary
	Tcl_ListObjAppendElement(NULL, oPtr->linkedCmdsList, src);
    }
    Tcl_BounceRefCount(myCmd);
    return TCL_OK;
}

/*
 * ----------------------------------------------------------------------
 *
 * TclOONextObjCmd, TclOONextToObjCmd --
 *
 *	Implementation of the [next] and [nextto] commands. Note that these
 *	commands are only ever to be used inside the body of a procedure-like
 *	method.
 *
 * ----------------------------------------------------------------------
1349
1350
1351
1352
1353
1354
1355























































































































































































1356
1357
1358
1359
1360
1361
1362
1363
    /*
     * Return the name of the cloned object.
     */

    Tcl_SetObjResult(interp, TclOOObjectName(interp, (Object *) o2Ptr));
    return TCL_OK;
}
























































































































































































/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */







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








1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
    /*
     * Return the name of the cloned object.
     */

    Tcl_SetObjResult(interp, TclOOObjectName(interp, (Object *) o2Ptr));
    return TCL_OK;
}

/*
 * ----------------------------------------------------------------------
 *
 * TclOOCallbackObjCmd --
 *
 *	Implementation of the [callback] command, which constructs callbacks
 *	into the current object.
 *
 * ----------------------------------------------------------------------
 */
int
TclOOCallbackObjCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    Interp *iPtr = (Interp *) interp;
    CallFrame *framePtr = iPtr->varFramePtr;

    /*
     * Start with sanity checks on the calling context to make sure that we
     * are invoked from a suitable method context. If so, we can safely
     * retrieve the handle to the object call context.
     */

    if (framePtr == NULL || !(framePtr->isProcCallFrame & FRAME_IS_METHOD)) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"%s may only be called from inside a method",
		TclGetString(objv[0])));
	OO_ERROR(interp, CONTEXT_REQUIRED);
	return TCL_ERROR;
    }

    CallContext *contextPtr = (CallContext *) framePtr->clientData;
    if (objc < 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "method ...");
	return TCL_ERROR;
    }

    // Get the [my] real name.
    Tcl_Obj *namePtr = TclOOObjectMyName(interp, contextPtr->oPtr);
    if (!namePtr) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"no possible safe callback without my", TCL_AUTO_LENGTH));
	OO_ERROR(interp, NO_MY);
	return TCL_ERROR;
    }

    // No check that the method exists; could be dynamically added.

    Tcl_Obj *listPtr = Tcl_NewListObj(1, &namePtr);
    (void) TclListObjAppendElements(NULL, listPtr, objc-1, objv+1);
    Tcl_SetObjResult(interp, listPtr);
    return TCL_OK;
}

/*
 * ----------------------------------------------------------------------
 *
 * TclOOClassVariableObjCmd --
 *
 *	Implementation of the [classvariable] command, which links to
 *	variables in the class of the current object.
 *
 * ----------------------------------------------------------------------
 */
int
TclOOClassVariableObjCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    Interp *iPtr = (Interp *) interp;
    CallFrame *framePtr = iPtr->varFramePtr;

    if (objc < 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "name ...");
	return TCL_ERROR;
    }

    /*
     * Start with sanity checks on the calling context to make sure that we
     * are invoked from a suitable method context. If so, we can safely
     * retrieve the handle to the object call context.
     */

    if (framePtr == NULL || !(framePtr->isProcCallFrame & FRAME_IS_METHOD)) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"%s may only be called from inside a method",
		TclGetString(objv[0])));
	OO_ERROR(interp, CONTEXT_REQUIRED);
	return TCL_ERROR;
    }

    // Get a reference to the class's namespace
    CallContext *contextPtr = (CallContext *) framePtr->clientData;
    Class *clsPtr = CurrentlyInvoked(contextPtr).mPtr->declaringClassPtr;
    if (clsPtr == NULL) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"method not defined by a class", TCL_AUTO_LENGTH));
	OO_ERROR(interp, UNMATCHED_CONTEXT);
	return TCL_ERROR;
    }
    Tcl_Namespace *clsNsPtr = clsPtr->thisPtr->namespacePtr;

    // Check the list of variable names
    for (int i = 1; i < objc; i++) {
	const char *varName = TclGetString(objv[i]);
	if (Tcl_StringMatch(varName, "*(*)")) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "bad variable name \"%s\": can't create a %s",
		    varName, "scalar variable that looks like an array element"));
	    Tcl_SetErrorCode(interp, "TCL", "UPVAR", "LOCAL_ELEMENT", NULL);
	    return TCL_ERROR;
	}
	if (Tcl_StringMatch(varName, "*::*")) {
	    Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		    "bad variable name \"%s\": can't create a %s",
		    varName, "local variable with a namespace separator in it"));
	    Tcl_SetErrorCode(interp, "TCL", "UPVAR", "LOCAL_ELEMENT", NULL);
	    return TCL_ERROR;
	}
    }

    // Lastly, link the caller's local variables to the class's variables
    Tcl_Namespace *ourNsPtr = (Tcl_Namespace *) iPtr->varFramePtr->nsPtr;
    for (int i = 1; i < objc; i++) {
	// Locate the other variable.
	iPtr->varFramePtr->nsPtr = (Namespace *) clsNsPtr;
	Var *arrayPtr, *otherPtr = TclObjLookupVarEx(interp, objv[i], NULL,
		(TCL_NAMESPACE_ONLY|TCL_LEAVE_ERR_MSG|TCL_AVOID_RESOLVERS),
		"access", /*createPart1*/ 1, /*createPart2*/ 0, &arrayPtr);
	iPtr->varFramePtr->nsPtr = (Namespace *) ourNsPtr;
	if (otherPtr == NULL) {
	    return TCL_ERROR;
	}

	// Create the new variable and link it to otherPtr.
	if (TclPtrObjMakeUpvarIdx(interp, otherPtr, objv[i], 0,
		TCL_INDEX_NONE) != TCL_OK) {
	    return TCL_ERROR;
	}
    }

    return TCL_OK;
}

/*
 * ----------------------------------------------------------------------
 *
 * TclOODelegateNameObjCmd --
 *
 *	Implementation of the [oo::DelegateName] command, which is a utility
 *	that gets the name of the class delegate for a class. It's trivial,
 *	but makes working with them much easier as delegate names are
 *	intentionally hard to create by accident.
 *
 *	Not part of TclOO public API. No public documentation.
 *
 * ----------------------------------------------------------------------
 */
int
TclOODelegateNameObjCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    if (objc != 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "class");
	return TCL_ERROR;
    }
    Class *clsPtr = TclOOGetClassFromObj(interp, objv[1]);
    if (clsPtr == NULL) {
	return TCL_ERROR;
    }
    Tcl_SetObjResult(interp, Tcl_ObjPrintf("%s:: oo ::delegate",
	    clsPtr->thisPtr->namespacePtr->fullName));
    return TCL_OK;
}

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */
Changes to generic/tclOODefineCmds.c.
33
34
35
36
37
38
39

40
41
42
43
44
45
46
47
48
49










50
51
52
53
54
55
56
 * Some things that make it easier to declare a slot.
 */
typedef struct DeclaredSlot {
    const char *name;
    const Tcl_MethodType getterType;
    const Tcl_MethodType setterType;
    const Tcl_MethodType resolverType;

} DeclaredSlot;

#define SLOT(name,getter,setter,resolver)				\
    {"::oo::" name,							\
	    {TCL_OO_METHOD_VERSION_CURRENT, "core method: " name " Getter", \
		    getter, NULL, NULL},				\
	    {TCL_OO_METHOD_VERSION_CURRENT, "core method: " name " Setter", \
		    setter, NULL, NULL},				\
	    {TCL_OO_METHOD_VERSION_CURRENT, "core method: " name " Resolver", \
		    resolver, NULL, NULL}}











/*
 * A [string match] pattern used to determine if a method should be exported.
 */

#define PUBLIC_PATTERN		"[a-z]*"








>


|

|

|

|
|
>
>
>
>
>
>
>
>
>
>







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
59
60
61
62
63
64
65
66
67
 * Some things that make it easier to declare a slot.
 */
typedef struct DeclaredSlot {
    const char *name;
    const Tcl_MethodType getterType;
    const Tcl_MethodType setterType;
    const Tcl_MethodType resolverType;
    const char *defaultOp;	// The default op, if not set by the class
} DeclaredSlot;

#define SLOT(name,getter,setter,resolver,defOp) \
    {"::oo::" name,							\
	    {TCL_OO_METHOD_VERSION_1, "core method: " name " Getter",	\
		    getter, NULL, NULL},				\
	    {TCL_OO_METHOD_VERSION_1, "core method: " name " Setter",	\
		    setter, NULL, NULL},				\
	    {TCL_OO_METHOD_VERSION_1, "core method: " name " Resolver",	\
		    resolver, NULL, NULL}, (defOp)}

typedef struct DeclaredSlotMethod {
    const char *name;
    int flags;
    const Tcl_MethodType implType;
} DeclaredSlotMethod;

#define SLOT_METHOD(name,impl,flags) \
    {name, flags, {TCL_OO_METHOD_VERSION_1,				\
	    "core method: " name " slot", impl, NULL, NULL}}

/*
 * A [string match] pattern used to determine if a method should be exported.
 */

#define PUBLIC_PATTERN		"[a-z]*"

74
75
76
77
78
79
80



























81
82
83
84
85
86
87
static inline int	InitDefineContext(Tcl_Interp *interp,
			    Tcl_Namespace *namespacePtr, Object *oPtr,
			    int objc, Tcl_Obj *const objv[]);
static inline void	RecomputeClassCacheFlag(Object *oPtr);
static int		RenameDeleteMethod(Tcl_Interp *interp, Object *oPtr,
			    int useClass, Tcl_Obj *const fromPtr,
			    Tcl_Obj *const toPtr);



























static int		ClassFilter_Get(void *clientData,
			    Tcl_Interp *interp, Tcl_ObjectContext context,
			    int objc, Tcl_Obj *const *objv);
static int		ClassFilter_Set(void *clientData,
			    Tcl_Interp *interp, Tcl_ObjectContext context,
			    int objc, Tcl_Obj *const *objv);
static int		ClassMixin_Get(void *clientData,







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







85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
static inline int	InitDefineContext(Tcl_Interp *interp,
			    Tcl_Namespace *namespacePtr, Object *oPtr,
			    int objc, Tcl_Obj *const objv[]);
static inline void	RecomputeClassCacheFlag(Object *oPtr);
static int		RenameDeleteMethod(Tcl_Interp *interp, Object *oPtr,
			    int useClass, Tcl_Obj *const fromPtr,
			    Tcl_Obj *const toPtr);
static int		Slot_Append(void *,
			    Tcl_Interp *interp, Tcl_ObjectContext context,
			    int objc, Tcl_Obj *const *objv);
static int		Slot_AppendNew(void *,
			    Tcl_Interp *interp, Tcl_ObjectContext context,
			    int objc, Tcl_Obj *const *objv);
static int		Slot_Clear(void *,
			    Tcl_Interp *interp, Tcl_ObjectContext context,
			    int objc, Tcl_Obj *const *objv);
static int		Slot_Prepend(void *,
			    Tcl_Interp *interp, Tcl_ObjectContext context,
			    int objc, Tcl_Obj *const *objv);
static int		Slot_Remove(void *,
			    Tcl_Interp *interp, Tcl_ObjectContext context,
			    int objc, Tcl_Obj *const *objv);
static int		Slot_Resolve(void *,
			    Tcl_Interp *interp, Tcl_ObjectContext context,
			    int objc, Tcl_Obj *const *objv);
static int		Slot_Set(void *,
			    Tcl_Interp *interp, Tcl_ObjectContext context,
			    int objc, Tcl_Obj *const *objv);
static int		Slot_Unimplemented(void *,
			    Tcl_Interp *interp, Tcl_ObjectContext,
			    int, Tcl_Obj *const *);
static int		Slot_Unknown(void *,
			    Tcl_Interp *interp, Tcl_ObjectContext context,
			    int objc, Tcl_Obj *const *objv);
static int		ClassFilter_Get(void *clientData,
			    Tcl_Interp *interp, Tcl_ObjectContext context,
			    int objc, Tcl_Obj *const *objv);
static int		ClassFilter_Set(void *clientData,
			    Tcl_Interp *interp, Tcl_ObjectContext context,
			    int objc, Tcl_Obj *const *objv);
static int		ClassMixin_Get(void *clientData,
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175














176
177
178
179
180
181
182
			    int objc, Tcl_Obj *const *objv);

/*
 * Now define the slots used in declarations.
 */

static const DeclaredSlot slots[] = {
    SLOT("define::filter",      ClassFilter_Get, ClassFilter_Set, NULL),
    SLOT("define::mixin",       ClassMixin_Get,  ClassMixin_Set, ResolveClass),
    SLOT("define::superclass",  ClassSuper_Get,  ClassSuper_Set, ResolveClass),
    SLOT("define::variable",    ClassVars_Get,   ClassVars_Set, NULL),
    SLOT("objdefine::filter",   ObjFilter_Get,   ObjFilter_Set, NULL),
    SLOT("objdefine::mixin",    ObjMixin_Get,    ObjMixin_Set, ResolveClass),
    SLOT("objdefine::variable", ObjVars_Get,     ObjVars_Set, NULL),
    SLOT("configuresupport::readableproperties",
	    Configurable_ClassReadableProps_Get,
	    Configurable_ClassReadableProps_Set, NULL),
    SLOT("configuresupport::writableproperties",
	    Configurable_ClassWritableProps_Get,
	    Configurable_ClassWritableProps_Set, NULL),
    SLOT("configuresupport::objreadableproperties",
	    Configurable_ObjectReadableProps_Get,
	    Configurable_ObjectReadableProps_Set, NULL),
    SLOT("configuresupport::objwritableproperties",
	    Configurable_ObjectWritableProps_Get,
	    Configurable_ObjectWritableProps_Set, NULL),
    {NULL, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}}














};

/*
 * How to build the in-namespace name of a private variable. This is a pattern
 * used with Tcl_ObjPrintf().
 */








|
|
|
|
|
|
|


|


|


|


|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>







187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
			    int objc, Tcl_Obj *const *objv);

/*
 * Now define the slots used in declarations.
 */

static const DeclaredSlot slots[] = {
    SLOT("define::filter",      ClassFilter_Get, ClassFilter_Set, NULL, NULL),
    SLOT("define::mixin",       ClassMixin_Get,  ClassMixin_Set, ResolveClass, "-set"),
    SLOT("define::superclass",  ClassSuper_Get,  ClassSuper_Set, ResolveClass, "-set"),
    SLOT("define::variable",    ClassVars_Get,   ClassVars_Set, NULL, NULL),
    SLOT("objdefine::filter",   ObjFilter_Get,   ObjFilter_Set, NULL, NULL),
    SLOT("objdefine::mixin",    ObjMixin_Get,    ObjMixin_Set, ResolveClass, "-set"),
    SLOT("objdefine::variable", ObjVars_Get,     ObjVars_Set, NULL, NULL),
    SLOT("configuresupport::readableproperties",
	    Configurable_ClassReadableProps_Get,
	    Configurable_ClassReadableProps_Set, NULL, NULL),
    SLOT("configuresupport::writableproperties",
	    Configurable_ClassWritableProps_Get,
	    Configurable_ClassWritableProps_Set, NULL, NULL),
    SLOT("configuresupport::objreadableproperties",
	    Configurable_ObjectReadableProps_Get,
	    Configurable_ObjectReadableProps_Set, NULL, NULL),
    SLOT("configuresupport::objwritableproperties",
	    Configurable_ObjectWritableProps_Get,
	    Configurable_ObjectWritableProps_Set, NULL, NULL),
    {NULL, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, {0, 0, 0, 0, 0}, 0}
};

static const DeclaredSlotMethod slotMethods[] = {
    SLOT_METHOD("Get",		Slot_Unimplemented, 0),
    SLOT_METHOD("Resolve",	Slot_Resolve,	0),
    SLOT_METHOD("Set",		Slot_Unimplemented, 0),
    SLOT_METHOD("-append",	Slot_Append,	PUBLIC_METHOD),
    SLOT_METHOD("-appendifnew",	Slot_AppendNew,	PUBLIC_METHOD),
    SLOT_METHOD("-clear",	Slot_Clear,	PUBLIC_METHOD),
    SLOT_METHOD("-prepend",	Slot_Prepend,	PUBLIC_METHOD),
    SLOT_METHOD("-remove",	Slot_Remove,	PUBLIC_METHOD),
    SLOT_METHOD("-set",		Slot_Set,	PUBLIC_METHOD),
    SLOT_METHOD("unknown",	Slot_Unknown,	0),
    {NULL, 0, {0, 0, 0, 0, 0}}
};

/*
 * How to build the in-namespace name of a private variable. This is a pattern
 * used with Tcl_ObjPrintf().
 */

1175
1176
1177
1178
1179
1180
1181

















































































































1182
1183
1184
1185
1186
1187
1188

    return result;
}

/*
 * ----------------------------------------------------------------------
 *

















































































































 * TclOODefineObjCmd --
 *
 *	Implementation of the "oo::define" command. Works by effectively doing
 *	the same as 'namespace eval', but with extra magic applied so that the
 *	object to be modified is known to the commands in the target
 *	namespace. Also does ensemble-like tricks with dispatch so that error
 *	messages are clearer.







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







1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353

    return result;
}

/*
 * ----------------------------------------------------------------------
 *
 * ExportMethod, UnexportMethod, ExportInstanceMethod, UnexportInstanceMethod --
 *
 *	Exporting and unexporting are done by setting or removing the
 *	PUBLIC_METHOD flag on the method record. If there is no such method in
 *	this class or object (i.e. the method comes from something inherited
 *	from or that we're an instance of) then we put in a blank record just
 *	to hold that flag (or its absence); such records are skipped over by
 *	the call chain engine *except* for their flags member.
 *
 *	Caller has the responsibility to update any epochs if necessary.
 *
 * ----------------------------------------------------------------------
 */

// Make a blank method record or look up the existing one.
static inline Method *
GetOrCreateMethod(
    Tcl_HashTable *tablePtr,
    Tcl_Obj *namePtr,
    int *isNew)
{
    Tcl_HashEntry *hPtr = Tcl_CreateHashEntry(tablePtr, namePtr,
		    isNew);
    if (*isNew) {
	Method *mPtr = (Method *) Tcl_Alloc(sizeof(Method));
	memset(mPtr, 0, sizeof(Method));
	mPtr->refCount = 1;
	mPtr->namePtr = namePtr;
	Tcl_IncrRefCount(namePtr);
	Tcl_SetHashValue(hPtr, mPtr);
	return mPtr;
    } else {
	return (Method *) Tcl_GetHashValue(hPtr);
    }
}

static int
ExportMethod(
    Class *clsPtr,
    Tcl_Obj *namePtr)
{
    int isNew;
    Method *mPtr = GetOrCreateMethod(&clsPtr->classMethods, namePtr, &isNew);
    if (isNew || !(mPtr->flags & (PUBLIC_METHOD | PRIVATE_METHOD))) {
	mPtr->flags |= PUBLIC_METHOD;
	mPtr->flags &= ~TRUE_PRIVATE_METHOD;
	isNew = 1;
    }
    return isNew;
}

static int
UnexportMethod(
    Class *clsPtr,
    Tcl_Obj *namePtr)
{
    int isNew;
    Method *mPtr = GetOrCreateMethod(&clsPtr->classMethods, namePtr, &isNew);
    if (isNew || mPtr->flags & (PUBLIC_METHOD | TRUE_PRIVATE_METHOD)) {
	mPtr->flags &= ~(PUBLIC_METHOD | TRUE_PRIVATE_METHOD);
	isNew = 1;
    }
    return isNew;
}

// Make the table of methods in the instance if it doesn't already exist.
static inline void
InitMethodTable(
    Object *oPtr)
{
    if (!oPtr->methodsPtr) {
	oPtr->methodsPtr = (Tcl_HashTable *) Tcl_Alloc(sizeof(Tcl_HashTable));
	Tcl_InitObjHashTable(oPtr->methodsPtr);
	oPtr->flags &= ~USE_CLASS_CACHE;
    }
}

static int
ExportInstanceMethod(
    Object *oPtr,
    Tcl_Obj *namePtr)
{
    InitMethodTable(oPtr);

    int isNew;
    Method *mPtr = GetOrCreateMethod(oPtr->methodsPtr, namePtr, &isNew);
    if (isNew || !(mPtr->flags & (PUBLIC_METHOD | PRIVATE_METHOD))) {
	mPtr->flags |= PUBLIC_METHOD;
	mPtr->flags &= ~TRUE_PRIVATE_METHOD;
	isNew = 1;
    }
    return isNew;
}

static int
UnexportInstanceMethod(
    Object *oPtr,
    Tcl_Obj *namePtr)
{
    InitMethodTable(oPtr);

    int isNew;
    Method *mPtr = GetOrCreateMethod(oPtr->methodsPtr, namePtr, &isNew);
    if (isNew || mPtr->flags & (PUBLIC_METHOD | TRUE_PRIVATE_METHOD)) {
	mPtr->flags &= ~(PUBLIC_METHOD | TRUE_PRIVATE_METHOD);
	isNew = 1;
    }
    return isNew;
}

/*
 * ----------------------------------------------------------------------
 *
 * TclOODefineObjCmd --
 *
 *	Implementation of the "oo::define" command. Works by effectively doing
 *	the same as 'namespace eval', but with extra magic applied so that the
 *	object to be modified is known to the commands in the target
 *	namespace. Also does ensemble-like tricks with dispatch so that error
 *	messages are clearer.
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
TclOODefineExportObjCmd(
    void *clientData,
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    int isInstanceExport = (clientData != NULL);
    Object *oPtr;
    Method *mPtr;
    Tcl_HashEntry *hPtr;
    Class *clsPtr;
    int i, isNew, changed = 0;

    if (objc < 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "name ?name ...?");
	return TCL_ERROR;
    }

    oPtr = (Object *) TclOOGetDefineCmdContext(interp);
    if (oPtr == NULL) {
	return TCL_ERROR;
    }
    clsPtr = oPtr->classPtr;
    if (!isInstanceExport && !clsPtr) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"attempt to misuse API", TCL_AUTO_LENGTH));
	OO_ERROR(interp, MONKEY_BUSINESS);
	return TCL_ERROR;
    }

    for (i = 1; i < objc; i++) {
	/*
	 * Exporting is done by adding the PUBLIC_METHOD flag to the method
	 * record. If there is no such method in this object or class (i.e.
	 * the method comes from something inherited from or that we're an
	 * instance of) then we put in a blank record with that flag; such
	 * records are skipped over by the call chain engine *except* for
	 * their flags member.
	 */

	if (isInstanceExport) {
	    if (!oPtr->methodsPtr) {
		oPtr->methodsPtr = (Tcl_HashTable *)
			Tcl_Alloc(sizeof(Tcl_HashTable));
		Tcl_InitObjHashTable(oPtr->methodsPtr);
		oPtr->flags &= ~USE_CLASS_CACHE;
	    }
	    hPtr = Tcl_CreateHashEntry(oPtr->methodsPtr, objv[i],
		    &isNew);
	} else {
	    hPtr = Tcl_CreateHashEntry(&clsPtr->classMethods, objv[i],
		    &isNew);
	}

	if (isNew) {
	    mPtr = (Method *) Tcl_Alloc(sizeof(Method));
	    memset(mPtr, 0, sizeof(Method));
	    mPtr->refCount = 1;
	    mPtr->namePtr = objv[i];
	    Tcl_IncrRefCount(objv[i]);
	    Tcl_SetHashValue(hPtr, mPtr);
	} else {
	    mPtr = (Method *) Tcl_GetHashValue(hPtr);
	}
	if (isNew || !(mPtr->flags & (PUBLIC_METHOD | PRIVATE_METHOD))) {
	    mPtr->flags |= PUBLIC_METHOD;
	    mPtr->flags &= ~TRUE_PRIVATE_METHOD;
	    changed = 1;
	}
    }

    /*
     * Bump the right epoch if we actually changed anything.
     */








<
<
<
<
|






|



|


















<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<

<
<
<
<
<
|







2048
2049
2050
2051
2052
2053
2054




2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084












2085







2086





2087
2088
2089
2090
2091
2092
2093
2094
TclOODefineExportObjCmd(
    void *clientData,
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    int isInstanceExport = (clientData != NULL);




    int i, changed = 0;

    if (objc < 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "name ?name ...?");
	return TCL_ERROR;
    }

    Object *oPtr = (Object *) TclOOGetDefineCmdContext(interp);
    if (oPtr == NULL) {
	return TCL_ERROR;
    }
    Class *clsPtr = oPtr->classPtr;
    if (!isInstanceExport && !clsPtr) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"attempt to misuse API", TCL_AUTO_LENGTH));
	OO_ERROR(interp, MONKEY_BUSINESS);
	return TCL_ERROR;
    }

    for (i = 1; i < objc; i++) {
	/*
	 * Exporting is done by adding the PUBLIC_METHOD flag to the method
	 * record. If there is no such method in this object or class (i.e.
	 * the method comes from something inherited from or that we're an
	 * instance of) then we put in a blank record with that flag; such
	 * records are skipped over by the call chain engine *except* for
	 * their flags member.
	 */

	if (isInstanceExport) {












	    changed |= ExportInstanceMethod(oPtr, objv[i]);







	} else {





	    changed |= ExportMethod(clsPtr, objv[i]);
	}
    }

    /*
     * Bump the right epoch if we actually changed anything.
     */

2024
2025
2026
2027
2028
2029
2030















































2031
2032
2033
2034
2035
2036
2037
    }
    if (mPtr == NULL) {
	Tcl_DecrRefCount(prefixObj);
	return TCL_ERROR;
    }
    return TCL_OK;
}
















































/*
 * ----------------------------------------------------------------------
 *
 * TclOODefineMethodObjCmd --
 *
 *	Implementation of the "method" subcommand of the "oo::define" and







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







2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
    }
    if (mPtr == NULL) {
	Tcl_DecrRefCount(prefixObj);
	return TCL_ERROR;
    }
    return TCL_OK;
}

/*
 * ----------------------------------------------------------------------
 *
 * TclOODefineInitialiseObjCmd --
 *
 *	Implementation of the "initialise" subcommand of the "oo::define"
 *	command.
 *
 * ----------------------------------------------------------------------
 */

int
TclOODefineInitialiseObjCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    if (objc != 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "body");
	return TCL_ERROR;
    }

    // Build the lambda
    Tcl_Object object = TclOOGetDefineCmdContext(interp);
    if (object == NULL) {
	return TCL_ERROR;
    }
    Tcl_Obj *lambdaWords[] = {
	Tcl_NewObj(),
	objv[1],
	TclNewNamespaceObj(Tcl_GetObjectNamespace(object))
    };

    // Delegate to [apply] to run it
    Tcl_Obj *applyArgs[] = {
	Tcl_NewStringObj("apply", -1),
	Tcl_NewListObj(3, lambdaWords)
    };
    Tcl_IncrRefCount(applyArgs[0]);
    Tcl_IncrRefCount(applyArgs[1]);
    int result = Tcl_ApplyObjCmd(NULL, interp, 2, applyArgs);
    Tcl_DecrRefCount(applyArgs[0]);
    Tcl_DecrRefCount(applyArgs[1]);
    return result;
}

/*
 * ----------------------------------------------------------------------
 *
 * TclOODefineMethodObjCmd --
 *
 *	Implementation of the "method" subcommand of the "oo::define" and
2126
2127
2128
2129
2130
2131
2132


































































2133
2134
2135
2136
2137
2138
2139
    }
    return TCL_OK;
}

/*
 * ----------------------------------------------------------------------
 *


































































 * TclOODefineRenameMethodObjCmd --
 *
 *	Implementation of the "renamemethod" subcommand of the "oo::define"
 *	and "oo::objdefine" commands.
 *
 * ----------------------------------------------------------------------
 */







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







2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
2328
2329
2330
2331
2332
2333
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
    }
    return TCL_OK;
}

/*
 * ----------------------------------------------------------------------
 *
 * TclOODefineClassMethodObjCmd --
 *
 *	Implementation of the "classmethod" subcommand of the "oo::define"
 *	command. Defines a class method. See define(n) for details.
 *
 * ----------------------------------------------------------------------
 */

int
TclOODefineClassMethodObjCmd(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    if (objc != 2 && objc != 4) {
	Tcl_WrongNumArgs(interp, 1, objv, "name ?args body?");
	return TCL_ERROR;
    }
    Class *clsPtr = TclOOGetClassDefineCmdContext(interp);
    if (!clsPtr) {
	return TCL_ERROR;
    }

    int isPublic = Tcl_StringMatch(TclGetString(objv[1]), PUBLIC_PATTERN)
	    ? PUBLIC_METHOD : 0;

    // Create the method on the delegate class if the caller gave arguments and body
    if (objc == 4) {
	Tcl_Obj *delegateName = Tcl_ObjPrintf("%s:: oo ::delegate",
		clsPtr->thisPtr->namespacePtr->fullName);
	Class *delegatePtr = TclOOGetClassFromObj(interp, delegateName);
	Tcl_DecrRefCount(delegateName);
	if (!delegatePtr) {
	    return TCL_ERROR;
	}
	if (IsPrivateDefine(interp)) {
	    isPublic = 0;
	}
	if (TclOONewProcMethod(interp, delegatePtr, isPublic, objv[1],
		objv[2], objv[3], NULL) == NULL) {
	    return TCL_ERROR;
	}
    }

    // Make the connection to the delegate by forwarding
    if (IsPrivateDefine(interp)) {
	isPublic = TRUE_PRIVATE_METHOD;
    }
    Tcl_Obj *forwardArgs[] = {
	Tcl_NewStringObj("myclass", -1),
	objv[1]
    };
    Tcl_Obj *prefixObj = Tcl_NewListObj(2, forwardArgs);
    Method *mPtr = TclOONewForwardMethod(interp, clsPtr, isPublic,
	    objv[1], prefixObj);
    if (mPtr == NULL) {
	Tcl_DecrRefCount(prefixObj);
	return TCL_ERROR;
    }
    return TCL_OK;
}

/*
 * ----------------------------------------------------------------------
 *
 * TclOODefineRenameMethodObjCmd --
 *
 *	Implementation of the "renamemethod" subcommand of the "oo::define"
 *	and "oo::objdefine" commands.
 *
 * ----------------------------------------------------------------------
 */
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
    void *clientData,
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    int isInstanceUnexport = (clientData != NULL);
    Object *oPtr;
    Method *mPtr;
    Tcl_HashEntry *hPtr;
    Class *clsPtr;
    int i, isNew, changed = 0;

    if (objc < 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "name ?name ...?");
	return TCL_ERROR;
    }

    oPtr = (Object *) TclOOGetDefineCmdContext(interp);
    if (oPtr == NULL) {
	return TCL_ERROR;
    }
    clsPtr = oPtr->classPtr;
    if (!isInstanceUnexport && !clsPtr) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"attempt to misuse API", TCL_AUTO_LENGTH));
	OO_ERROR(interp, MONKEY_BUSINESS);
	return TCL_ERROR;
    }

    for (i = 1; i < objc; i++) {
	/*
	 * Unexporting is done by removing the PUBLIC_METHOD flag from the
	 * method record. If there is no such method in this object or class
	 * (i.e. the method comes from something inherited from or that we're
	 * an instance of) then we put in a blank record without that flag;
	 * such records are skipped over by the call chain engine *except* for
	 * their flags member.
	 */

	if (isInstanceUnexport) {
	    if (!oPtr->methodsPtr) {
		oPtr->methodsPtr = (Tcl_HashTable *)
			Tcl_Alloc(sizeof(Tcl_HashTable));
		Tcl_InitObjHashTable(oPtr->methodsPtr);
		oPtr->flags &= ~USE_CLASS_CACHE;
	    }
	    hPtr = Tcl_CreateHashEntry(oPtr->methodsPtr, objv[i],
		    &isNew);
	} else {
	    hPtr = Tcl_CreateHashEntry(&clsPtr->classMethods, objv[i],
		    &isNew);
	}

	if (isNew) {
	    mPtr = (Method *) Tcl_Alloc(sizeof(Method));
	    memset(mPtr, 0, sizeof(Method));
	    mPtr->refCount = 1;
	    mPtr->namePtr = objv[i];
	    Tcl_IncrRefCount(objv[i]);
	    Tcl_SetHashValue(hPtr, mPtr);
	} else {
	    mPtr = (Method *) Tcl_GetHashValue(hPtr);
	}
	if (isNew || mPtr->flags & (PUBLIC_METHOD | TRUE_PRIVATE_METHOD)) {
	    mPtr->flags &= ~(PUBLIC_METHOD | TRUE_PRIVATE_METHOD);
	    changed = 1;
	}
    }

    /*
     * Bump the right epoch if we actually changed anything.
     */








<
<

|



















<
<
<
<
<
<
<
<
<

<
<
<
<
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<

<
<
<
<
|







2450
2451
2452
2453
2454
2455
2456


2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477









2478












2479







2480




2481
2482
2483
2484
2485
2486
2487
2488
    void *clientData,
    Tcl_Interp *interp,
    int objc,
    Tcl_Obj *const *objv)
{
    int isInstanceUnexport = (clientData != NULL);
    Object *oPtr;


    Class *clsPtr;
    int i, changed = 0;

    if (objc < 2) {
	Tcl_WrongNumArgs(interp, 1, objv, "name ?name ...?");
	return TCL_ERROR;
    }

    oPtr = (Object *) TclOOGetDefineCmdContext(interp);
    if (oPtr == NULL) {
	return TCL_ERROR;
    }
    clsPtr = oPtr->classPtr;
    if (!isInstanceUnexport && !clsPtr) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj(
		"attempt to misuse API", TCL_AUTO_LENGTH));
	OO_ERROR(interp, MONKEY_BUSINESS);
	return TCL_ERROR;
    }

    for (i = 1; i < objc; i++) {









	if (isInstanceUnexport) {












	    changed |= UnexportInstanceMethod(oPtr, objv[i]);







	} else {




	    changed |= UnexportMethod(clsPtr, objv[i]);
	}
    }

    /*
     * Bump the right epoch if we actually changed anything.
     */

2336
2337
2338
2339
2340
2341
2342
2343
2344

2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367






2368








2369



2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382











































































































































































































































2383





2384





























2385











































































































































































2386
2387
2388



2389


2390




















2391








































2392
2393
2394
2395
2396
2397
2398
}

/*
 * ----------------------------------------------------------------------
 *
 * TclOODefineSlots --
 *
 *	Create the "::oo::Slot" class and its standard instances. Class
 *	definition is empty at the stage (added by scripting).

 *
 * ----------------------------------------------------------------------
 */

int
TclOODefineSlots(
    Foundation *fPtr)
{
    const DeclaredSlot *slotInfoPtr;
    Tcl_Interp *interp = fPtr->interp;
    Tcl_Obj *getName, *setName, *resolveName;
    Tcl_Object object = Tcl_NewObjectInstance(interp, (Tcl_Class)
	    fPtr->classCls, "::oo::Slot", NULL, TCL_INDEX_NONE, NULL, 0);
    Class *slotCls;

    if (object == NULL) {
	return TCL_ERROR;
    }
    slotCls = ((Object *) object)->classPtr;
    if (slotCls == NULL) {
	return TCL_ERROR;
    }







    TclNewLiteralStringObj(getName, "Get");








    TclNewLiteralStringObj(setName, "Set");



    TclNewLiteralStringObj(resolveName, "Resolve");
    for (slotInfoPtr = slots ; slotInfoPtr->name ; slotInfoPtr++) {
	Tcl_Object slotObject = Tcl_NewObjectInstance(interp,
		(Tcl_Class) slotCls, slotInfoPtr->name, NULL, TCL_INDEX_NONE,
		NULL, 0);

	if (slotObject == NULL) {
	    continue;
	}
	TclNewInstanceMethod(interp, slotObject, getName, 0,
		&slotInfoPtr->getterType, NULL);
	TclNewInstanceMethod(interp, slotObject, setName, 0,
		&slotInfoPtr->setterType, NULL);











































































































































































































































	if (slotInfoPtr->resolverType.callProc) {





	    TclNewInstanceMethod(interp, slotObject, resolveName, 0,





























		    &slotInfoPtr->resolverType, NULL);











































































































































































	}
    }
    Tcl_BounceRefCount(getName);



    Tcl_BounceRefCount(setName);


    Tcl_BounceRefCount(resolveName);




















    return TCL_OK;








































}

/*
 * ----------------------------------------------------------------------
 *
 * ClassFilter_Get, ClassFilter_Set --
 *







|
|
>








<

<


<




|




>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
|
>
>
>
|
|

|
<




|
|
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>


|
>
>
>
|
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569

2570

2571
2572

2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604

2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
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
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
3011
3012
3013
3014
3015
3016
3017
3018
3019
3020
3021
3022
3023
3024
3025
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069
3070
3071
3072
3073
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
}

/*
 * ----------------------------------------------------------------------
 *
 * TclOODefineSlots --
 *
 *	Create the "::oo::Slot" class and its standard instances. These are
 *	basically lists at the low level of TclOO; this provides a more
 *	consistent interface to them.
 *
 * ----------------------------------------------------------------------
 */

int
TclOODefineSlots(
    Foundation *fPtr)
{

    Tcl_Interp *interp = fPtr->interp;

    Tcl_Object object = Tcl_NewObjectInstance(interp, (Tcl_Class)
	    fPtr->classCls, "::oo::Slot", NULL, TCL_INDEX_NONE, NULL, 0);


    if (object == NULL) {
	return TCL_ERROR;
    }
    Tcl_Class slotCls = (Tcl_Class) ((Object *) object)->classPtr;
    if (slotCls == NULL) {
	return TCL_ERROR;
    }

    for (const DeclaredSlotMethod *smPtr = slotMethods; smPtr->name; smPtr++) {
	Tcl_Obj *name = Tcl_NewStringObj(smPtr->name, -1);
	Tcl_NewMethod(interp, slotCls, name, smPtr->flags,
		&smPtr->implType, NULL);
	Tcl_BounceRefCount(name);
    }

    // If a slot can't figure out what method to call directly, it uses
    // --default-operation. That defaults to -append; we set that here.
    Tcl_Obj *defaults[] = {
	fPtr->myName,
	Tcl_NewStringObj("-append", TCL_AUTO_LENGTH)
    };
    TclOONewForwardMethod(interp, (Class *) slotCls, 0,
	    fPtr->slotDefOpName, Tcl_NewListObj(2, defaults));

    // Hide the destroy method. (We're definitely taking a ref to the name.)
    UnexportMethod((Class *) slotCls,
	    Tcl_NewStringObj("destroy", TCL_AUTO_LENGTH));

    for (const DeclaredSlot *slotPtr = slots ; slotPtr->name ; slotPtr++) {
	Tcl_Object slotObject = Tcl_NewObjectInstance(interp,
		slotCls, slotPtr->name, NULL, TCL_INDEX_NONE, NULL, 0);


	if (slotObject == NULL) {
	    continue;
	}
	TclNewInstanceMethod(interp, slotObject, fPtr->slotGetName, 0,
		&slotPtr->getterType, NULL);
	TclNewInstanceMethod(interp, slotObject, fPtr->slotSetName, 0,
		&slotPtr->setterType, NULL);
	if (slotPtr->resolverType.callProc) {
	    TclNewInstanceMethod(interp, slotObject, fPtr->slotResolveName, 0,
		    &slotPtr->resolverType, NULL);
	}
	if (slotPtr->defaultOp) {
	    Tcl_Obj *slotDefaults[] = {
		fPtr->myName,
		Tcl_NewStringObj(slotPtr->defaultOp, TCL_AUTO_LENGTH)
	    };
	    TclOONewForwardInstanceMethod(interp, (Object *) slotObject, 0,
		    fPtr->slotDefOpName, Tcl_NewListObj(2, slotDefaults));
	}
    }
    return TCL_OK;
}

/*
 * ----------------------------------------------------------------------
 *
 * CallSlotGet, CallSlotSet, CallSlotResolve, ResolveAll --
 *
 *	How to call the standard low-level methods of a slot.
 *	ResolveAll is the lifting of CallSlotResolve to work over a whole
 *	list of items.
 *
 * ----------------------------------------------------------------------
 */

// Call [$slot Get] to retrieve the list of contents of the slot
static inline Tcl_Obj *
CallSlotGet(
    Tcl_Interp *interp,
    Object *slot)
{
    Tcl_Obj *getArgs[] = {
	slot->fPtr->myName,
	slot->fPtr->slotGetName
    };
    int code = TclOOPrivateObjectCmd(slot, interp, 2, getArgs);
    if (code != TCL_OK) {
	return NULL;
    }
    return Tcl_GetObjResult(interp);
}

// Call [$slot Set $list] to set the list of contents of the slot
static inline int
CallSlotSet(
    Tcl_Interp *interp,
    Object *slot,
    Tcl_Obj *list)
{
    Tcl_Obj *setArgs[] = {
	slot->fPtr->myName,
	slot->fPtr->slotSetName,
	list
    };
    return TclOOPrivateObjectCmd(slot, interp, 3, setArgs);
}

// Call [$slot Resolve $item] to convert a slot item into canonical form
static inline Tcl_Obj *
CallSlotResolve(
    Tcl_Interp *interp,
    Object *slot,
    Tcl_Obj *item)
{
    Tcl_Obj *resolveArgs[] = {
	slot->fPtr->myName,
	slot->fPtr->slotResolveName,
	item
    };
    int code = TclOOPrivateObjectCmd(slot, interp, 3, resolveArgs);
    if (code != TCL_OK) {
	return NULL;
    }
    return Tcl_GetObjResult(interp);
}

static inline Tcl_Obj *
ResolveAll(
    Tcl_Interp *interp,
    Object *slot,
    int objc,
    Tcl_Obj *const *objv)
{
    Tcl_Obj **resolvedItems = (Tcl_Obj **) TclStackAlloc(interp,
	    sizeof(Tcl_Obj *) * objc);
    for (int i = 0; i < objc; i++) {
	resolvedItems[i] = CallSlotResolve(interp, slot, objv[i]);
	if (resolvedItems[i] == NULL) {
	    for (int j = 0; j < i; j++) {
		Tcl_DecrRefCount(resolvedItems[j]);
	    }
	    TclStackFree(interp, (void *) resolvedItems);
	    return NULL;
	}
	Tcl_IncrRefCount(resolvedItems[i]);
	Tcl_ResetResult(interp);
    }
    Tcl_Obj *resolvedList = Tcl_NewListObj(objc, resolvedItems);
    for (int i = 0; i < objc; i++) {
	TclDecrRefCount(resolvedItems[i]);
    }
    TclStackFree(interp, (void *) resolvedItems);
    return resolvedList;
}

/*
 * ----------------------------------------------------------------------
 *
 * Slot_Append --
 *
 *	Implementation of the "-append" slot operation.
 *
 * ----------------------------------------------------------------------
 */
static int
Slot_Append(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    Tcl_ObjectContext context,
    int objc,
    Tcl_Obj *const *objv)
{
    Object *oPtr = (Object *) Tcl_ObjectContextObject(context);
    int skip = Tcl_ObjectContextSkippedArgs(context);
    if (skip == objc) {
	return TCL_OK;
    }

    // Resolve all values
    Tcl_Obj *resolved = ResolveAll(interp, oPtr, objc - skip, objv + skip);
    if (resolved == NULL) {
	return TCL_ERROR;
    }

    // Get slot contents; store in list
    Tcl_Obj *list = CallSlotGet(interp, oPtr);
    if (list == NULL) {
	Tcl_DecrRefCount(resolved);
	return TCL_ERROR;
    }
    Tcl_IncrRefCount(list);
    Tcl_ResetResult(interp);

    // Append
    if (Tcl_IsShared(list)) {
	Tcl_Obj *dup = Tcl_DuplicateObj(list);
	Tcl_IncrRefCount(dup);
	Tcl_DecrRefCount(list);
	list = dup;
    }
    if (Tcl_ListObjAppendList(interp, list, resolved) != TCL_OK) {
	Tcl_DecrRefCount(list);
	Tcl_DecrRefCount(resolved);
	return TCL_ERROR;
    }
    Tcl_DecrRefCount(resolved);

    // Set slot contents
    int code = CallSlotSet(interp, oPtr, list);
    Tcl_DecrRefCount(list);
    return code;
}

/*
 * ----------------------------------------------------------------------
 *
 * Slot_AppendNew --
 *
 *	Implementation of the "-appendifnew" slot operation.
 *
 * ----------------------------------------------------------------------
 */
static int
Slot_AppendNew(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    Tcl_ObjectContext context,
    int objc,
    Tcl_Obj *const *objv)
{
    Object *oPtr = (Object *) Tcl_ObjectContextObject(context);
    int skip = Tcl_ObjectContextSkippedArgs(context);
    if (skip == objc) {
	return TCL_OK;
    }

    // Resolve all values
    Tcl_Obj *resolved = ResolveAll(interp, oPtr, objc - skip, objv + skip);
    if (resolved == NULL) {
	return TCL_ERROR;
    }

    // Get slot contents; store in list
    Tcl_Obj *list = CallSlotGet(interp, oPtr);
    if (list == NULL) {
	Tcl_DecrRefCount(resolved);
	return TCL_ERROR;
    }
    Tcl_IncrRefCount(list);
    Tcl_ResetResult(interp);

    // Prepare a set of items in the list to set
    Tcl_Size listc;
    Tcl_Obj **listv;
    if (TclListObjGetElements(interp, list, &listc, &listv) != TCL_OK) {
	Tcl_DecrRefCount(list);
	Tcl_DecrRefCount(resolved);
	return TCL_ERROR;
    }
    Tcl_HashTable unique;
    Tcl_InitObjHashTable(&unique);
    for (Tcl_Size i=0 ; i<listc; i++) {
	Tcl_CreateHashEntry(&unique, listv[i], NULL);
    }

    // Append the new items if they're not already there
    if (Tcl_IsShared(list)) {
	Tcl_Obj *dup = Tcl_DuplicateObj(list);
	Tcl_IncrRefCount(dup);
	Tcl_DecrRefCount(list);
	list = dup;
    }
    TclListObjGetElements(NULL, resolved, &listc, &listv);
    for (Tcl_Size i=0 ; i<listc; i++) {
	int isNew;
	Tcl_CreateHashEntry(&unique, listv[i], &isNew);
	if (isNew) {
	    Tcl_ListObjAppendElement(interp, list, listv[i]);
	}
    }
    Tcl_DecrRefCount(resolved);
    Tcl_DeleteHashTable(&unique);

    // Set slot contents
    int code = CallSlotSet(interp, oPtr, list);
    Tcl_DecrRefCount(list);
    return code;
}

/*
 * ----------------------------------------------------------------------
 *
 * Slot_Clear --
 *
 *	Implementation of the "-clear" slot operation.
 *
 * ----------------------------------------------------------------------
 */
static int
Slot_Clear(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    Tcl_ObjectContext context,
    int objc,
    Tcl_Obj *const *objv)
{
    Object *oPtr = (Object *) Tcl_ObjectContextObject(context);
    int skip = Tcl_ObjectContextSkippedArgs(context);
    if (skip != objc) {
	Tcl_WrongNumArgs(interp, skip, objv, NULL);
	return TCL_ERROR;
    }
    Tcl_Obj *list = Tcl_NewObj();
    Tcl_IncrRefCount(list);
    int code = CallSlotSet(interp, oPtr, list);
    Tcl_DecrRefCount(list);
    return code;
}

/*
 * ----------------------------------------------------------------------
 *
 * Slot_Prepend --
 *
 *	Implementation of the "-prepend" slot operation.
 *
 * ----------------------------------------------------------------------
 */
static int
Slot_Prepend(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    Tcl_ObjectContext context,
    int objc,
    Tcl_Obj *const *objv)
{
    Object *oPtr = (Object *) Tcl_ObjectContextObject(context);
    int skip = Tcl_ObjectContextSkippedArgs(context);
    if (skip == objc) {
	return TCL_OK;
    }

    // Resolve all values
    Tcl_Obj *list = ResolveAll(interp, oPtr, objc - skip, objv + skip);
    if (list == NULL) {
	return TCL_ERROR;
    }
    Tcl_IncrRefCount(list);

    // Get slot contents and append to list
    Tcl_Obj *oldList = CallSlotGet(interp, oPtr);
    if (oldList == NULL) {
	Tcl_DecrRefCount(list);
	return TCL_ERROR;
    }
    Tcl_ListObjAppendList(NULL, list, oldList);
    Tcl_ResetResult(interp);

    // Set slot contents
    int code = CallSlotSet(interp, oPtr, list);
    Tcl_DecrRefCount(list);
    return code;
}

/*
 * ----------------------------------------------------------------------
 *
 * Slot_Remove --
 *
 *	Implementation of the "-remove" slot operation.
 *
 * ----------------------------------------------------------------------
 */
static int
Slot_Remove(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    Tcl_ObjectContext context,
    int objc,
    Tcl_Obj *const *objv)
{
    Object *oPtr = (Object *) Tcl_ObjectContextObject(context);
    int skip = Tcl_ObjectContextSkippedArgs(context);
    if (skip == objc) {
	return TCL_OK;
    }

    // Resolve all values
    Tcl_Obj *resolved = ResolveAll(interp, oPtr, objc - skip, objv + skip);
    if (resolved == NULL) {
	return TCL_ERROR;
    }

    // Get slot contents; store in list
    Tcl_Obj *oldList = CallSlotGet(interp, oPtr);
    if (oldList == NULL) {
	Tcl_DecrRefCount(resolved);
	return TCL_ERROR;
    }
    Tcl_IncrRefCount(oldList);
    Tcl_ResetResult(interp);

    // Prepare a set of items in the list to remove
    Tcl_Size listc;
    Tcl_Obj **listv;
    TclListObjGetElements(NULL, resolved, &listc, &listv);
    Tcl_HashTable removeSet;
    Tcl_InitObjHashTable(&removeSet);
    for (Tcl_Size i=0 ; i<listc; i++) {
	Tcl_CreateHashEntry(&removeSet, listv[i], NULL);
    }
    Tcl_DecrRefCount(resolved);

    // Append the new items from the old items if they're not in the remove set
    if (TclListObjGetElements(interp, oldList, &listc, &listv) != TCL_OK) {
	Tcl_DecrRefCount(oldList);
	Tcl_DeleteHashTable(&removeSet);
	return TCL_ERROR;
    }
    Tcl_Obj *newList = Tcl_NewObj();
    for (Tcl_Size i=0 ; i<listc; i++) {
	if (Tcl_FindHashEntry(&removeSet, listv[i]) == NULL) {
	    Tcl_ListObjAppendElement(NULL, newList, listv[i]);
	}
    }
    Tcl_DecrRefCount(oldList);
    Tcl_DeleteHashTable(&removeSet);

    // Set slot contents
    Tcl_IncrRefCount(newList);
    int code = CallSlotSet(interp, oPtr, newList);
    Tcl_DecrRefCount(newList);
    return code;
}

/*
 * ----------------------------------------------------------------------
 *
 * Slot_Resolve --
 *
 *	Default implementation of the "Resolve" slot accessor. Just returns
 *	its argument unchanged; particular slots may override.
 *
 * ----------------------------------------------------------------------
 */
static int
Slot_Resolve(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    Tcl_ObjectContext context,
    int objc,
    Tcl_Obj *const *objv)
{
    int skip = Tcl_ObjectContextSkippedArgs(context);
    if (skip + 1 != objc) {
	Tcl_WrongNumArgs(interp, skip, objv, "list");
	return TCL_ERROR;
    }
    Tcl_SetObjResult(interp, objv[objc - 1]);
    return TCL_OK;
}

/*
 * ----------------------------------------------------------------------
 *
 * Slot_Set --
 *
 *	Implementation of the "-set" slot operation.
 *
 * ----------------------------------------------------------------------
 */
static int
Slot_Set(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    Tcl_ObjectContext context,
    int objc,
    Tcl_Obj *const *objv)
{
    Object *oPtr = (Object *) Tcl_ObjectContextObject(context);
    int skip = Tcl_ObjectContextSkippedArgs(context);
    Tcl_Obj *list;

    // Resolve all values
    if (skip == objc) {
	list = Tcl_NewObj();
    } else {
	list = ResolveAll(interp, oPtr, objc - skip, objv + skip);
	if (list == NULL) {
	    return TCL_ERROR;
	}
    }
    Tcl_IncrRefCount(list);

    // Set slot contents
    int code = CallSlotSet(interp, oPtr, list);
    Tcl_DecrRefCount(list);
    return code;
}

/*
 * ----------------------------------------------------------------------
 *
 * Slot_Unimplemented --
 *
 *	Default implementation of the "Get" and "Set" slot accessors. Just
 *	returns an error; actual slots must override.
 *
 * ----------------------------------------------------------------------
 */
static int
Slot_Unimplemented(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    TCL_UNUSED(Tcl_ObjectContext),
    TCL_UNUSED(int),
    TCL_UNUSED(Tcl_Obj *const *))
{
    Tcl_SetObjResult(interp, Tcl_NewStringObj("unimplemented", -1));
    OO_ERROR(interp, ABSTRACT_SLOT);
    return TCL_ERROR;
}

/*
 * ----------------------------------------------------------------------
 *
 * Slot_Unknown --
 *
 *	Unknown method name handler for slots. Delegates to the default slot
 *	operation (--default-operation forwarded method) unless the first
 *	argument starts with a dash.
 *
 * ----------------------------------------------------------------------
 */
static int
Slot_Unknown(
    TCL_UNUSED(void *),
    Tcl_Interp *interp,
    Tcl_ObjectContext context,
    int objc,
    Tcl_Obj *const *objv)
{
    Object *oPtr = (Object *) Tcl_ObjectContextObject(context);
    int skip = Tcl_ObjectContextSkippedArgs(context);
    if (skip >= objc) {
	Tcl_Obj *args[] = {
	    oPtr->fPtr->myName,
	    oPtr->fPtr->slotDefOpName
	};
	return TclOOPrivateObjectCmd(oPtr, interp, 2, args);
    } else if (TclGetString(objv[skip])[0] != '-') {
	Tcl_Obj **args = (Tcl_Obj **) TclStackAlloc(interp,
		sizeof(Tcl_Obj *) * (objc - skip + 2));
	args[0] = oPtr->fPtr->myName;
	args[1] = oPtr->fPtr->slotDefOpName;
	memcpy(args+2, objv+skip, sizeof(Tcl_Obj*) * (objc - skip));
	int code = TclOOPrivateObjectCmd(oPtr, interp, objc - skip + 2, args);
	TclStackFree(interp, args);
	return code;
    }
    return TclNRObjectContextInvokeNext(interp, context, objc, objv, skip);
}

/*
 * ----------------------------------------------------------------------
 *
 * ClassFilter_Get, ClassFilter_Set --
 *
Changes to generic/tclOOInt.h.
251
252
253
254
255
256
257

258
259
260
261
262
263
264
				/* Configurations for the variable resolver
				 * used inside methods. */
    Tcl_Command myclassCommand;	/* Reference to this object's class dispatcher
				 * command. */
    PropertyStorage properties;	/* Information relating to the lists of
				 * properties that this object *claims* to
				 * support. */

};

enum ObjectFlags {
    OBJECT_DESTRUCTING = 1,	/* Indicates that an object is being or has
				 * been destroyed. */
    DESTRUCTOR_CALLED = 2,	/* Indicates that evaluation of destructor
				 * script for the object has began */







>







251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
				/* Configurations for the variable resolver
				 * used inside methods. */
    Tcl_Command myclassCommand;	/* Reference to this object's class dispatcher
				 * command. */
    PropertyStorage properties;	/* Information relating to the lists of
				 * properties that this object *claims* to
				 * support. */
    Tcl_Obj *linkedCmdsList;	/* List of names of linked commands. */
};

enum ObjectFlags {
    OBJECT_DESTRUCTING = 1,	/* Indicates that an object is being or has
				 * been destroyed. */
    DESTRUCTOR_CALLED = 2,	/* Indicates that evaluation of destructor
				 * script for the object has began */
401
402
403
404
405
406
407
408
409


410
411
412
413
414
415
416
				 * constructor. */
    Tcl_Obj *destructorName;	/* Shared object containing the "name" of a
				 * destructor. */
    Tcl_Obj *clonedName;	/* Shared object containing the name of a
				 * "<cloned>" pseudo-constructor. */
    Tcl_Obj *defineName;	/* Fully qualified name of oo::define. */
    Tcl_Obj *myName;		/* The "my" shared object. */
    Tcl_Obj *mcdName;		/* The shared object for calling the helper to
				 * mix in class delegates. */


};

/*
 * The number of MInvoke records in the CallChain before we allocate
 * separately.
 */
#define CALL_CHAIN_STATIC_SIZE 4







|
|
>
>







402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
				 * constructor. */
    Tcl_Obj *destructorName;	/* Shared object containing the "name" of a
				 * destructor. */
    Tcl_Obj *clonedName;	/* Shared object containing the name of a
				 * "<cloned>" pseudo-constructor. */
    Tcl_Obj *defineName;	/* Fully qualified name of oo::define. */
    Tcl_Obj *myName;		/* The "my" shared object. */
    Tcl_Obj *slotGetName;	/* The "Get" name used by slots. */
    Tcl_Obj *slotSetName;	/* The "Set" name used by slots. */
    Tcl_Obj *slotResolveName;	/* The "Resolve" name used by slots. */
    Tcl_Obj *slotDefOpName;	/* The "--default-operation" name used by slots. */
};

/*
 * The number of MInvoke records in the CallChain before we allocate
 * separately.
 */
#define CALL_CHAIN_STATIC_SIZE 4
494
495
496
497
498
499
500

501
502
503
504
505
506

507
508
509
510
511
512
513
514
515


516


517
518
519
520
521
522
523
 * Commands relating to OO support.
 *----------------------------------------------------------------
 */

MODULE_SCOPE int		TclOOInit(Tcl_Interp *interp);
MODULE_SCOPE Tcl_ObjCmdProc	TclOODefineObjCmd;
MODULE_SCOPE Tcl_ObjCmdProc	TclOOObjDefObjCmd;

MODULE_SCOPE Tcl_ObjCmdProc	TclOODefineConstructorObjCmd;
MODULE_SCOPE Tcl_ObjCmdProc	TclOODefineDefnNsObjCmd;
MODULE_SCOPE Tcl_ObjCmdProc	TclOODefineDeleteMethodObjCmd;
MODULE_SCOPE Tcl_ObjCmdProc	TclOODefineDestructorObjCmd;
MODULE_SCOPE Tcl_ObjCmdProc	TclOODefineExportObjCmd;
MODULE_SCOPE Tcl_ObjCmdProc	TclOODefineForwardObjCmd;

MODULE_SCOPE Tcl_ObjCmdProc	TclOODefineMethodObjCmd;
MODULE_SCOPE Tcl_ObjCmdProc	TclOODefineRenameMethodObjCmd;
MODULE_SCOPE Tcl_ObjCmdProc	TclOODefineUnexportObjCmd;
MODULE_SCOPE Tcl_ObjCmdProc	TclOODefineClassObjCmd;
MODULE_SCOPE Tcl_ObjCmdProc	TclOODefineSelfObjCmd;
MODULE_SCOPE Tcl_ObjCmdProc	TclOODefineObjSelfObjCmd;
MODULE_SCOPE Tcl_ObjCmdProc	TclOODefinePrivateObjCmd;
MODULE_SCOPE Tcl_ObjCmdProc	TclOODefinePropertyCmd;
MODULE_SCOPE Tcl_ObjCmdProc	TclOOUnknownDefinition;


MODULE_SCOPE Tcl_ObjCmdProc	TclOOCopyObjectCmd;


MODULE_SCOPE Tcl_ObjCmdProc	TclOONextObjCmd;
MODULE_SCOPE Tcl_ObjCmdProc	TclOONextToObjCmd;
MODULE_SCOPE Tcl_ObjCmdProc	TclOOSelfObjCmd;
MODULE_SCOPE Tcl_ObjCmdProc	TclOOInfoObjectPropCmd;
MODULE_SCOPE Tcl_ObjCmdProc	TclOOInfoClassPropCmd;

/*







>






>









>
>

>
>







497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
 * Commands relating to OO support.
 *----------------------------------------------------------------
 */

MODULE_SCOPE int		TclOOInit(Tcl_Interp *interp);
MODULE_SCOPE Tcl_ObjCmdProc	TclOODefineObjCmd;
MODULE_SCOPE Tcl_ObjCmdProc	TclOOObjDefObjCmd;
MODULE_SCOPE Tcl_ObjCmdProc	TclOODefineClassMethodObjCmd;
MODULE_SCOPE Tcl_ObjCmdProc	TclOODefineConstructorObjCmd;
MODULE_SCOPE Tcl_ObjCmdProc	TclOODefineDefnNsObjCmd;
MODULE_SCOPE Tcl_ObjCmdProc	TclOODefineDeleteMethodObjCmd;
MODULE_SCOPE Tcl_ObjCmdProc	TclOODefineDestructorObjCmd;
MODULE_SCOPE Tcl_ObjCmdProc	TclOODefineExportObjCmd;
MODULE_SCOPE Tcl_ObjCmdProc	TclOODefineForwardObjCmd;
MODULE_SCOPE Tcl_ObjCmdProc	TclOODefineInitialiseObjCmd;
MODULE_SCOPE Tcl_ObjCmdProc	TclOODefineMethodObjCmd;
MODULE_SCOPE Tcl_ObjCmdProc	TclOODefineRenameMethodObjCmd;
MODULE_SCOPE Tcl_ObjCmdProc	TclOODefineUnexportObjCmd;
MODULE_SCOPE Tcl_ObjCmdProc	TclOODefineClassObjCmd;
MODULE_SCOPE Tcl_ObjCmdProc	TclOODefineSelfObjCmd;
MODULE_SCOPE Tcl_ObjCmdProc	TclOODefineObjSelfObjCmd;
MODULE_SCOPE Tcl_ObjCmdProc	TclOODefinePrivateObjCmd;
MODULE_SCOPE Tcl_ObjCmdProc	TclOODefinePropertyCmd;
MODULE_SCOPE Tcl_ObjCmdProc	TclOOUnknownDefinition;
MODULE_SCOPE Tcl_ObjCmdProc	TclOOCallbackObjCmd;
MODULE_SCOPE Tcl_ObjCmdProc	TclOOClassVariableObjCmd;
MODULE_SCOPE Tcl_ObjCmdProc	TclOOCopyObjectCmd;
MODULE_SCOPE Tcl_ObjCmdProc	TclOODelegateNameObjCmd;
MODULE_SCOPE Tcl_ObjCmdProc	TclOOLinkObjCmd;
MODULE_SCOPE Tcl_ObjCmdProc	TclOONextObjCmd;
MODULE_SCOPE Tcl_ObjCmdProc	TclOONextToObjCmd;
MODULE_SCOPE Tcl_ObjCmdProc	TclOOSelfObjCmd;
MODULE_SCOPE Tcl_ObjCmdProc	TclOOInfoObjectPropCmd;
MODULE_SCOPE Tcl_ObjCmdProc	TclOOInfoClassPropCmd;

/*
605
606
607
608
609
610
611

612
613
614
615
616
617
618
			    Tcl_Var *aryPtr);
MODULE_SCOPE int	TclNRObjectContextInvokeNext(Tcl_Interp *interp,
			    Tcl_ObjectContext context, Tcl_Size objc,
			    Tcl_Obj *const *objv, Tcl_Size skip);
MODULE_SCOPE void	TclOODefineBasicMethods(Class *clsPtr,
			    const DeclaredClassMethod *dcm);
MODULE_SCOPE Tcl_Obj *	TclOOObjectName(Tcl_Interp *interp, Object *oPtr);

MODULE_SCOPE void	TclOOReleaseClassContents(Tcl_Interp *interp,
			    Object *oPtr);
MODULE_SCOPE int	TclOORemoveFromInstances(Object *oPtr, Class *clsPtr);
MODULE_SCOPE int	TclOORemoveFromMixins(Class *mixinPtr, Object *oPtr);
MODULE_SCOPE int	TclOORemoveFromMixinSubs(Class *subPtr,
			    Class *mixinPtr);
MODULE_SCOPE int	TclOORemoveFromSubclasses(Class *subPtr,







>







614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
			    Tcl_Var *aryPtr);
MODULE_SCOPE int	TclNRObjectContextInvokeNext(Tcl_Interp *interp,
			    Tcl_ObjectContext context, Tcl_Size objc,
			    Tcl_Obj *const *objv, Tcl_Size skip);
MODULE_SCOPE void	TclOODefineBasicMethods(Class *clsPtr,
			    const DeclaredClassMethod *dcm);
MODULE_SCOPE Tcl_Obj *	TclOOObjectName(Tcl_Interp *interp, Object *oPtr);
MODULE_SCOPE Tcl_Obj *	TclOOObjectMyName(Tcl_Interp *interp, Object *oPtr);
MODULE_SCOPE void	TclOOReleaseClassContents(Tcl_Interp *interp,
			    Object *oPtr);
MODULE_SCOPE int	TclOORemoveFromInstances(Object *oPtr, Class *clsPtr);
MODULE_SCOPE int	TclOORemoveFromMixins(Class *mixinPtr, Object *oPtr);
MODULE_SCOPE int	TclOORemoveFromMixinSubs(Class *subPtr,
			    Class *mixinPtr);
MODULE_SCOPE int	TclOORemoveFromSubclasses(Class *subPtr,
Changes to generic/tclOOScript.h.
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
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
 * contains the commented version of everything; *this* file is automatically
 * generated.
 */

static const char *tclOOSetupScript =
/* !BEGIN!: Do not edit below this line. */
"::namespace eval ::oo {\n"
"\t::namespace path {}\n"
"\tnamespace eval Helpers {\n"
"\t\tnamespace path {}\n"
"\t\tproc callback {method args} {\n"
"\t\t\tlist [uplevel 1 {::namespace which my}] $method {*}$args\n"
"\t\t}\n"
"\t\tnamespace export callback\n"
"\t\tnamespace eval tmp {namespace import ::oo::Helpers::callback}\n"
"\t\tnamespace export -clear\n"
"\t\trename tmp::callback mymethod\n"
"\t\tnamespace delete tmp\n"
"\t\tproc classvariable {name args} {\n"
"\t\t\tset ns [info object namespace [uplevel 1 {self class}]]\n"
"\t\t\tforeach v [list $name {*}$args] {\n"
"\t\t\t\tif {[string match *(*) $v]} {\n"
"\t\t\t\t\tset reason \"can\'t create a scalar variable that looks like an array element\"\n"
"\t\t\t\t\treturn -code error -errorcode {TCL UPVAR LOCAL_ELEMENT} \\\n"
"\t\t\t\t\t\t[format {bad variable name \"%s\": %s} $v $reason]\n"
"\t\t\t\t}\n"
"\t\t\t\tif {[string match *::* $v]} {\n"
"\t\t\t\t\tset reason \"can\'t create a local variable with a namespace separator in it\"\n"
"\t\t\t\t\treturn -code error -errorcode {TCL UPVAR INVERTED} \\\n"
"\t\t\t\t\t\t[format {bad variable name \"%s\": %s} $v $reason]\n"
"\t\t\t\t}\n"
"\t\t\t\tlappend vs $v $v\n"
"\t\t\t}\n"
"\t\t\ttailcall namespace upvar $ns {*}$vs\n"
"\t\t}\n"
"\t\tproc link {args} {\n"
"\t\t\tset ns [uplevel 1 {::namespace current}]\n"
"\t\t\tforeach link $args {\n"
"\t\t\t\tif {[llength $link] == 2} {\n"
"\t\t\t\t\tlassign $link src dst\n"
"\t\t\t\t} elseif {[llength $link] == 1} {\n"
"\t\t\t\t\tlassign $link src\n"
"\t\t\t\t\tset dst $src\n"
"\t\t\t\t} else {\n"
"\t\t\t\t\treturn -code error -errorcode {TCL OO CMDLINK_FORMAT} \\\n"
"\t\t\t\t\t\t\"bad link description; must only have one or two elements\"\n"
"\t\t\t\t}\n"
"\t\t\t\tif {![string match ::* $src]} {\n"
"\t\t\t\t\tset src [string cat $ns :: $src]\n"
"\t\t\t\t}\n"
"\t\t\t\tinterp alias {} $src {} ${ns}::my $dst\n"
"\t\t\t\ttrace add command ${ns}::my delete [list \\\n"
"\t\t\t\t\t::oo::UnlinkLinkedCommand $src]\n"
"\t\t\t}\n"
"\t\t\treturn\n"
"\t\t}\n"
"\t}\n"
"\tproc UnlinkLinkedCommand {cmd args} {\n"
"\t\tif {[namespace which $cmd] ne {}} {\n"
"\t\t\trename $cmd {}\n"
"\t\t}\n"
"\t}\n"
"\tproc DelegateName {class} {\n"
"\t\tstring cat [info object namespace $class] {:: oo ::delegate}\n"
"\t}\n"
"\tproc MixinClassDelegates {class} {\n"
"\t\tif {![info object isa class $class]} {\n"
"\t\t\treturn\n"
"\t\t}\n"
"\t\tset delegate [DelegateName $class]\n"
"\t\tif {![info object isa class $delegate]} {\n"
"\t\t\treturn\n"
"\t\t}\n"
"\t\tforeach c [info class superclass $class] {\n"
"\t\t\tset d [DelegateName $c]\n"
"\t\t\tif {![info object isa class $d]} {\n"
"\t\t\t\tcontinue\n"
"\t\t\t}\n"
"\t\t\tdefine $delegate ::oo::define::superclass -appendifnew $d\n"
"\t\t}\n"
"\t\tobjdefine $class ::oo::objdefine::mixin -appendifnew $delegate\n"
"\t}\n"
"\tproc UpdateClassDelegatesAfterClone {originObject targetObject} {\n"
"\t\tset originDelegate [DelegateName $originObject]\n"
"\t\tset targetDelegate [DelegateName $targetObject]\n"
"\t\tif {\n"
"\t\t\t[info object isa class $originDelegate]\n"
"\t\t\t&& ![info object isa class $targetDelegate]\n"
"\t\t} then {\n"
"\t\t\tcopy $originDelegate $targetDelegate\n"
"\t\t\tobjdefine $targetObject ::oo::objdefine::mixin -set \\\n"
"\t\t\t\t{*}[lmap c [info object mixin $targetObject] {\n"
"\t\t\t\t\tif {$c eq $originDelegate} {set targetDelegate} {set c}\n"
"\t\t\t\t}]\n"
"\t\t}\n"
"\t}\n"
"\tproc define::classmethod {name args} {\n"
"\t\t::set argc [::llength [::info level 0]]\n"
"\t\t::if {$argc == 3} {\n"
"\t\t\t::return -code error -errorcode {TCL WRONGARGS} [::format \\\n"
"\t\t\t\t{wrong # args: should be \"%s name \?args body\?\"} \\\n"
"\t\t\t\t[::lindex [::info level 0] 0]]\n"
"\t\t}\n"
"\t\t::set cls [::uplevel 1 self]\n"
"\t\t::if {$argc == 4} {\n"
"\t\t\t::oo::define [::oo::DelegateName $cls] method $name {*}$args\n"
"\t\t}\n"
"\t\t::tailcall forward $name myclass $name\n"
"\t}\n"
"\tproc define::initialise {body} {\n"
"\t\t::set clsns [::info object namespace [::uplevel 1 self]]\n"
"\t\t::tailcall apply [::list {} $body $clsns]\n"
"\t}\n"
"\tnamespace eval define {\n"
"\t\t::namespace export initialise\n"
"\t\t::namespace eval tmp {::namespace import ::oo::define::initialise}\n"
"\t\t::namespace export -clear\n"
"\t\t::rename tmp::initialise initialize\n"
"\t\t::namespace delete tmp\n"
"\t}\n"
"\tdefine Slot {\n"
"\t\tmethod Get -unexport {} {\n"
"\t\t\treturn -code error -errorcode {TCL OO ABSTRACT_SLOT} \"unimplemented\"\n"
"\t\t}\n"
"\t\tmethod Set -unexport list {\n"
"\t\t\treturn -code error -errorcode {TCL OO ABSTRACT_SLOT} \"unimplemented\"\n"
"\t\t}\n"
"\t\tmethod Resolve -unexport list {\n"
"\t\t\treturn $list\n"
"\t\t}\n"
"\t\tmethod -set -export args {\n"
"\t\t\tset my [namespace which my]\n"
"\t\t\tset args [lmap a $args {uplevel 1 [list $my Resolve $a]}]\n"
"\t\t\ttailcall my Set $args\n"
"\t\t}\n"
"\t\tmethod -append -export args {\n"
"\t\t\tset my [namespace which my]\n"
"\t\t\tset args [lmap a $args {uplevel 1 [list $my Resolve $a]}]\n"
"\t\t\tset current [uplevel 1 [list $my Get]]\n"
"\t\t\ttailcall my Set [list {*}$current {*}$args]\n"
"\t\t}\n"
"\t\tmethod -appendifnew -export args {\n"
"\t\t\tset my [namespace which my]\n"
"\t\t\tset current [uplevel 1 [list $my Get]]\n"
"\t\t\tforeach a $args {\n"
"\t\t\t\tset a [uplevel 1 [list $my Resolve $a]]\n"
"\t\t\t\tif {$a ni $current} {\n"
"\t\t\t\t\tlappend current $a\n"
"\t\t\t\t}\n"
"\t\t\t}\n"
"\t\t\ttailcall my Set $current\n"
"\t\t}\n"
"\t\tmethod -clear -export {} {tailcall my Set {}}\n"
"\t\tmethod -prepend -export args {\n"
"\t\t\tset my [namespace which my]\n"
"\t\t\tset args [lmap a $args {uplevel 1 [list $my Resolve $a]}]\n"
"\t\t\tset current [uplevel 1 [list $my Get]]\n"
"\t\t\ttailcall my Set [list {*}$args {*}$current]\n"
"\t\t}\n"
"\t\tmethod -remove -export args {\n"
"\t\t\tset my [namespace which my]\n"
"\t\t\tset args [lmap a $args {uplevel 1 [list $my Resolve $a]}]\n"
"\t\t\tset current [uplevel 1 [list $my Get]]\n"
"\t\t\ttailcall my Set [lmap val $current {\n"
"\t\t\t\tif {$val in $args} continue else {set val}\n"
"\t\t\t}]\n"
"\t\t}\n"
"\t\tforward --default-operation my -append\n"
"\t\tmethod unknown -unexport {args} {\n"
"\t\t\tset def --default-operation\n"
"\t\t\tif {[llength $args] == 0} {\n"
"\t\t\t\ttailcall my $def\n"
"\t\t\t} elseif {![string match -* [lindex $args 0]]} {\n"
"\t\t\t\ttailcall my $def {*}$args\n"
"\t\t\t}\n"
"\t\t\tnext {*}$args\n"
"\t\t}\n"
"\t\tunexport destroy\n"
"\t}\n"
"\tobjdefine define::superclass forward --default-operation my -set\n"
"\tobjdefine define::mixin forward --default-operation my -set\n"
"\tobjdefine objdefine::mixin forward --default-operation my -set\n"
"\tdefine object method <cloned> -unexport {originObject} {\n"
"\t\tforeach p [info procs [info object namespace $originObject]::*] {\n"
"\t\t\tset args [info args $p]\n"
"\t\t\tset idx -1\n"
"\t\t\tforeach a $args {\n"
"\t\t\t\tif {[info default $p $a d]} {\n"
"\t\t\t\t\tlset args [incr idx] [list $a $d]\n"







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







23
24
25
26
27
28
29















































































































































































30
31
32
33
34
35
36
 * contains the commented version of everything; *this* file is automatically
 * generated.
 */

static const char *tclOOSetupScript =
/* !BEGIN!: Do not edit below this line. */
"::namespace eval ::oo {\n"















































































































































































"\tdefine object method <cloned> -unexport {originObject} {\n"
"\t\tforeach p [info procs [info object namespace $originObject]::*] {\n"
"\t\t\tset args [info args $p]\n"
"\t\t\tset idx -1\n"
"\t\t\tforeach a $args {\n"
"\t\t\t\tif {[info default $p $a d]} {\n"
"\t\t\t\t\tlset args [incr idx] [list $a $d]\n"
226
227
228
229
230
231
232

233
234











235
236
237
238
239
240

241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257



258
259


260



261
262
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
"\t\t\t\t} else {\n"
"\t\t\t\t\tset vNew $vOrigin\n"
"\t\t\t\t}\n"
"\t\t\t}\n"
"\t\t}\n"
"\t}\n"
"\tdefine class method <cloned> -unexport {originObject} {\n"

"\t\tnext $originObject\n"
"\t\t::oo::UpdateClassDelegatesAfterClone $originObject [self]\n"











"\t}\n"
"\tclass create singleton {\n"
"\t\tsuperclass class\n"
"\t\tvariable object\n"
"\t\tunexport create createWithNamespace\n"
"\t\tmethod new args {\n"

"\t\t\tif {![info exists object] || ![info object isa object $object]} {\n"
"\t\t\t\tset object [next {*}$args]\n"
"\t\t\t\t::oo::objdefine $object {\n"
"\t\t\t\t\tmethod destroy {} {\n"
"\t\t\t\t\t\t::return -code error -errorcode {TCL OO SINGLETON} \\\n"
"\t\t\t\t\t\t\t\"may not destroy a singleton object\"\n"
"\t\t\t\t\t}\n"
"\t\t\t\t\tmethod <cloned> -unexport {originObject} {\n"
"\t\t\t\t\t\t::return -code error -errorcode {TCL OO SINGLETON} \\\n"
"\t\t\t\t\t\t\t\"may not clone a singleton object\"\n"
"\t\t\t\t\t}\n"
"\t\t\t\t}\n"
"\t\t\t}\n"
"\t\t\treturn $object\n"
"\t\t}\n"
"\t}\n"
"\tclass create abstract {\n"



"\t\tsuperclass class\n"
"\t\tunexport create createWithNamespace new\n"


"\t}\n"



"\tnamespace eval configuresupport {\n"
"\t\t::namespace eval configurableclass {\n"
"\t\t\t::proc properties args {::tailcall property {*}$args}\n"
"\t\t\t::namespace path ::oo::define\n"
"\t\t\t::namespace export property\n"
"\t\t}\n"
"\t\t::namespace eval configurableobject {\n"
"\t\t\t::proc properties args {::tailcall property {*}$args}\n"
"\t\t\t::namespace path ::oo::objdefine\n"
"\t\t\t::namespace export property\n"
"\t\t}\n"
"\t\t::oo::define configurable {\n"
"\t\t\tdefinitionnamespace -instance configurableobject\n"
"\t\t\tdefinitionnamespace -class configurableclass\n"
"\t\t}\n"
"\t}\n"
"\tclass create configurable {\n"
"\t\tsuperclass class\n"
"\t\tconstructor {{definitionScript \"\"}} {\n"
"\t\t\tnext {mixin ::oo::configuresupport::configurable}\n"
"\t\t\tnext $definitionScript\n"
"\t\t}\n"
"\t\tdefinitionnamespace -class configuresupport::configurableclass\n"
"\t}\n"







"}\n"
/* !END!: Do not edit above this line. */
;

#endif /* TCL_OO_SCRIPT_H */

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */







>

|
>
>
>
>
>
>
>
>
>
>
>

|
|
<
|
|
>
|
|
|
<
<
<
<
<
<
<
<
<
|
|
<

|
>
>
>
|
|
>
>

>
>
>
|
<
|
|
|
|
|
|
|
|
<
<
<
<
<

<
<
<
|
|
<


>
>
>
>
>
>
>













51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74

75
76
77
78
79
80









81
82

83
84
85
86
87
88
89
90
91
92
93
94
95
96

97
98
99
100
101
102
103
104





105



106
107

108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
"\t\t\t\t} else {\n"
"\t\t\t\t\tset vNew $vOrigin\n"
"\t\t\t\t}\n"
"\t\t\t}\n"
"\t\t}\n"
"\t}\n"
"\tdefine class method <cloned> -unexport {originObject} {\n"
"\t\tset targetObject [self]\n"
"\t\tnext $originObject\n"
"\t\tset originDelegate [::oo::DelegateName $originObject]\n"
"\t\tset targetDelegate [::oo::DelegateName $targetObject]\n"
"\t\tif {\n"
"\t\t\t[info object isa class $originDelegate]\n"
"\t\t\t&& ![info object isa class $targetDelegate]\n"
"\t\t} then {\n"
"\t\t\t::oo::copy $originDelegate $targetDelegate\n"
"\t\t\t::oo::objdefine $targetObject mixin -set \\\n"
"\t\t\t\t{*}[lmap c [info object mixin $targetObject] {\n"
"\t\t\t\t\tif {$c eq $originDelegate} {set targetDelegate} {set c}\n"
"\t\t\t\t}]\n"
"\t\t}\n"
"\t}\n"
"\tclass create singleton\n"
"\tdefine singleton superclass -set class\n"

"\tdefine singleton unexport create createWithNamespace\n"
"\tdefine singleton method new args {\n"
"\t\tvariable object\n"
"\t\tif {![info exists object] || ![info object isa object $object]} {\n"
"\t\t\tset object [next {*}$args]\n"
"\t\t\t::oo::objdefine $object mixin -prepend ::oo::SingletonInstance\n"









"\t\t}\n"
"\t\treturn $object\n"

"\t}\n"
"\tclass create SingletonInstance\n"
"\tdefine SingletonInstance method destroy {} {\n"
"\t\treturn -code error -errorcode {TCL OO SINGLETON} \\\n"
"\t\t\t\"may not destroy a singleton object\"\n"
"\t}\n"
"\tdefine SingletonInstance method <cloned> -unexport {originObject} {\n"
"\t\treturn -code error -errorcode {TCL OO SINGLETON} \\\n"
"\t\t\t\"may not clone a singleton object\"\n"
"\t}\n"
"\tclass create abstract\n"
"\tdefine abstract superclass -set class\n"
"\tdefine abstract unexport create createWithNamespace new\n"
"\tnamespace eval configuresupport::configurableclass {\n"

"\t\t::proc properties args {::tailcall property {*}$args}\n"
"\t\t::namespace path ::oo::define\n"
"\t\t::namespace export property\n"
"\t}\n"
"\tnamespace eval configuresupport::configurableobject {\n"
"\t\t::proc properties args {::tailcall property {*}$args}\n"
"\t\t::namespace path ::oo::objdefine\n"
"\t\t::namespace export property\n"





"\t}\n"



"\tdefine configuresupport::configurable {\n"
"\t\tdefinitionnamespace -instance configuresupport::configurableobject\n"

"\t\tdefinitionnamespace -class configuresupport::configurableclass\n"
"\t}\n"
"\tclass create configurable\n"
"\tdefine configurable superclass -set class\n"
"\tdefine configurable constructor {{definitionScript \"\"}} {\n"
"\t\t::oo::define [self] {mixin -append ::oo::configuresupport::configurable}\n"
"\t\tnext $definitionScript\n"
"\t}\n"
"\tdefine configurable definitionnamespace -class configuresupport::configurableclass\n"
"}\n"
/* !END!: Do not edit above this line. */
;

#endif /* TCL_OO_SCRIPT_H */

/*
 * Local Variables:
 * mode: c
 * c-basic-offset: 4
 * fill-column: 78
 * End:
 */
Changes to generic/tclStringObj.c.
231
232
233
234
235
236
237




238
239
240
241
242
243
244
    Tcl_Size length)		/* The number of bytes to copy from "bytes"
				 * when initializing the new object. If
				 * TCL_INDEX_NONE, use bytes up to the first NUL
				 * byte. */
{
    return Tcl_DbNewStringObj(bytes, length, "unknown", 0);
}




#else /* if not TCL_MEM_DEBUG */
Tcl_Obj *
Tcl_NewStringObj(
    const char *bytes,		/* Points to the first of the length bytes
				 * used to initialize the new object. */
    Tcl_Size length)		/* The number of bytes to copy from "bytes"
				 * when initializing the new object. If -1,







>
>
>
>







231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
    Tcl_Size length)		/* The number of bytes to copy from "bytes"
				 * when initializing the new object. If
				 * TCL_INDEX_NONE, use bytes up to the first NUL
				 * byte. */
{
    return Tcl_DbNewStringObj(bytes, length, "unknown", 0);
}

// Redefine the macro
#define Tcl_NewStringObj(bytes, len) \
     Tcl_DbNewStringObj(bytes, len, __FILE__, __LINE__)
#else /* if not TCL_MEM_DEBUG */
Tcl_Obj *
Tcl_NewStringObj(
    const char *bytes,		/* Points to the first of the length bytes
				 * used to initialize the new object. */
    Tcl_Size length)		/* The number of bytes to copy from "bytes"
				 * when initializing the new object. If -1,
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
	return objPtr->length;
    }

    /*
     * Optimize the case where we're really dealing with a byte-array object;
     * we don't need to convert to a string to perform the get-length operation.
     *
     * Starting in Tcl 8.7, we check for a "pure" byte-array, because the
     * machinery behind that test is using a proper byte-array ObjType.  We
     * could also compute length of an improper byte-array without shimmering
     * but there's no value in that. We *want* to shimmer an improper byte-array
     * because improper byte-arrays have worthless internal reps.
     */

    if (TclIsPureByteArray(objPtr)) {







|







394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
	return objPtr->length;
    }

    /*
     * Optimize the case where we're really dealing with a byte-array object;
     * we don't need to convert to a string to perform the get-length operation.
     *
     * Starting in Tcl 9.0, we check for a "pure" byte-array, because the
     * machinery behind that test is using a proper byte-array ObjType.  We
     * could also compute length of an improper byte-array without shimmering
     * but there's no value in that. We *want* to shimmer an improper byte-array
     * because improper byte-arrays have worthless internal reps.
     */

    if (TclIsPureByteArray(objPtr)) {
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
	return objPtr->length;
    }

    /*
     * Optimize the case where we're really dealing with a byte-array object;
     * we don't need to convert to a string to perform the get-length operation.
     *
     * Starting in Tcl 8.7, we check for a "pure" byte-array, because the
     * machinery behind that test is using a proper byte-array ObjType.  We
     * could also compute length of an improper byte-array without shimmering
     * but there's no value in that. We *want* to shimmer an improper byte-array
     * because improper byte-arrays have worthless internal reps.
     */

    if (TclIsPureByteArray(objPtr)) {







|







445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
	return objPtr->length;
    }

    /*
     * Optimize the case where we're really dealing with a byte-array object;
     * we don't need to convert to a string to perform the get-length operation.
     *
     * Starting in Tcl 9.0, we check for a "pure" byte-array, because the
     * machinery behind that test is using a proper byte-array ObjType.  We
     * could also compute length of an improper byte-array without shimmering
     * but there's no value in that. We *want* to shimmer an improper byte-array
     * because improper byte-arrays have worthless internal reps.
     */

    if (TclIsPureByteArray(objPtr)) {
Changes to generic/tclStubLib.c.
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
    if (!stubsPtr || (stubsPtr->magic != magic)) {
	exact &= 0xFFFF00; /* Filter out minor/major Tcl version */
	if (!exact) {
	    exact = 0x060800;
	}
	if (stubsPtr && (stubsPtr->magic == TCL_STUB_MAGIC)
		&& ((exact|0x010000) == 0x070800)) {
	    /* We are running in Tcl 9.x, but extension is compiled with 8.6 or 8.7 */
	    stubsPtr->tcl_SetObjResult(interp, stubsPtr->tcl_ObjPrintf(
		    "this extension is compiled for Tcl %d.%d",
		    (exact & 0x0FF00)>>8, (exact & 0x0FF0000)>>16));
	} else if (stubsPtr && (stubsPtr->magic == (int)0xFCA3BACF)
		&& ((exact & 0x0FF00) >= 0x0900)) {
	    /* We are running in Tcl 8.x, but extension is compiled with 9.0+ */
	    char major[4], minor[4];







|







75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
    if (!stubsPtr || (stubsPtr->magic != magic)) {
	exact &= 0xFFFF00; /* Filter out minor/major Tcl version */
	if (!exact) {
	    exact = 0x060800;
	}
	if (stubsPtr && (stubsPtr->magic == TCL_STUB_MAGIC)
		&& ((exact|0x010000) == 0x070800)) {
	    /* We are running in Tcl 9.x, but extension is compiled with 8.6 */
	    stubsPtr->tcl_SetObjResult(interp, stubsPtr->tcl_ObjPrintf(
		    "this extension is compiled for Tcl %d.%d",
		    (exact & 0x0FF00)>>8, (exact & 0x0FF0000)>>16));
	} else if (stubsPtr && (stubsPtr->magic == (int)0xFCA3BACF)
		&& ((exact & 0x0FF00) >= 0x0900)) {
	    /* We are running in Tcl 8.x, but extension is compiled with 9.0+ */
	    char major[4], minor[4];
Changes to generic/tclTest.c.
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541

static int
TestCommonInit(
    Tcl_Interp *interp)		/* Interpreter for application. */
{
    Tcl_CmdInfo info;

    if (Tcl_InitStubs(interp, "8.7-", 0) == NULL) {
	return TCL_ERROR;
    }
    if (Tcl_GetCommandInfo(interp, "::tcl::build-info", &info)) {
	if (info.isNativeObjectProc == 2) {
	    Tcl_CreateObjCommand2(interp, "::tcl::test::build-info",
		    info.objProc2, (void *)version, NULL);
	} else {







|







527
528
529
530
531
532
533
534
535
536
537
538
539
540
541

static int
TestCommonInit(
    Tcl_Interp *interp)		/* Interpreter for application. */
{
    Tcl_CmdInfo info;

    if (Tcl_InitStubs(interp, "9.0-", 0) == NULL) {
	return TCL_ERROR;
    }
    if (Tcl_GetCommandInfo(interp, "::tcl::build-info", &info)) {
	if (info.isNativeObjectProc == 2) {
	    Tcl_CreateObjCommand2(interp, "::tcl::test::build-info",
		    info.objProc2, (void *)version, NULL);
	} else {
Changes to generic/tclTestABSList.c.
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
    return TCL_ERROR;
}

/*
 *  lgen package init
 */
int Lgen_Init(Tcl_Interp *interp) {
    if (Tcl_InitStubs(interp, "8.7", 0) == NULL) {
	return TCL_ERROR;
    }
    Tcl_CreateObjCommand(interp, "lgen", lGenObjCmd, NULL, NULL);
    Tcl_PkgProvide(interp, "lgen", "1.0");
    return TCL_OK;
}








|







1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
    return TCL_ERROR;
}

/*
 *  lgen package init
 */
int Lgen_Init(Tcl_Interp *interp) {
    if (Tcl_InitStubs(interp, "9.0-", 0) == NULL) {
	return TCL_ERROR;
    }
    Tcl_CreateObjCommand(interp, "lgen", lGenObjCmd, NULL, NULL);
    Tcl_PkgProvide(interp, "lgen", "1.0");
    return TCL_OK;
}

1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
 *----------------------------------------------------------------------
 */

int
Tcl_ABSListTest_Init(
    Tcl_Interp *interp)
{
    if (Tcl_InitStubs(interp, "8.7-", 0) == NULL) {
	return TCL_ERROR;
    }
    Tcl_CreateObjCommand(interp, "lstring", lLStringObjCmd, NULL, NULL);
    Tcl_CreateObjCommand(interp, "lgen", lGenObjCmd, NULL, NULL);
    Tcl_PkgProvide(interp, "abstractlisttest", "1.0.0");
    return TCL_OK;
}







|







1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
 *----------------------------------------------------------------------
 */

int
Tcl_ABSListTest_Init(
    Tcl_Interp *interp)
{
    if (Tcl_InitStubs(interp, "9.0-", 0) == NULL) {
	return TCL_ERROR;
    }
    Tcl_CreateObjCommand(interp, "lstring", lLStringObjCmd, NULL, NULL);
    Tcl_CreateObjCommand(interp, "lgen", lGenObjCmd, NULL, NULL);
    Tcl_PkgProvide(interp, "abstractlisttest", "1.0.0");
    return TCL_OK;
}
Changes to generic/tclTestObj.c.
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
     * An array of Tcl_Obj pointers used in the commands that operate on or get
     * the values of Tcl object-valued variables. varPtr[i] is the i-th variable's
     * Tcl_Obj *.
     */
    Tcl_Obj **varPtr;

#ifndef TCL_WITH_EXTERNAL_TOMMATH
    if (Tcl_TomMath_InitStubs(interp, "8.7-") == NULL) {
	return TCL_ERROR;
    }
#endif
    varPtr = (Tcl_Obj **)Tcl_Alloc(NUMBER_OF_OBJECT_VARS * sizeof(varPtr[0]));
    if (!varPtr) {
	return TCL_ERROR;
    }







|







102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
     * An array of Tcl_Obj pointers used in the commands that operate on or get
     * the values of Tcl object-valued variables. varPtr[i] is the i-th variable's
     * Tcl_Obj *.
     */
    Tcl_Obj **varPtr;

#ifndef TCL_WITH_EXTERNAL_TOMMATH
    if (Tcl_TomMath_InitStubs(interp, "9.0-") == NULL) {
	return TCL_ERROR;
    }
#endif
    varPtr = (Tcl_Obj **)Tcl_Alloc(NUMBER_OF_OBJECT_VARS * sizeof(varPtr[0]));
    if (!varPtr) {
	return TCL_ERROR;
    }
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
 *
 * TestlistobjCmd --
 *
 *	This function implements the 'testlistobj' command. It is used to
 *	test a few possible corner cases in list object manipulation from
 *	C code that cannot occur at the Tcl level.
 *
 *      Following new commands are added for 8.7 as regression tests for
 *      memory leaks and use-after-free. Unlike 8.6, 8.7 has multiple internal
 *      representations for lists.  It has to be ensured that corresponding
 *      implementations obey the invariants of the C list API. The script
 *      level tests do not suffice as Tcl list commands do not execute
 *      the same exact code path as the exported C API.
 *
 *      Note these new commands are only useful when Tcl is compiled with
 *      TCL_MEM_DEBUG defined.







|
|







852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
 *
 * TestlistobjCmd --
 *
 *	This function implements the 'testlistobj' command. It is used to
 *	test a few possible corner cases in list object manipulation from
 *	C code that cannot occur at the Tcl level.
 *
 *      Following new commands are added for 9.0 as regression tests for
 *      memory leaks and use-after-free. Unlike 8.6, 9.0 has multiple internal
 *      representations for lists.  It has to be ensured that corresponding
 *      implementations obey the invariants of the C list API. The script
 *      level tests do not suffice as Tcl list commands do not execute
 *      the same exact code path as the exported C API.
 *
 *      Note these new commands are only useful when Tcl is compiled with
 *      TCL_MEM_DEBUG defined.
Changes to generic/tclZipfs.c.
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
static int		InitReadableChannel(Tcl_Interp *interp,
			    ZipChannel *info, ZipEntry *z);
static int		InitWritableChannel(Tcl_Interp *interp,
			    ZipChannel *info, ZipEntry *z, int trunc);
static int		ListMountPoints(Tcl_Interp *interp);
static int		ContainsMountPoint(const char *path, int pathLen);
static void		CleanupMount(ZipFile *zf);
static Tcl_Obj *	ScriptLibrarySetup(const char *dirName);
static void		SerializeCentralDirectoryEntry(
			    const unsigned char *start,
			    const unsigned char *end, unsigned char *buf,
			    ZipEntry *z, size_t nameLength,
			    long long dataStartOffset);
static void		SerializeCentralDirectorySuffix(
			    const unsigned char *start,







<







410
411
412
413
414
415
416

417
418
419
420
421
422
423
static int		InitReadableChannel(Tcl_Interp *interp,
			    ZipChannel *info, ZipEntry *z);
static int		InitWritableChannel(Tcl_Interp *interp,
			    ZipChannel *info, ZipEntry *z, int trunc);
static int		ListMountPoints(Tcl_Interp *interp);
static int		ContainsMountPoint(const char *path, int pathLen);
static void		CleanupMount(ZipFile *zf);

static void		SerializeCentralDirectoryEntry(
			    const unsigned char *start,
			    const unsigned char *end, unsigned char *buf,
			    ZipEntry *z, size_t nameLength,
			    long long dataStartOffset);
static void		SerializeCentralDirectorySuffix(
			    const unsigned char *start,
642
643
644
645
646
647
648







649
650
651
652
653
654
655
	Tcl_Panic("out of bounds write(2): start=%p, end=%p, ptr=%p",
		bufferStart, bufferEnd, ptr);
    }
    ptr[0] = value & 0xff;
    ptr[1] = (value >> 8) & 0xff;
}








/*
 *-------------------------------------------------------------------------
 *
 * ReadLock, WriteLock, Unlock --
 *
 *	POSIX like rwlock functions to support multiple readers and single
 *	writer on internal structs.







>
>
>
>
>
>
>







641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
	Tcl_Panic("out of bounds write(2): start=%p, end=%p, ptr=%p",
		bufferStart, bufferEnd, ptr);
    }
    ptr[0] = value & 0xff;
    ptr[1] = (value >> 8) & 0xff;
}

/*
 * Need a separate mutex for locating libraries because the search calls
 * TclZipfs_Mount which takes out a write lock on the ZipFSMutex. Since
 * those cannot be nested, we need a separate mutex.
 */
TCL_DECLARE_MUTEX(ZipFSLocateLibMutex)

/*
 *-------------------------------------------------------------------------
 *
 * ReadLock, WriteLock, Unlock --
 *
 *	POSIX like rwlock functions to support multiple readers and single
 *	writer on internal structs.
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979


980
981

982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
static char *
DecodeZipEntryText(
    const unsigned char *inputBytes,
    unsigned int inputLength,
    Tcl_DString *dstPtr)	/* Must have been initialized by caller! */
{
    Tcl_Encoding encoding;
    const char *src;
    char *dst;
    int dstLen, srcLen = inputLength, flags;
    Tcl_EncodingState state;

    if (inputLength < 1) {
	return Tcl_DStringValue(dstPtr);
    }

    /*
     * We can't use Tcl_ExternalToUtfDString at this point; it has no way to
     * fail. So we use this modified version of it that can report encoding
     * errors to us (so we can fall back to something else).
     *
     * The utf-8 encoding is implemented internally, and so is guaranteed to
     * be present.


     */


    src = (const char *) inputBytes;
    dst = Tcl_DStringValue(dstPtr);
    dstLen = dstPtr->spaceAvl - 1;
    flags = TCL_ENCODING_START | TCL_ENCODING_END;	/* Special flag! */

    while (1) {
	int srcRead, dstWrote;
	int result = Tcl_ExternalToUtf(NULL, tclUtf8Encoding, src, srcLen, flags,
		&state, dst, dstLen, &srcRead, &dstWrote, NULL);
	int soFar = dst + dstWrote - Tcl_DStringValue(dstPtr);

	if (result == TCL_OK) {
	    Tcl_DStringSetLength(dstPtr, soFar);
	    return Tcl_DStringValue(dstPtr);
	} else if (result != TCL_CONVERT_NOSPACE) {
	    break;
	}

	flags &= ~TCL_ENCODING_START;
	src += srcRead;
	srcLen -= srcRead;
	if (Tcl_DStringLength(dstPtr) == 0) {
	    Tcl_DStringSetLength(dstPtr, dstLen);
	}
	Tcl_DStringSetLength(dstPtr, 2 * Tcl_DStringLength(dstPtr) + 1);
	dst = Tcl_DStringValue(dstPtr) + soFar;
	dstLen = Tcl_DStringLength(dstPtr) - soFar - 1;
    }

    /*
     * Something went wrong. Fall back to another encoding. Those *can* use
     * Tcl_ExternalToUtfDString().
     */








<
<
<
<






|
|
<

|
|
>
>


>
|
<
<
<
|
<
<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<







963
964
965
966
967
968
969




970
971
972
973
974
975
976
977

978
979
980
981
982
983
984
985
986



987








988













989
990
991
992
993
994
995
static char *
DecodeZipEntryText(
    const unsigned char *inputBytes,
    unsigned int inputLength,
    Tcl_DString *dstPtr)	/* Must have been initialized by caller! */
{
    Tcl_Encoding encoding;





    if (inputLength < 1) {
	return Tcl_DStringValue(dstPtr);
    }

    /*
     * We Tcl_ExternalToUtfDStringEx because that can report if it failed,
     * allowing us to try a different encoding.

     *
     * The UTF-8 encoding is implemented internally, and so is guaranteed to
     * be present. Tcl's own startup files (including the encoding definitions)
     * should all have ASCII filenames, which is a subset of UTF-8, and so they
     * should all work via this.
     */

    if (Tcl_ExternalToUtfDStringEx(NULL, tclUtf8Encoding,
	    (const char *) inputBytes, inputLength,



	    TCL_ENCODING_PROFILE_STRICT, dstPtr, NULL) == TCL_OK) {








	return Tcl_DStringValue(dstPtr);













    }

    /*
     * Something went wrong. Fall back to another encoding. Those *can* use
     * Tcl_ExternalToUtfDString().
     */

4299
4300
4301
4302
4303
4304
4305
4306
4307
4308
4309
4310
4311
4312
4313
4314
4315
4316
4317
4318
4319
4320
4321
4322
4323
4324
4325
4326
4327
4328
4329
4330
4331
4332
4333
4334
4335
4336
4337
4338
4339
4340
4341
4342
4343
4344
4345
4346
4347
4348
4349
4350
4351
4352
4353
4354
4355
4356
4357
4358
4359
4360
4361
4362
4363
4364
4365
4366
4367





4368
4369
4370
4371
4372
4373
4374
4375
4376
4377
4378
4379
4380
4381
4382
4383
4384
4385
4386
4387

4388
4389
4390
4391
4392
4393
4394
4395
4396
4397
4398
4399
4400
4401
4402
4403
4404
4405
4406
4407
4408
4409
4410
4411
4412
4413
4414
4415






4416
4417







4418




4419
4420
4421
4422
4423

4424
4425

4426
4427
4428



4429
4430
4431
4432
4433
4434
4435
	}
    }
    Unlock();
    return TCL_OK;
}

/*
 *-------------------------------------------------------------------------
 *
 * TclZipfs_TclLibrary --
 *
 *	This procedure gets (and possibly finds) the root that Tcl's library
 *	files are mounted under.
 *
 * Results:
 *	A Tcl object holding the location (with zero refcount), or NULL if no
 *	Tcl library can be found.
 *
 * Side effects:
 *	May initialise the cache of where such library files are to be found.
 *	This cache is never cleared.
 *
 *-------------------------------------------------------------------------
 */

/* Utility routine to centralize housekeeping */
static Tcl_Obj *
ScriptLibrarySetup(
    const char *dirName)
{
    Tcl_Obj *libDirObj = Tcl_NewStringObj(dirName, -1);
    Tcl_Obj *subDirObj, *searchPathObj;

    TclNewLiteralStringObj(subDirObj, "encoding");
    Tcl_IncrRefCount(subDirObj);
    TclNewObj(searchPathObj);
    Tcl_ListObjAppendElement(NULL, searchPathObj,
	    Tcl_FSJoinToPath(libDirObj, 1, &subDirObj));
    Tcl_DecrRefCount(subDirObj);
    Tcl_IncrRefCount(searchPathObj);
    Tcl_SetEncodingSearchPath(searchPathObj);
    Tcl_DecrRefCount(searchPathObj);
    /* Bug [fccb9f322f]. Reinit system encoding after setting search path */
    TclpSetInitialEncodings();
    zipfs_tcl_library_init = 1;
    return libDirObj;
}

Tcl_Obj *
TclZipfs_TclLibrary(void)
{
    Tcl_Obj *vfsInitScript;
    int found;
#if (defined(_WIN32) || defined(__CYGWIN__)) && !defined(STATIC_BUILD)
#   define LIBRARY_SIZE	    64
    HMODULE hModule;
    WCHAR wName[MAX_PATH + LIBRARY_SIZE];
    char dllName[(MAX_PATH + LIBRARY_SIZE) * 3];
#endif /* _WIN32 */

    /*
     * Use the cached value if that has been set; we don't want to repeat the
     * searching and mounting. Even if it is not found, see [62019f8aa9f5ec73].
     */
    
    if (zipfs_tcl_library_init) {
	if (!zipfs_literal_tcl_library) {
	    return NULL;
	}





	return ScriptLibrarySetup(zipfs_literal_tcl_library);
    }

    /*
     * Look for the library file system within the executable.
     */

    vfsInitScript = Tcl_NewStringObj(ZIPFS_APP_MOUNT "/tcl_library/init.tcl",
	    -1);
    Tcl_IncrRefCount(vfsInitScript);
    found = Tcl_FSAccess(vfsInitScript, F_OK);
    Tcl_DecrRefCount(vfsInitScript);
    if (found == TCL_OK) {
	zipfs_literal_tcl_library = ZIPFS_APP_MOUNT "/tcl_library";
	return ScriptLibrarySetup(zipfs_literal_tcl_library);
    }

    /*
     * Look for the library file system within the DLL/shared library.  Note
     * that we must mount the zip file and dll before releasing to search.

     */

#if !defined(STATIC_BUILD)
#if defined(_WIN32) || defined(__CYGWIN__)
    hModule = (HMODULE)TclWinGetTclInstance();
    GetModuleFileNameW(hModule, wName, MAX_PATH);
#ifdef __CYGWIN__
    cygwin_conv_path(3, wName, dllName, sizeof(dllName));
#else
    WideCharToMultiByte(CP_UTF8, 0, wName, -1, dllName, sizeof(dllName), NULL, NULL);
#endif

    if (ZipfsAppHookFindTclInit(dllName) == TCL_OK) {
	return ScriptLibrarySetup(zipfs_literal_tcl_library);
    }
#elif !defined(NO_DLFCN_H)
    Dl_info dlinfo;
    if (dladdr((const void *)TclZipfs_TclLibrary, &dlinfo) && (dlinfo.dli_fname != NULL)
	    && (ZipfsAppHookFindTclInit(dlinfo.dli_fname) == TCL_OK)) {
	return ScriptLibrarySetup(zipfs_literal_tcl_library);
    }
#else
    if (ZipfsAppHookFindTclInit(CFG_RUNTIME_LIBDIR "/" CFG_RUNTIME_DLLFILE) == TCL_OK) {
	return ScriptLibrarySetup(zipfs_literal_tcl_library);
    }
#endif /* _WIN32 */
#endif /* !defined(STATIC_BUILD) */







    /*
     * If anything set the cache (but subsequently failed) go with that







     * anyway.




     */

    if (zipfs_literal_tcl_library) {
	return ScriptLibrarySetup(zipfs_literal_tcl_library);
    }

    /* 
     * No zipfs tcl-library, mark it to avoid performance penalty [62019f8aa9f5ec73],

     * by future calls (child interpreters, threads, etc).
     */
    zipfs_tcl_library_init = 1;



    return NULL;
}

/*
 *-------------------------------------------------------------------------
 *
 * ZipFSTclLibraryObjCmd --







<
<
|

|
|


<
|


|
|




<
<
<
<
<
<
<
|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
|










<
<
<
<
<

|
<
|
>
>
>
>
>
|


<
|
<
|
|
<





|



|
|
>

<











|





|



|




>
>
>
>
>
>
|
<
>
>
>
>
>
>
>
|
>
>
>
>
|

|
|
<
>
|
<
>
|

|
>
>
>







4279
4280
4281
4282
4283
4284
4285


4286
4287
4288
4289
4290
4291

4292
4293
4294
4295
4296
4297
4298
4299
4300







4301
















4302
4303
4304
4305
4306
4307
4308
4309
4310
4311
4312





4313
4314

4315
4316
4317
4318
4319
4320
4321
4322
4323

4324

4325
4326

4327
4328
4329
4330
4331
4332
4333
4334
4335
4336
4337
4338
4339

4340
4341
4342
4343
4344
4345
4346
4347
4348
4349
4350
4351
4352
4353
4354
4355
4356
4357
4358
4359
4360
4361
4362
4363
4364
4365
4366
4367
4368
4369
4370
4371
4372

4373
4374
4375
4376
4377
4378
4379
4380
4381
4382
4383
4384
4385
4386
4387
4388

4389
4390

4391
4392
4393
4394
4395
4396
4397
4398
4399
4400
4401
4402
4403
4404
	}
    }
    Unlock();
    return TCL_OK;
}

/*


 * TclZipfsLocateTclLibrary --
 *
 *	This procedure locates the root that Tcl's library files are mounted
 *	under if they are under a zipfs file system.
 *
 * Results:

 *	TCL_OK if the library was found, TCL_ERROR otherwise.
 *
 * Side effects:
 *	Initializes the global variable zipfs_literal_tcl_library. Will
 *	never be cleared.
 *
 *-------------------------------------------------------------------------
 */








int
















TclZipfsLocateTclLibrary(void)
{
    Tcl_Obj *vfsInitScript;
    int found;
#if (defined(_WIN32) || defined(__CYGWIN__)) && !defined(STATIC_BUILD)
#   define LIBRARY_SIZE	    64
    HMODULE hModule;
    WCHAR wName[MAX_PATH + LIBRARY_SIZE];
    char dllName[(MAX_PATH + LIBRARY_SIZE) * 3];
#endif /* _WIN32 */






    if (zipfs_tcl_library_init) {
	return zipfs_literal_tcl_library ? TCL_OK : TCL_ERROR;

    }

    Tcl_MutexLock(&ZipFSLocateLibMutex);
    if (zipfs_tcl_library_init) {
	/* Some other thread won the race */
	Tcl_MutexUnlock(&ZipFSLocateLibMutex);
	return zipfs_literal_tcl_library ? TCL_OK : TCL_ERROR;
    }


    /* Look for the library file system within the executable. */

    vfsInitScript =
	Tcl_NewStringObj(ZIPFS_APP_MOUNT "/tcl_library/init.tcl", -1);

    Tcl_IncrRefCount(vfsInitScript);
    found = Tcl_FSAccess(vfsInitScript, F_OK);
    Tcl_DecrRefCount(vfsInitScript);
    if (found == TCL_OK) {
	zipfs_literal_tcl_library = ZIPFS_APP_MOUNT "/tcl_library";
	goto unlock_and_return;
    }

    /*
     * Look for the library file system within the DLL/shared
     * library.  Note that we must mount the zip file and dll before
     * releasing to search.
     */

#if !defined(STATIC_BUILD)
#if defined(_WIN32) || defined(__CYGWIN__)
    hModule = (HMODULE)TclWinGetTclInstance();
    GetModuleFileNameW(hModule, wName, MAX_PATH);
#ifdef __CYGWIN__
    cygwin_conv_path(3, wName, dllName, sizeof(dllName));
#else
    WideCharToMultiByte(CP_UTF8, 0, wName, -1, dllName, sizeof(dllName), NULL, NULL);
#endif

    if (ZipfsAppHookFindTclInit(dllName) == TCL_OK) {
	goto unlock_and_return;
    }
#elif !defined(NO_DLFCN_H)
    Dl_info dlinfo;
    if (dladdr((const void *)TclZipfs_TclLibrary, &dlinfo) && (dlinfo.dli_fname != NULL)
	    && (ZipfsAppHookFindTclInit(dlinfo.dli_fname) == TCL_OK)) {
	goto unlock_and_return;
    }
#else
    if (ZipfsAppHookFindTclInit(CFG_RUNTIME_LIBDIR "/" CFG_RUNTIME_DLLFILE) == TCL_OK) {
	goto unlock_and_return;
    }
#endif /* _WIN32 */
#endif /* !defined(STATIC_BUILD) */

unlock_and_return:
    zipfs_tcl_library_init = 1;
    Tcl_MutexUnlock(&ZipFSLocateLibMutex);
    return zipfs_literal_tcl_library ? TCL_OK : TCL_ERROR;
}

/*

 *-------------------------------------------------------------------------
 *
 * TclZipfs_TclLibrary --
 *
 *	This procedure gets the root that Tcl's library
 *	files are mounted under if they are under a zipfs file system.
 *
 * Results:
 *	A Tcl object holding the location (with zero refcount), or NULL if no
 *	Tcl library can be found.
 *
 *-------------------------------------------------------------------------
 */

Tcl_Obj *
TclZipfs_TclLibrary(void)

{
    /*

     * Assumes TclZipfsLocateTclLibrary has already been called at startup
     * through Tcl_InitSubsystems.
     */
    assert(zipfs_tcl_library_init);
    if (zipfs_literal_tcl_library) {
	return Tcl_NewStringObj(zipfs_literal_tcl_library, -1);
    }
    return NULL;
}

/*
 *-------------------------------------------------------------------------
 *
 * ZipFSTclLibraryObjCmd --
6488
6489
6490
6491
6492
6493
6494































6495
6496
6497
6498
6499
6500
6501
	ZipFS.fallbackEntryEncoding = NULL;
    }

    ZipFS.initialized = 0;
    Unlock();
}
































/*
 *-------------------------------------------------------------------------
 *
 * TclZipfs_AppHook --
 *
 *	Performs the argument munging for the shell
 *







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







6457
6458
6459
6460
6461
6462
6463
6464
6465
6466
6467
6468
6469
6470
6471
6472
6473
6474
6475
6476
6477
6478
6479
6480
6481
6482
6483
6484
6485
6486
6487
6488
6489
6490
6491
6492
6493
6494
6495
6496
6497
6498
6499
6500
6501
	ZipFS.fallbackEntryEncoding = NULL;
    }

    ZipFS.initialized = 0;
    Unlock();
}

/*
 * TclZipfsInitEncodingDirs --
 *
 *	Sets the encoding directory search path to the encoding directory
 *	under the tcl_library directory within a ZipFS mount. Overwrites the
 *	previously set encoding search path so only to be called at
 *	initialization.
 */
static int
TclZipfsInitEncodingDirs(void)
{
    if (zipfs_literal_tcl_library == NULL) {
	return TCL_ERROR;
    }
    Tcl_Obj *libDirObj = Tcl_NewStringObj(zipfs_literal_tcl_library, -1);
    Tcl_Obj *subDirObj, *searchPathObj;

    TclNewLiteralStringObj(subDirObj, "encoding");
    Tcl_IncrRefCount(subDirObj);
    TclNewObj(searchPathObj);
    Tcl_ListObjAppendElement(NULL, searchPathObj,
	    Tcl_FSJoinToPath(libDirObj, 1, &subDirObj));
    Tcl_DecrRefCount(subDirObj);
    Tcl_IncrRefCount(searchPathObj);
    Tcl_SetEncodingSearchPath(searchPathObj);
    Tcl_DecrRefCount(searchPathObj);
    /* Reinit system encoding after setting search path */
    TclpSetInitialEncodings();
    return TCL_OK;
}

/*
 *-------------------------------------------------------------------------
 *
 * TclZipfs_AppHook --
 *
 *	Performs the argument munging for the shell
 *
6521
6522
6523
6524
6525
6526
6527
6528
6529
6530
6531
6532



6533
6534
6535
6536
6537
6538
6539
#ifdef _WIN32
    result = Tcl_FindExecutable(NULL);
#else
    result = Tcl_FindExecutable((*argvPtr)[0]);
#endif
    archive = Tcl_GetNameOfExecutable();
    TclZipfs_Init(NULL);

    /*
     * Look for init.tcl in one of the locations mounted later in this
     * function.
     */




    if (!TclZipfs_Mount(NULL, archive, ZIPFS_APP_MOUNT, NULL)) {
	int found;
	Tcl_Obj *vfsInitScript;

	TclNewLiteralStringObj(vfsInitScript, ZIPFS_APP_MOUNT "/main.tcl");
	Tcl_IncrRefCount(vfsInitScript);







<


|

>
>
>







6521
6522
6523
6524
6525
6526
6527

6528
6529
6530
6531
6532
6533
6534
6535
6536
6537
6538
6539
6540
6541
#ifdef _WIN32
    result = Tcl_FindExecutable(NULL);
#else
    result = Tcl_FindExecutable((*argvPtr)[0]);
#endif
    archive = Tcl_GetNameOfExecutable();
    TclZipfs_Init(NULL);

    /*
     * Look for init.tcl in one of the locations mounted later in this
     * function. Errors ignored as other locations may be available.
     */
    if (TclZipfsLocateTclLibrary() == TCL_OK) {
	(void) TclZipfsInitEncodingDirs();
    }

    if (!TclZipfs_Mount(NULL, archive, ZIPFS_APP_MOUNT, NULL)) {
	int found;
	Tcl_Obj *vfsInitScript;

	TclNewLiteralStringObj(vfsInitScript, ZIPFS_APP_MOUNT "/main.tcl");
	Tcl_IncrRefCount(vfsInitScript);
Changes to library/clock.tcl.
664
665
666
667
668
669
670

671
672
673
674
675



676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692




693
694
695
696
697
698
699
    # Select the locale, eventually load it
    mcpackagelocale set $locale
    return $locale
}

#----------------------------------------------------------------------
#

# _hasRegistry --
#
#	Helper that checks whether registry module is available (Windows only)
#	and loads it on demand.
#



#----------------------------------------------------------------------
proc ::tcl::clock::_hasRegistry {} {
    set res 0
    if { $::tcl_platform(platform) eq {windows} } {
	if { [catch { package require registry 1.3 }] } {
	    # try to load registry directly from root (if uninstalled / development env):
	    if {[regexp {[/\\]library$} [info library]]} {catch {
		load [lindex \
			[glob -tails -directory [file dirname [info nameofexecutable]] \
			    tcl9registry*[expr {[::tcl::pkgconfig get debug] ? {g} : {}}].dll] 0 \
		] Registry
	    }}
	}
	if { [namespace which -command ::registry] ne "" } {
	    set res 1
	}
    }




    proc ::tcl::clock::_hasRegistry {} [list return $res]
    return $res
}

#----------------------------------------------------------------------
#
# LoadWindowsDateTimeFormats --







>


|


>
>
>

|
<











|


>
>
>
>







664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681

682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
    # Select the locale, eventually load it
    mcpackagelocale set $locale
    return $locale
}

#----------------------------------------------------------------------
#
# _registryExists --
# _hasRegistry --
#
#	Helpers that checks whether registry module is available (Windows only)
#	and loads it on demand.
#
# Side effects:
#	_hasRegistry does it only once, and hereafter simply returns 1 or 0.
#
#----------------------------------------------------------------------
proc ::tcl::clock::_registryExists {} {

    if { $::tcl_platform(platform) eq {windows} } {
	if { [catch { package require registry 1.3 }] } {
	    # try to load registry directly from root (if uninstalled / development env):
	    if {[regexp {[/\\]library$} [info library]]} {catch {
		load [lindex \
			[glob -tails -directory [file dirname [info nameofexecutable]] \
			    tcl9registry*[expr {[::tcl::pkgconfig get debug] ? {g} : {}}].dll] 0 \
		] Registry
	    }}
	}
	if { [namespace which -command ::registry] ne "" } {
	    return 1
	}
    }
    return 0
}
proc ::tcl::clock::_hasRegistry {} {
    set res [_registryExists]
    proc ::tcl::clock::_hasRegistry {} [list return $res]
    return $res
}

#----------------------------------------------------------------------
#
# LoadWindowsDateTimeFormats --
Changes to library/dde/pkgIndex.tcl.
1
2
3
4
5
if {![package vsatisfies [package provide Tcl] 9.0-]} return
if {[info sharedlibextension] != ".dll"} return
package ifneeded dde 1.5a0 \
	[list load [file join $dir tcl9dde15.dll] Dde]



|


1
2
3
4
5
if {![package vsatisfies [package provide Tcl] 9.0-]} return
if {[info sharedlibextension] != ".dll"} return
package ifneeded dde 1.5a1 \
	[list load [file join $dir tcl9dde15.dll] Dde]

Changes to library/init.tcl.
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#
# All rights reserved.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#

package require -exact tcl 9.1a0

# Compute the auto path to use in this interpreter.
# The values on the path come from several locations:
#
# The environment variable TCLLIBPATH
#
# tcl_library, which is the directory containing this init.tcl script.







|







11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#
# All rights reserved.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#

package require -exact tcl 9.1a1

# Compute the auto path to use in this interpreter.
# The values on the path come from several locations:
#
# The environment variable TCLLIBPATH
#
# tcl_library, which is the directory containing this init.tcl script.
Changes to library/manifest.txt.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
###
# Package manifest for all Tcl packages included in the /library file system
###
apply {{dir} {
  set isafe [interp issafe]
  foreach {safe package version file} {
    0 http            2.10.0 {http http.tcl}
    1 msgcat          1.7.1  {msgcat msgcat.tcl}
    1 opt             0.4.9  {opt optparse.tcl}
    0 cookiejar       0.2.0  {cookiejar cookiejar.tcl}
    0 tcl::idna       1.0.1  {cookiejar idna.tcl}
    0 platform        1.0.19 {platform platform.tcl}
    0 platform::shell 1.1.4  {platform shell.tcl}
    1 tcltest         2.5.9  {tcltest tcltest.tcl}
  } {
    if {$isafe && !$safe} continue
    package ifneeded $package $version  [list source [file join $dir {*}$file]]
  }
}} $dir











|

|





1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
###
# Package manifest for all Tcl packages included in the /library file system
###
apply {{dir} {
  set isafe [interp issafe]
  foreach {safe package version file} {
    0 http            2.10.0 {http http.tcl}
    1 msgcat          1.7.1  {msgcat msgcat.tcl}
    1 opt             0.4.9  {opt optparse.tcl}
    0 cookiejar       0.2.0  {cookiejar cookiejar.tcl}
    0 tcl::idna       1.0.1  {cookiejar idna.tcl}
    0 platform        1.1.0  {platform platform.tcl}
    0 platform::shell 1.1.4  {platform shell.tcl}
    1 tcltest         2.5.10 {tcltest tcltest.tcl}
  } {
    if {$isafe && !$safe} continue
    package ifneeded $package $version  [list source [file join $dir {*}$file]]
  }
}} $dir
Changes to library/platform/pkgIndex.tcl.
1
2
3
package ifneeded platform        1.0.19 [list source -encoding utf-8 [file join $dir platform.tcl]]
package ifneeded platform::shell 1.1.4 [list source -encoding utf-8 [file join $dir shell.tcl]]

|


1
2
3
package ifneeded platform        1.1.0 [list source -encoding utf-8 [file join $dir platform.tcl]]
package ifneeded platform::shell 1.1.4 [list source -encoding utf-8 [file join $dir shell.tcl]]

Changes to library/platform/platform.tcl.
119
120
121
122
123
124
125




126

127
128
129
130
131
132
133
		# sparc
		if {$tcl_platform(wordSize) == 8} {
		    append cpu 64
		}
	    }
	}
	darwin {




	    set plat macosx

	    # Correctly identify the cpu when running as a 64bit
	    # process on a machine with a 32bit kernel
	    if {$cpu eq "ix86"} {
		if {$tcl_platform(wordSize) == 8} {
		    set cpu x86_64
		}
	    }







>
>
>
>
|
>







119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
		# sparc
		if {$tcl_platform(wordSize) == 8} {
		    append cpu 64
		}
	    }
	}
	darwin {
	    set major [lindex [split $tcl_platform(osVersion) .] 0]
	    if {$major > 19} {
		set plat macos
	    } else {
		set plat macosx
	    }
	    # Correctly identify the cpu when running as a 64bit
	    # process on a machine with a 32bit kernel
	    if {$cpu eq "ix86"} {
		if {$tcl_platform(wordSize) == 8} {
		    set cpu x86_64
		}
	    }
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183

184

185
186
187
188
189
190
191
192
193
194
195
196

proc ::platform::identify {} {
    global tcl_platform

    set id [generic]
    regexp {^([^-]+)-([^-]+)$} $id -> plat cpu

    switch -- $plat {
	solaris {
	    regsub {^5} $tcl_platform(osVersion) 2 text
	    append plat $text
	    return "${plat}-${cpu}"
	}
	macosx {
	    set major [lindex [split $tcl_platform(osVersion) .] 0]
	    if {$major > 19} {
		set minor [lindex [split $tcl_platform(osVersion) .] 1]

		incr major -9

		append plat $major.[expr {$minor - 1}]
	    } else {
		incr major -4
		append plat 10.$major
		return "${plat}-${cpu}"
	    }
	    return "${plat}-${cpu}"
	}
	linux {
	    # Look for the libc*.so and determine its version
	    # (libc5/6, libc6 further glibc 2.X)








|





|


|
>
|
>
|



<







172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195

196
197
198
199
200
201
202

proc ::platform::identify {} {
    global tcl_platform

    set id [generic]
    regexp {^([^-]+)-([^-]+)$} $id -> plat cpu

    switch -glob -- $plat {
	solaris {
	    regsub {^5} $tcl_platform(osVersion) 2 text
	    append plat $text
	    return "${plat}-${cpu}"
	}
	macos* {
	    set major [lindex [split $tcl_platform(osVersion) .] 0]
	    if {$major > 19} {
		incr major
		if {$major < 26} {
		    incr major -10
		}
		append plat $major
	    } else {
		incr major -4
		append plat 10.$major

	    }
	    return "${plat}-${cpu}"
	}
	linux {
	    # Look for the libc*.so and determine its version
	    # (libc5/6, libc6 further glibc 2.X)

334
335
336
337
338
339
340
341
342
343
344

345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375

376
377
378

379
380
381
382
383
384
385

386
387
388
389
390
391
392
393
394
395
396

397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413

414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
	}
	macosx-x86_64 {
	    lappend res macosx-i386-x86_64
	}
	macosx-ix86 {
	    lappend res macosx-universal macosx-i386-x86_64
	}
	macosx*-*    {
	    # 10.5+,11.0+
	    if {[regexp {macosx([^-]*)-(.*)} $id -> v cpu]} {


		switch -exact -- $cpu {
		    ix86    {
			lappend alt i386-x86_64
			lappend alt universal
		    }
		    x86_64  {
			if {[lindex [split $::tcl_platform(osVersion) .] 0] < 19} {
			    set alt i386-x86_64
			} else {
			    set alt {}
			}
		    }
		    arm  {
			lappend alt x86_64
		    }
		    default { set alt {} }
		}

		if {$v ne ""} {
		    foreach {major minor} [split $v .] break

		    set res {}
		    if {$major eq 13} {
			# Add 13.0 to 13.minor to patterns.
			for {set j $minor} {$j >= 0} {incr j -1} {
			    lappend res macosx${major}.${j}-${cpu}
			    foreach a $alt {
				lappend res macosx${major}.${j}-$a
			    }
			}
			set major 12

			set minor 5
		    }
		    if {$major eq 12} {

			# Add 12.0 to 12.minor to patterns.
			for {set j $minor} {$j >= 0} {incr j -1} {
			    lappend res macosx${major}.${j}-${cpu}
			    foreach a $alt {
				lappend res macosx${major}.${j}-$a
			    }
			}

			set major 11
			set minor 5
		    }
		    if {$major eq 11} {
			# Add 11.0 to 11.minor to patterns.
			for {set j $minor} {$j >= 0} {incr j -1} {
			    lappend res macosx${major}.${j}-${cpu}
			    foreach a $alt {
				lappend res macosx${major}.${j}-$a
			    }
			}

			set major 10
			set minor 15
		    }
		    # Add 10.5 to 10.minor to patterns.
		    for {set j $minor} {$j >= 5} {incr j -1} {
			if {$cpu ne "arm"} {
			    lappend res macosx${major}.${j}-${cpu}
			}
			foreach a $alt {
			    lappend res macosx${major}.${j}-$a
			}
		    }

		    # Add unversioned patterns for 10.3/10.4 builds.
		    lappend res macosx-${cpu}
		    foreach a $alt {
			lappend res macosx-$a

		    }
		} else {
		    # No version, just do unversioned patterns.
		    foreach a $alt {
			lappend res macosx-$a
		    }
		}
	    } else {
		# no v, no cpu ... nothing
	    }
	}
    }
    lappend res tcl ; # Pure tcl packages are always compatible.
    return $res
}


# ### ### ### ######### ######### #########
## Ready

package provide platform 1.0.19

# ### ### ### ######### ######### #########
## Demo application

if {[info exists argv0] && ($argv0 eq [info script])} {
    puts ====================================
    parray tcl_platform







|

|

>






|












<
<

|
|
<
|
|
|
|
<
|
>
|
|
<
>
|
|
<
|
|
|
<
>
|
<
|
<
<
<
<
|
|
|
|
>
|
<
<
<
|
|
|
|
|
|
|
|
<
|
|
|
|
>




















|







340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370


371
372
373

374
375
376
377

378
379
380
381

382
383
384

385
386
387

388
389

390




391
392
393
394
395
396



397
398
399
400
401
402
403
404

405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
	}
	macosx-x86_64 {
	    lappend res macosx-i386-x86_64
	}
	macosx-ix86 {
	    lappend res macosx-universal macosx-i386-x86_64
	}
	macos*-*    {
	    # 10.5+,11.0+
	    if {[regexp {macosx?([^-]*)-(.*)} $id -> v cpu]} {

		foreach {major minor} [split $v.15 .] break
		switch -exact -- $cpu {
		    ix86    {
			lappend alt i386-x86_64
			lappend alt universal
		    }
		    x86_64  {
			if {$major < 11 && $minor < 15} {
			    set alt i386-x86_64
			} else {
			    set alt {}
			}
		    }
		    arm  {
			lappend alt x86_64
		    }
		    default { set alt {} }
		}

		if {$v ne ""} {


		    set res {}
		    while {$major > 10} {
			# Add $major to patterns.

			lappend res macos${major}-${cpu}
			foreach a $alt {
			    lappend res macos${major}-$a
			}

			incr major -1
			if {$major == 25} {
			    set major 15
			}

		    }
		    # Add 10.9 to 10.minor to patterns.
		    for {set j $minor} {$j >= 9} {incr j -1} {

			if {$cpu ne "arm"} {
			    lappend res macosx${major}.${j}-${cpu}
			}

			if {($cpu eq "x86_64") && ($j == 14) && ![package vsatisfies [package provide Tcl] 9.0-]} {
			    set alt i386-x86_64

			}




			foreach a $alt {
			    lappend res macosx${major}.${j}-$a
			}
		    }
		    if {![package vsatisfies [package provide Tcl] 9.0-]} {
			# Continue up to 10.5.



			for {} {$j >= 5} {incr j -1} {
			    if {$cpu ne "arm"} {
				lappend res macosx${major}.${j}-${cpu}
			    }
			    foreach a $alt {
				lappend res macosx${major}.${j}-$a
			    }
			}

			# Add unversioned patterns for 10.3/10.4 builds.
			lappend res macosx-${cpu}
			foreach a $alt {
			    lappend res macosx-$a
			}
		    }
		} else {
		    # No version, just do unversioned patterns.
		    foreach a $alt {
			lappend res macosx-$a
		    }
		}
	    } else {
		# no v, no cpu ... nothing
	    }
	}
    }
    lappend res tcl ; # Pure tcl packages are always compatible.
    return $res
}


# ### ### ### ######### ######### #########
## Ready

package provide platform 1.1.0

# ### ### ### ######### ######### #########
## Demo application

if {[info exists argv0] && ($argv0 eq [info script])} {
    puts ====================================
    parray tcl_platform
Changes to library/registry/pkgIndex.tcl.
1
2
3
4
if {![package vsatisfies [package provide Tcl] 9.0-]} return
if {[info sharedlibextension] != ".dll"} return
package ifneeded registry 1.4a0 \
	[list load [file join $dir tcl9registry14.dll] Registry]


|

1
2
3
4
if {![package vsatisfies [package provide Tcl] 9.0-]} return
if {[info sharedlibextension] != ".dll"} return
package ifneeded registry 1.4a1 \
	[list load [file join $dir tcl9registry14.dll] Registry]
Changes to library/tcltest/pkgIndex.tcl.
1
2
3
4
5
6
7
8
9
10
11
12
# Tcl package index file, version 1.1
# This file is generated by the "pkg_mkIndex -direct" command
# and sourced either when an application starts up or
# by a "package unknown" script.  It invokes the
# "package ifneeded" command to set up package-related
# information so that packages will be loaded automatically
# in response to "package require" commands.  When this
# script is sourced, the variable $dir must contain the
# full path name of this file's directory.

if {![package vsatisfies [package provide Tcl] 8.5-]} {return}
package ifneeded tcltest 2.5.9 [list source -encoding utf-8 [file join $dir tcltest.tcl]]











|
1
2
3
4
5
6
7
8
9
10
11
12
# Tcl package index file, version 1.1
# This file is generated by the "pkg_mkIndex -direct" command
# and sourced either when an application starts up or
# by a "package unknown" script.  It invokes the
# "package ifneeded" command to set up package-related
# information so that packages will be loaded automatically
# in response to "package require" commands.  When this
# script is sourced, the variable $dir must contain the
# full path name of this file's directory.

if {![package vsatisfies [package provide Tcl] 8.5-]} {return}
package ifneeded tcltest 2.5.10 [list source -encoding utf-8 [file join $dir tcltest.tcl]]
Changes to library/tcltest/tcltest.tcl.
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# All rights reserved.

namespace eval tcltest {

    # When the version number changes, be sure to update the pkgIndex.tcl file,
    # and the install directory in the Makefiles.  When the minor version
    # changes (new feature) be sure to update the man page as well.
    variable Version 2.5.9

    # Compatibility support for dumb variables defined in tcltest 1
    # Do not use these.  Call [package require] and [info patchlevel]
    # yourself.  You don't need tcltest to wrap it for you.
    variable version [package require Tcl 8.5-]
    variable patchLevel [info patchlevel]








|







17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# All rights reserved.

namespace eval tcltest {

    # When the version number changes, be sure to update the pkgIndex.tcl file,
    # and the install directory in the Makefiles.  When the minor version
    # changes (new feature) be sure to update the man page as well.
    variable Version 2.5.10

    # Compatibility support for dumb variables defined in tcltest 1
    # Do not use these.  Call [package require] and [info patchlevel]
    # yourself.  You don't need tcltest to wrap it for you.
    variable version [package require Tcl 8.5-]
    variable patchLevel [info patchlevel]

2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
		"Skipping test files that match:  [skipFiles]"
    }
    if {[llength [matchFiles]] > 0} {
	puts [outputChannel] \
		"Only running test files that match:  [matchFiles]"
    }

    set timeCmd {clock format [clock seconds]}
    puts [outputChannel] "Tests began at [eval $timeCmd]"

    # Run each of the specified tests
    foreach file [lsort [GetMatchingFiles]] {
	set tail [file tail $file]
	puts [outputChannel] $tail
	flush [outputChannel]







|







2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
		"Skipping test files that match:  [skipFiles]"
    }
    if {[llength [matchFiles]] > 0} {
	puts [outputChannel] \
		"Only running test files that match:  [matchFiles]"
    }

    set timeCmd {clock format now -format "%Y-%m-%d %H:%M:%S %Z" -locale en}
    puts [outputChannel] "Tests began at [eval $timeCmd]"

    # Run each of the specified tests
    foreach file [lsort [GetMatchingFiles]] {
	set tail [file tail $file]
	puts [outputChannel] $tail
	flush [outputChannel]
Changes to macosx/tclMacOSXFCmd.c.
90
91
92
93
94
95
96


97
98
99
100
101
102
103
    u_int16_t fdFlags;
    u_int32_t location;
    u_int16_t reserved;
    u_int32_t extendedFileInfo[4];
} __attribute__ ((__packed__)) finderinfo;

typedef struct {


    u_int32_t info_length;
    u_int32_t data[8];
} fileinfobuf;

/*
 *----------------------------------------------------------------------
 *







>
>







90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
    u_int16_t fdFlags;
    u_int32_t location;
    u_int16_t reserved;
    u_int32_t extendedFileInfo[4];
} __attribute__ ((__packed__)) finderinfo;

typedef struct {
    u_int64_t reserved1; /* Make sure data is 8-byte aligned */
    u_int32_t reserved2; /* See [992f94d847] */
    u_int32_t info_length;
    u_int32_t data[8];
} fileinfobuf;

/*
 *----------------------------------------------------------------------
 *
156
157
158
159
160
161
162
163

164
165
166
167
168
169
170
    alist.bitmapcount = ATTR_BIT_MAP_COUNT;
    if (objIndex == MACOSX_RSRCLENGTH_ATTRIBUTE) {
	alist.fileattr = ATTR_FILE_RSRCLENGTH;
    } else {
	alist.commonattr = ATTR_CMN_FNDRINFO;
    }
    native = (const char *)Tcl_FSGetNativePath(fileName);
    result = getattrlist(native, &alist, &finfo, sizeof(fileinfobuf), 0);


    if (result != 0) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"could not read attributes of \"%s\": %s",
		TclGetString(fileName), Tcl_PosixError(interp)));
	return TCL_ERROR;
    }







|
>







158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
    alist.bitmapcount = ATTR_BIT_MAP_COUNT;
    if (objIndex == MACOSX_RSRCLENGTH_ATTRIBUTE) {
	alist.fileattr = ATTR_FILE_RSRCLENGTH;
    } else {
	alist.commonattr = ATTR_CMN_FNDRINFO;
    }
    native = (const char *)Tcl_FSGetNativePath(fileName);
    result = getattrlist(native, &alist, &finfo.info_length,
	    sizeof(fileinfobuf) - offsetof(fileinfobuf, info_length), 0);

    if (result != 0) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"could not read attributes of \"%s\": %s",
		TclGetString(fileName), Tcl_PosixError(interp)));
	return TCL_ERROR;
    }
252
253
254
255
256
257
258
259

260
261
262
263
264
265
266
    alist.bitmapcount = ATTR_BIT_MAP_COUNT;
    if (objIndex == MACOSX_RSRCLENGTH_ATTRIBUTE) {
	alist.fileattr = ATTR_FILE_RSRCLENGTH;
    } else {
	alist.commonattr = ATTR_CMN_FNDRINFO;
    }
    native = (const char *)Tcl_FSGetNativePath(fileName);
    result = getattrlist(native, &alist, &finfo, sizeof(fileinfobuf), 0);


    if (result != 0) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"could not read attributes of \"%s\": %s",
		TclGetString(fileName), Tcl_PosixError(interp)));
	return TCL_ERROR;
    }







|
>







255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
    alist.bitmapcount = ATTR_BIT_MAP_COUNT;
    if (objIndex == MACOSX_RSRCLENGTH_ATTRIBUTE) {
	alist.fileattr = ATTR_FILE_RSRCLENGTH;
    } else {
	alist.commonattr = ATTR_CMN_FNDRINFO;
    }
    native = (const char *)Tcl_FSGetNativePath(fileName);
    result = getattrlist(native, &alist, &finfo.info_length,
	    sizeof(fileinfobuf) - offsetof(fileinfobuf, info_length), 0);

    if (result != 0) {
	Tcl_SetObjResult(interp, Tcl_ObjPrintf(
		"could not read attributes of \"%s\": %s",
		TclGetString(fileName), Tcl_PosixError(interp)));
	return TCL_ERROR;
    }
409
410
411
412
413
414
415
416

417
418
419
420
421
422
423
	Tcl_DString srcBuf, dstBuf;
	int result;

	bzero(&alist, sizeof(struct attrlist));
	alist.bitmapcount = ATTR_BIT_MAP_COUNT;
	alist.commonattr = ATTR_CMN_FNDRINFO;

	if (getattrlist(src, &alist, &finfo, sizeof(fileinfobuf), 0)) {

	    return TCL_ERROR;
	}
	if (setattrlist(dst, &alist, &finfo.data, sizeof(finfo.data), 0)) {
	    return TCL_ERROR;
	}

	/*







|
>







413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
	Tcl_DString srcBuf, dstBuf;
	int result;

	bzero(&alist, sizeof(struct attrlist));
	alist.bitmapcount = ATTR_BIT_MAP_COUNT;
	alist.commonattr = ATTR_CMN_FNDRINFO;

	if (getattrlist(src, &alist, &finfo.info_length,
		sizeof(fileinfobuf) - offsetof(fileinfobuf, info_length), 0)) {
	    return TCL_ERROR;
	}
	if (setattrlist(dst, &alist, &finfo.data, sizeof(finfo.data), 0)) {
	    return TCL_ERROR;
	}

	/*
431
432
433
434
435
436
437
438

439
440
441
442
443
444
445
	/*
	 * We only copy a non-empty resource fork, so determine if that's the
	 * case first.
	 */

	alist.commonattr = 0;
	alist.fileattr = ATTR_FILE_RSRCLENGTH;
	if (getattrlist(src, &alist, &finfo, sizeof(fileinfobuf), 0)) {

	    return TCL_ERROR;
	} else if (*rsrcForkSize == 0) {
	    return TCL_OK;
	}

	/*
	 * Construct paths to resource forks.







|
>







436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
	/*
	 * We only copy a non-empty resource fork, so determine if that's the
	 * case first.
	 */

	alist.commonattr = 0;
	alist.fileattr = ATTR_FILE_RSRCLENGTH;
	if (getattrlist(src, &alist, &finfo.info_length,
		sizeof(fileinfobuf) - offsetof(fileinfobuf, info_length), 0)) {
	    return TCL_ERROR;
	} else if (*rsrcForkSize == 0) {
	    return TCL_OK;
	}

	/*
	 * Construct paths to resource forks.
500
501
502
503
504
505
506
507

508
509
510
511
512
513
514
    fileinfobuf finfo;
    finderinfo *finder = (finderinfo *) &finfo.data;
    OSType osType;

    bzero(&alist, sizeof(struct attrlist));
    alist.bitmapcount = ATTR_BIT_MAP_COUNT;
    alist.commonattr = ATTR_CMN_FNDRINFO;
    if (getattrlist(pathName, &alist, &finfo, sizeof(fileinfobuf), 0) != 0) {

	return 0;
    }
    if ((types->perm & TCL_GLOB_PERM_HIDDEN) &&
	    !((finder->fdFlags & kFinfoIsInvisible) || (*fileName == '.'))) {
	return 0;
    }
    if (S_ISDIR(statBufPtr->st_mode)







|
>







506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
    fileinfobuf finfo;
    finderinfo *finder = (finderinfo *) &finfo.data;
    OSType osType;

    bzero(&alist, sizeof(struct attrlist));
    alist.bitmapcount = ATTR_BIT_MAP_COUNT;
    alist.commonattr = ATTR_CMN_FNDRINFO;
    if (getattrlist(pathName, &alist, &finfo.info_length,
	    sizeof(fileinfobuf) - offsetof(fileinfobuf, info_length), 0)) {
	return 0;
    }
    if ((types->perm & TCL_GLOB_PERM_HIDDEN) &&
	    !((finder->fdFlags & kFinfoIsInvisible) || (*fileName == '.'))) {
	return 0;
    }
    if (S_ISDIR(statBufPtr->st_mode)
Changes to tests/clock.test.
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
		  Bias 300 \
		  StandardBias 0 \
		  DaylightBias -60 \
		  StandardStart \x00\x00\x0B\x00\x01\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00 \
		  DaylightStart \x00\x00\x03\x00\x02\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00]]
}


proc ::testClock::registry { cmd path key } {
    variable reg
    if { $cmd ne {get} } {
	return -code error "test case attempts to write/query the registry"
    }
    if { ![dict exists $reg $path $key] } {
	return -code error "test case attempts to read unknown registry entry $path $key"
    }
    return [dict get $reg $path $key]
}













































# Base test cases:

# no lazy creation of clock-ensemble (interim, bug [9889f96f4da77e3b], [31fd84270644f67d]),
# so ensemble created implicitely in init.tcl
test clock-0.1 "initial: auto-loading of ensemble and stubs on demand" -setup {
    set i [interp create]; # because clock can be used somewhere, test it in new interp:







<










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







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
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
		  Bias 300 \
		  StandardBias 0 \
		  DaylightBias -60 \
		  StandardStart \x00\x00\x0B\x00\x01\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00 \
		  DaylightStart \x00\x00\x03\x00\x02\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00]]
}


proc ::testClock::registry { cmd path key } {
    variable reg
    if { $cmd ne {get} } {
	return -code error "test case attempts to write/query the registry"
    }
    if { ![dict exists $reg $path $key] } {
	return -code error "test case attempts to read unknown registry entry $path $key"
    }
    return [dict get $reg $path $key]
}
proc ::testClock::_setupRegistry {} {
    rename ::tcl::clock::_hasRegistry ::tcl::clock::_org_hasRegistry
    proc ::tcl::clock::_hasRegistry {} {return 1}
    namespace eval ::tcl::clock {
	namespace import -force ::testClock::registry
    }
    ::tcl::clock::ClearCaches
}
proc ::testClock::_cleanupRegistry {} {
    if {[namespace which -command ::tcl::clock::registry] ne ""} {
	rename ::tcl::clock::registry {}
    }
    rename ::tcl::clock::_hasRegistry {}
    rename ::tcl::clock::_org_hasRegistry ::tcl::clock::_hasRegistry
    ::tcl::clock::ClearCaches
}

proc ::testClock::_setupNoTZ {} {
    if { [info exists ::env(TZ)] } {
	variable orgTZ $::env(TZ)
	unset ::env(TZ)
    }
    if { [info exists ::env(TCL_TZ)] } {
	variable orgTclTZ $::env(TCL_TZ)
	unset ::env(TCL_TZ)
    }
}
proc ::testClock::_cleanupNoTZ {} {
    variable orgTclTZ
    if { [info exists orgTclTZ] } {
	set ::env(TCL_TZ) $orgTclTZ
    } else {
	unset -nocomplain ::env(TCL_TZ)
    }
    variable orgTZ
    if { [info exists orgTZ] } {
	set ::env(TZ) $orgTZ
    } else {
	unset -nocomplain ::env(TZ)
    }
}

# Don't confuse all following tests with TZ or TCL_TZ environment vars (unset them here):
::testClock::_setupNoTZ

# Base test cases:

# no lazy creation of clock-ensemble (interim, bug [9889f96f4da77e3b], [31fd84270644f67d]),
# so ensemble created implicitely in init.tcl
test clock-0.1 "initial: auto-loading of ensemble and stubs on demand" -setup {
    set i [interp create]; # because clock can be used somewhere, test it in new interp:
35948
35949
35950
35951
35952
35953
35954
35955
35956
35957
35958
35959
35960
35961
35962
35963
35964
35965
35966
35967
35968
35969
35970
35971
35972
35973
35974
35975
35976
35977
35978
35979
35980
35981
35982
35983
35984
35985
35986
35987
35988
35989
35990
35991
35992
35993
35994
35995
35996
35997
35998
35999
36000
36001
36002
36003
36004
36005
36006
36007
36008
36009
36010
36011
36012
36013
36014
36015
36016
36017
36018
36019
36020
36021
36022
36023
36024
36025
36026
36027
36028
36029
36030
36031
36032
36033
36034
36035
36036
36037
36038
36039
36040
36041
36042
36043
36044
36045
36046
36047
36048
36049
36050
36051
36052
36053
36054
36055
36056
36057
36058
36059
36060
36061
36062
36063
36064
36065
36066
36067
36068
36069
36070
36071
36072
36073
36074
36075
36076
36077
36078
36079
36080
36081
36082
36083
36084
36085
36086
36087
36088
36089
36090
36091
36092
36093
36094
36095
36096
36097
36098
36099
36100
36101
36102
36103
36104
36105
36106
36107
36108
36109
36110
36111
36112
36113
36114
36115
36116
36117
36118
36119
36120
36121
36122
36123
36124
36125
36126
36127
36128
36129
36130
36131
36132
36133
36134

# 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
    } \
    -body {
	clock format 0 -timezone :UTC -locale system -format %x
    } \
    -cleanup {
	namespace eval ::tcl::clock {
	    rename registry {}
	}
	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
    } \
    -body {
	clock format 0 -timezone :UTC -locale system -format %Ex
    } \
    -cleanup {
	namespace eval ::tcl::clock {
	    rename registry {}
	}
	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
    } \
    -body {
	clock format 0 -timezone :UTC -locale system -format %X
    } \
    -cleanup {
	namespace eval ::tcl::clock {
	    rename registry {}
	}
	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)] } {
	    set oldTZ $env(TZ)
	    unset env(TZ)
	}
	if { [info exists env(TCL_TZ)] } {
	    set oldTclTZ $env(TCL_TZ)
	    unset env(TCL_TZ)
	}
	::tcl::clock::ClearCaches
    } \
    -body {
	clock format 0 -locale system -format %x
    } \
    -cleanup {
	namespace eval ::tcl::clock {
	    rename registry {}
	}
	if { [info exists oldTclTZ] } {
	    set env(TCL_TZ) $oldTclTZ
	}
	if { [info exists oldTZ] } {
	    set env(TZ) $oldTZ
	}
	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)] } {
	    set oldTZ $env(TZ)
	    unset env(TZ)
	}
	if { [info exists env(TCL_TZ)] } {
	    set oldTclTZ $env(TCL_TZ)
	    unset env(TCL_TZ)
	}
	::tcl::clock::ClearCaches
    } \
    -body {
	clock format 0 -locale system -format %Ex
    } \
    -cleanup {
	namespace eval ::tcl::clock {
	    rename registry {}
	}
	if {$noreg} {set ::tcl::clock::NoRegistry {}}
	if { [info exists oldTclTZ] } {
	    set env(TCL_TZ) $oldTclTZ
	}
	if { [info exists oldTZ] } {
	    set env(TZ) $oldTZ
	}
	::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)] } {
	    set oldTZ $env(TZ)
	    unset env(TZ)
	}
	if { [info exists env(TCL_TZ)] } {
	    set oldTclTZ $env(TCL_TZ)
	    unset env(TCL_TZ)
	}
	::tcl::clock::ClearCaches
    } \
    -body {
	clock format 0 -locale system -format "%X %Z"
    } \
    -cleanup {
	namespace eval ::tcl::clock {
	    rename registry {}
	}
	if {$noreg} {set ::tcl::clock::NoRegistry {}}
	if { [info exists oldTclTZ] } {
	    set env(TCL_TZ) $oldTclTZ
	}
	if { [info exists oldTZ] } {
	    set env(TZ) $oldTZ
	}
	::tcl::clock::ClearCaches
    } \
    -result [clock format 0 -locale current -timezone EST5 \
		 -format {%l:%M:%S %p %Z}]

test clock-32.1 {scan/format across the Gregorian change} {
    set problems {}
    set t [expr { wide(-6857395200) }]







<
|
<
<
<
<





<
|
<
<
<







<
|
<
<
<
<





<
|
<
<
<







<
|
<
<
<
<





<
|
<
<
<







<
|
<
<
<
<
<
<
<
<
<
<
<
<





<
|
<
<
<
<
<
<
<
<
<







<
|
<
<
<
<
<
<
<
<
<
<
<
<





<
|
<
<
<
<
<
<
<
<
<







<
|
<
<
<
<
<
<
<
<
<
<
<
<





<
|
<
<
<
<
<
<
<
<
<







35991
35992
35993
35994
35995
35996
35997

35998




35999
36000
36001
36002
36003

36004



36005
36006
36007
36008
36009
36010
36011

36012




36013
36014
36015
36016
36017

36018



36019
36020
36021
36022
36023
36024
36025

36026




36027
36028
36029
36030
36031

36032



36033
36034
36035
36036
36037
36038
36039

36040












36041
36042
36043
36044
36045

36046









36047
36048
36049
36050
36051
36052
36053

36054












36055
36056
36057
36058
36059

36060









36061
36062
36063
36064
36065
36066
36067

36068












36069
36070
36071
36072
36073

36074









36075
36076
36077
36078
36079
36080
36081

# END testcases30


test clock-31.1 {system locale} \
    -constraints {win noappverifier} \
    -setup {

	::testClock::_setupRegistry




    } \
    -body {
	clock format 0 -timezone :UTC -locale system -format %x
    } \
    -cleanup {

	::testClock::_cleanupRegistry



    } \
    -result [clock format 0 -timezone :UTC -locale current \
		 -format {%d-%b-%Y}]

test clock-31.2 {system locale} \
    -constraints {win noappverifier} \
    -setup {

	::testClock::_setupRegistry




    } \
    -body {
	clock format 0 -timezone :UTC -locale system -format %Ex
    } \
    -cleanup {

	::testClock::_cleanupRegistry



    } \
    -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 {

	::testClock::_setupRegistry




    } \
    -body {
	clock format 0 -timezone :UTC -locale system -format %X
    } \
    -cleanup {

	::testClock::_cleanupRegistry



    } \
    -result [clock format 0 -timezone :UTC -locale current \
		 -format {%l:%M:%S %p}]

test clock-31.4 {system locale} \
    -constraints {win noappverifier} \
    -setup {

	::testClock::_setupRegistry












    } \
    -body {
	clock format 0 -locale system -format %x
    } \
    -cleanup {

	::testClock::_cleanupRegistry









    } \
    -result [clock format 0 -locale current -timezone EST5 \
		 -format {%d-%b-%Y}]

test clock-31.5 {system locale} \
    -constraints {win noappverifier} \
    -setup {

	::testClock::_setupRegistry












    } \
    -body {
	clock format 0 -locale system -format %Ex
    } \
    -cleanup {

	::testClock::_cleanupRegistry









    } \
    -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 {

	::testClock::_setupRegistry












    } \
    -body {
	clock format 0 -locale system -format "%X %Z"
    } \
    -cleanup {

	::testClock::_cleanupRegistry









    } \
    -result [clock format 0 -locale current -timezone EST5 \
		 -format {%l:%M:%S %p %Z}]

test clock-32.1 {scan/format across the Gregorian change} {
    set problems {}
    set t [expr { wide(-6857395200) }]
36971
36972
36973
36974
36975
36976
36977
36978
36979
36980
36981
36982
36983
36984
36985
36986
36987
36988
36989
36990
36991
36992
36993
36994
36995
36996
36997
36998
36999
37000
37001
37002
37003
37004
37005
37006
37007
37008
37009
37010
37011
37012
37013
37014
37015
37016
37017
37018
37019
37020
37021
37022
37023
37024
37025
37026
37027
37028
37029
37030
37031
37032
37033
37034
37035
37036
37037
37038
37039
37040
37041
37042
37043
37044
37045
37046
37047
37048
37049
37050
37051
37052
37053
37054
37055
37056
37057
37058
37059
37060
37061
37062
37063
37064
37065



37066







37067


37068














37069





37070
37071












37072


37073
37074
37075
37076
37077
37078
37079
37080
37081
37082
37083
37084
37085
37086
37087
37088
37089
37090
37091
37092
37093
37094
37095
37096
37097
37098
37099
37100
37101
37102
37103
37104
37105
37106
37107
37108
37109
37110
37111
37112
37113
37114
37115
37116
37117
37118
37119
37120
37121
37122
37123
37124
37125
37126
37127
37128
37129
37130
37131
37132
37133
37134
37135
37136
37137
37138
37139
37140
37141
37142
37143
37144
37145
37146
37147
37148
37149
    set d [clock scan $s -format %Es -gmt 1]
    # %Es depend on the time zone (local seconds instead of posix seconds).
    list [expr {$b-$a}] [expr {$d-$c}]
} {-7200 7200}

test clock-38.1 {regression - convertUTCToLocalViaC - east of Greenwich} \
    -setup {
	if { [info exists env(TZ)] } {
	    set oldTZ $env(TZ)
	}
	set env(TZ) CET-01:00CEST-02:00,M3.5.0/02:00,M10.5.0/03:00
    } \
    -body {
	clock format 0 -format %H:%M:%S -timezone :localtime
    } \
    -cleanup {
	if { [info exists oldTZ] } {
	    set env(TZ) $oldTZ
	    unset oldTZ
	} else {
	    unset env(TZ)
	}
    } \
    -result {01:00:00}

test clock-38.2 {make sure TZ is not cached after unset} \
    -setup {
	if { [info exists env(TZ)] } {
	    set oldTZ $env(TZ)
	    unset env(TZ)
	}
	if { [info exists env(TCL_TZ)] } {
	    set oldTCLTZ $env(TCL_TZ)
	    unset env(TCL_TZ)
	}
    } \
    -body {
	set t1 [clock format 0]
	# a time zone that is unlikely to anywhere
	set env(TZ) "+04:20"
	set t2 [clock format 0]
	unset env(TZ)
	set t3 [clock format 0]
	expr {$t1 eq $t3 && $t1 ne $t2}
    } \
    -cleanup {
	if { [info exists oldTZ] } {
	    set env(TZ) $oldTZ
	    unset oldTZ
	}
	if { [info exists oldTclTZ] } {
	    set env(TCL_TZ) $oldTclTZ
	    unset oldTclTZ
	}
    } \
    -result 1

test clock-38.3sc {ensure cache of base is correct for :localtime if TZ-env changing / scan} \
    -setup {
	if { [info exists env(TZ)] } {
	    set oldTZ $env(TZ)
	}
    } \
    -body {
	set res {}
	foreach env(TZ) {GMT-11:30 GMT-07:30 GMT-03:30 GMT} \
		i {{07:30:00} {03:30:00} {23:30:00} {20:00:00}} \
	{
	    lappend res [clock scan $i -format "%H:%M:%S" -base [expr {20*60*60}] -timezone :localtime]
	}
	set res
    } \
    -cleanup {
	if { [info exists oldTZ] } {
	    set env(TZ) $oldTZ
	    unset oldTZ
	} else {
	    unset env(TZ)
	}
    } \
    -result [lrepeat 4 [expr {20*60*60}]]
test clock-38.3fm {ensure cache of base is correct for :localtime if TZ-env changing / format} \
    -setup {
	if { [info exists env(TZ)] } {
	    set oldTZ $env(TZ)
	}
    } \
    -body {
	set res {}
	foreach env(TZ) {GMT-11:30 GMT-07:30 GMT-03:30 GMT} {
	    lappend res [clock format [expr {20*60*60}] -format "%Y-%m-%dT%H:%M:%S %Z" -timezone :localtime]
	}
	set res
    } \
    -cleanup {



	if { [info exists oldTZ] } {







	    set env(TZ) $oldTZ


	    unset oldTZ














	} else {





	    unset env(TZ)
	}












    } \


    -result {{1970-01-02T07:30:00 +1130} {1970-01-02T03:30:00 +0730} {1970-01-01T23:30:00 +0330} {1970-01-01T20:00:00 +0000}}

test clock-39.1 {regression - synonym timezones} {
    clock format 0 -format {%H:%M:%S} -timezone :US/Eastern
} {19:00:00}

test clock-40.1 {regression - bad month with -timezone :localtime} \
    -setup {
	if { [info exists env(TZ)] } {
	    set oldTZ $env(TZ)
	}
	set env(TZ) UTC0
    } \
    -body {
	clock scan 2000-01-01T00:00:00 -timezone :localtime \
	    -format %Y-%m-%dT%H:%M:%S
    } \
    -cleanup {
	if { [info exists oldTZ] } {
	    set env(TZ) $oldTZ
	    unset oldTZ
	} else {
	    unset env(TZ)
	}
    } \
    -result 946684800

test clock-41.1 {regression test - format group %k when hour is 0 } {
    clock format 0 -format %k -gmt true
} { 0}

test clock-42.1 {regression test - %z in :localtime when west of Greenwich } \
    -setup {
	if { [info exists env(TZ)] } {
	    set oldTZ $env(TZ)
	}
	set env(TZ) EST5
    } \
    -body {
	clock format 0 -format %z -timezone :localtime
    } \
    -cleanup {
	if { [info exists oldTZ] } {
	    set env(TZ) $oldTZ
	    unset oldTZ
	} else {
	    unset env(TZ)
	}
    } \
    -result {-0500}

# 43.1 was a bad test - mktime returning -1 is an error according to Posix.

test clock-44.1 {regression test - time zone name containing hyphen } \
    -setup {
	if { [info exists env(TZ)] } {
	    set oldTZ $env(TZ)
	}
	set env(TZ) US/East-Indiana
    } \
    -body {
	clock format 1098466496 -format %H:%M:%S%z -timezone US/East-Indiana
    } \
    -cleanup {
	if { [info exists oldTZ] } {
	    set env(TZ) $oldTZ
	    unset oldTZ
	} else {
	    unset env(TZ)
	}
    } \
    -result {12:34:56-0500}

test clock-44.2 {regression test - time zone containing only two digits} \
    -body {
	clock scan 1985-04-12T10:15:30+04 -format %Y-%m-%dT%H:%M:%S%Z
    } \







<
<
<






<
<
|
<
<
<




<
<
<
<
<
<
<
<
<
<

|


|
|
|
|


<
<
|
<
<
<
<
<

|


<
<
<
<
<










<
<
|
<
<
<



<
<
<
<
<








>
>
>
|
>
>
>
>
>
>
>
|
>
>
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>
>
>
|
<
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
|







<
<
<







<
<
|
<
<
<









<
<
<






<
<
|
<
<
<







<
<
<






<
<
|
<
<
<







36918
36919
36920
36921
36922
36923
36924



36925
36926
36927
36928
36929
36930


36931



36932
36933
36934
36935










36936
36937
36938
36939
36940
36941
36942
36943
36944
36945


36946





36947
36948
36949
36950





36951
36952
36953
36954
36955
36956
36957
36958
36959
36960


36961



36962
36963
36964





36965
36966
36967
36968
36969
36970
36971
36972
36973
36974
36975
36976
36977
36978
36979
36980
36981
36982
36983
36984
36985
36986
36987
36988
36989
36990
36991
36992
36993
36994
36995
36996
36997
36998
36999
37000
37001
37002
37003
37004
37005
37006
37007
37008

37009
37010
37011
37012
37013
37014
37015
37016
37017
37018
37019
37020
37021
37022
37023
37024
37025
37026
37027
37028
37029
37030
37031



37032
37033
37034
37035
37036
37037
37038


37039



37040
37041
37042
37043
37044
37045
37046
37047
37048



37049
37050
37051
37052
37053
37054


37055



37056
37057
37058
37059
37060
37061
37062



37063
37064
37065
37066
37067
37068


37069



37070
37071
37072
37073
37074
37075
37076
    set d [clock scan $s -format %Es -gmt 1]
    # %Es depend on the time zone (local seconds instead of posix seconds).
    list [expr {$b-$a}] [expr {$d-$c}]
} {-7200 7200}

test clock-38.1 {regression - convertUTCToLocalViaC - east of Greenwich} \
    -setup {



	set env(TZ) CET-01:00CEST-02:00,M3.5.0/02:00,M10.5.0/03:00
    } \
    -body {
	clock format 0 -format %H:%M:%S -timezone :localtime
    } \
    -cleanup {


	unset -nocomplain env(TZ)



    } \
    -result {01:00:00}

test clock-38.2 {make sure TZ is not cached after unset} \










    -body {
	set t1 [clock format 0 -locale en]
	# a time zone that is unlikely to anywhere
	set env(TZ) "+04:20"
	set t2 [clock format 0 -locale en]
	unset -nocomplain env(TZ)
	set t3 [clock format 0 -locale en]
	list [expr {$t1 eq $t3 && $t1 ne $t2}] [subst {"$t1" eq "$t3" && "$t1" ne "$t2"}]
    } \
    -cleanup {


	unset -nocomplain env(TZ)





    } \
    -match glob -result {1 *}

test clock-38.3sc {ensure cache of base is correct for :localtime if TZ-env changing / scan} \





    -body {
	set res {}
	foreach env(TZ) {GMT-11:30 GMT-07:30 GMT-03:30 GMT} \
		i {{07:30:00} {03:30:00} {23:30:00} {20:00:00}} \
	{
	    lappend res [clock scan $i -format "%H:%M:%S" -base [expr {20*60*60}] -timezone :localtime]
	}
	set res
    } \
    -cleanup {


	unset -nocomplain env(TZ)



    } \
    -result [lrepeat 4 [expr {20*60*60}]]
test clock-38.3fm {ensure cache of base is correct for :localtime if TZ-env changing / format} \





    -body {
	set res {}
	foreach env(TZ) {GMT-11:30 GMT-07:30 GMT-03:30 GMT} {
	    lappend res [clock format [expr {20*60*60}] -format "%Y-%m-%dT%H:%M:%S %Z" -timezone :localtime]
	}
	set res
    } \
    -cleanup {
	unset -nocomplain env(TZ)
    } \
    -result {{1970-01-02T07:30:00 +1130} {1970-01-02T03:30:00 +0730} {1970-01-01T23:30:00 +0330} {1970-01-01T20:00:00 +0000}}

test clock-38.4sc {ensure cache of base is correct for :localtime if TZ-env changing / scan (system TZ, no registry)} \
    -setup {
	::testClock::_setupRegistry
	# simulate we have no registry, so system TZ and :localtime get +HHMM format
	proc ::tcl::clock::_hasRegistry {} {return 0}
    } -body {
	# force epoch switch and set first TZ (a time zone that is unlikely to anywhere) and use :localtime
	set env(TZ) "+03:20"
	clock scan "12:00:00" -format "%H:%M:%S" -base [expr {20*60*60}] -timezone :localtime -locale en
	# force epoch switch, with unset TZ, it shall be system timezone now
	unset -nocomplain env(TZ)
	set t1 [clock scan "12:00:00" -format "%H:%M:%S" -base [expr {20*60*60}] -locale en]
	# force epoch switch and set another TZ (a time zone that is unlikely to anywhere) and use system timezone
	set env(TZ) "+04:20"
	set t2 [clock scan "12:00:00" -format "%H:%M:%S" -base [expr {20*60*60}] -locale en]
	# force epoch switch, with unset TZ, it shall be again system timezone
	unset -nocomplain env(TZ)
	set t3 [clock scan "12:00:00" -format "%H:%M:%S" -base [expr {20*60*60}] -locale en]
	# compare scanned values (t1 must be equal t3 and not equal t2):
	list [expr {$t1 == $t3 && $t1 != $t2}] [subst {$t1 == $t3 && $t1 != $t2}]
    } -cleanup {
	unset -nocomplain env(TZ)
	::testClock::_cleanupRegistry
    } -match glob -result {1 *}
test clock-38.4fm {ensure cache of base is correct for :localtime if TZ-env changing / format (system TZ, no registry)} \
    -setup {
	::testClock::_setupRegistry
	# simulate we have no registry, so system TZ and :localtime get +HHMM format
	proc ::tcl::clock::_hasRegistry {} {return 0}
    } -body {
	# force epoch switch and set first TZ (a time zone that is unlikely to anywhere) and use :localtime
	set env(TZ) "+03:20"

	clock format 0  -timezone :localtime -locale en
	# force epoch switch, with unset TZ, it shall be system timezone now
	unset -nocomplain env(TZ)
	set t1 [clock format 0 -locale en]
	# force epoch switch and set another TZ (a time zone that is unlikely to anywhere) and use system timezone
	set env(TZ) "+04:20"
	set t2 [clock format 0 -locale en]
	# force epoch switch, with unset TZ, it shall be again system timezone
	unset -nocomplain env(TZ)
	set t3 [clock format 0 -locale en]
	# compare formatted values (t1 must be equal t3 and not equal t2):
	list [expr {$t1 eq $t3 && $t1 ne $t2}] [subst {"$t1" eq "$t3" && "$t1" ne "$t2"}]
    } -cleanup {
	unset -nocomplain env(TZ)
	::testClock::_cleanupRegistry
    } -match glob -result {1 *}

test clock-39.1 {regression - synonym timezones} {
    clock format 0 -format {%H:%M:%S} -timezone :US/Eastern
} {19:00:00}

test clock-40.1 {regression - bad month with -timezone :localtime} \
    -setup {



	set env(TZ) UTC0
    } \
    -body {
	clock scan 2000-01-01T00:00:00 -timezone :localtime \
	    -format %Y-%m-%dT%H:%M:%S
    } \
    -cleanup {


	unset -nocomplain env(TZ)



    } \
    -result 946684800

test clock-41.1 {regression test - format group %k when hour is 0 } {
    clock format 0 -format %k -gmt true
} { 0}

test clock-42.1 {regression test - %z in :localtime when west of Greenwich } \
    -setup {



	set env(TZ) EST5
    } \
    -body {
	clock format 0 -format %z -timezone :localtime
    } \
    -cleanup {


	unset -nocomplain env(TZ)



    } \
    -result {-0500}

# 43.1 was a bad test - mktime returning -1 is an error according to Posix.

test clock-44.1 {regression test - time zone name containing hyphen } \
    -setup {



	set env(TZ) US/East-Indiana
    } \
    -body {
	clock format 1098466496 -format %H:%M:%S%z -timezone US/East-Indiana
    } \
    -cleanup {


	unset -nocomplain env(TZ)



    } \
    -result {12:34:56-0500}

test clock-44.2 {regression test - time zone containing only two digits} \
    -body {
	clock scan 1985-04-12T10:15:30+04 -format %Y-%m-%dT%H:%M:%S%Z
    } \
37554
37555
37556
37557
37558
37559
37560
37561
37562
37563
37564
37565
37566
37567
37568
37569
37570
37571
37572
37573
37574
37575
37576
37577
37578
37579
37580
37581
37582
37583
37584
37585
37586
37587
37588
37589
37590
37591
37592
37593
37594
37595
37596
37597
37598
37599
37600
37601
37602
37603
    -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}
	if { [info exists env(TZ)] } {
	    set oldTZ $env(TZ)
	    unset env(TZ)
	}
	if { [info exists env(TCL_TZ)] } {
	    set oldTclTZ $env(TCL_TZ)
	    unset env(TCL_TZ)
	}
	# make it so New York time is a missing file
	dict set ::tcl::clock::WinZoneInfo \
	    {-18000 0 3600 0 11 0 1 2 0 0 0 0 3 0 2 2 0 0 0} \
	    :No/Such/File
	::tcl::clock::ClearCaches
    } \
    -body {
	list [::tcl::clock::GuessWindowsTimeZone] \
	    [clock format 0 -locale system -format "%H:%M:%S %Z"] \
	    [clock format -86400 -format "%Y"]
    } \
    -cleanup {
	# restore the registry and environment
	namespace eval ::tcl::clock {
	    rename registry {}
	}
	if {$noreg} {set ::tcl::clock::NoRegistry {}}
	if { [info exists oldTclTZ] } {
	    set env(TCL_TZ) $oldTclTZ
	}
	if { [info exists oldTZ] } {
	    set env(TZ) $oldTZ
	}
	# put New York back on the map
	dict set ::tcl::clock::WinZoneInfo \
	    {-18000 0 3600 0 11 0 1 2 0 0 0 0 3 0 2 2 0 0 0} \
	    :America/New_York
	::tcl::clock::ClearCaches
    } \
    -result {<-0500>+05:00:00<-0400>+04:00:00,M3.2.0/02:00:00,M11.1.0/02:00:00 {19:00:00 -0500} 1969}







<
|
<
<
<
<
<
<
<
<
<
<
<













<
|
<
<
<
<
<
<
<
<







37481
37482
37483
37484
37485
37486
37487

37488











37489
37490
37491
37492
37493
37494
37495
37496
37497
37498
37499
37500
37501

37502








37503
37504
37505
37506
37507
37508
37509
    -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

	::testClock::_setupRegistry











	# make it so New York time is a missing file
	dict set ::tcl::clock::WinZoneInfo \
	    {-18000 0 3600 0 11 0 1 2 0 0 0 0 3 0 2 2 0 0 0} \
	    :No/Such/File
	::tcl::clock::ClearCaches
    } \
    -body {
	list [::tcl::clock::GuessWindowsTimeZone] \
	    [clock format 0 -locale system -format "%H:%M:%S %Z"] \
	    [clock format -86400 -format "%Y"]
    } \
    -cleanup {
	# restore the registry and environment

	::testClock::_cleanupRegistry








	# put New York back on the map
	dict set ::tcl::clock::WinZoneInfo \
	    {-18000 0 3600 0 11 0 1 2 0 0 0 0 3 0 2 2 0 0 0} \
	    :America/New_York
	::tcl::clock::ClearCaches
    } \
    -result {<-0500>+05:00:00<-0400>+04:00:00,M3.2.0/02:00:00,M11.1.0/02:00:00 {19:00:00 -0500} 1969}
38621
38622
38623
38624
38625
38626
38627
38628
38629

38630
38631
38632
38633
38634
38635
38636
    unset ::tcltest::skippedBecause(valid_off)
}
if {!$valid_mode && [info exists ::tcltest::skippedBecause(!valid_off)]} {
    incr ::tcltest::numTests(Total) -$::tcltest::skippedBecause(!valid_off)
    incr ::tcltest::numTests(Skipped) -$::tcltest::skippedBecause(!valid_off)
    unset ::tcltest::skippedBecause(!valid_off)
}
::tcltest::cleanupTests
namespace delete ::testClock

unset valid_mode

return

# Local Variables:
# mode: tcl
# End:







|

>







38527
38528
38529
38530
38531
38532
38533
38534
38535
38536
38537
38538
38539
38540
38541
38542
38543
    unset ::tcltest::skippedBecause(valid_off)
}
if {!$valid_mode && [info exists ::tcltest::skippedBecause(!valid_off)]} {
    incr ::tcltest::numTests(Total) -$::tcltest::skippedBecause(!valid_off)
    incr ::tcltest::numTests(Skipped) -$::tcltest::skippedBecause(!valid_off)
    unset ::tcltest::skippedBecause(!valid_off)
}
::testClock::_cleanupNoTZ
namespace delete ::testClock
::tcltest::cleanupTests
unset valid_mode

return

# Local Variables:
# mode: tcl
# End:
Changes to tests/cmdMZ.test.
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
    } -> foo] [dictSort $foo] [info errorstack]
} {2 {-code 1 -errorcode NONE -errorstack {CALL a CALL b} -level 1} {CALL a CALL b}}
test cmdMZ-return-2.19 {return option handling} -body {
    return -level 0 -options {-options {-code break} -code continue}
} -returnCodes continue -result {}
test cmdMZ-return-2.20 {return option handling} {
    list [catch {
	return -level 0 -options {-foo 1} -options {-bar 2} 
    } -> foo] $foo
} {0 {-foo 1 -bar 2 -code 0 -level 0}}
test cmdMZ-return-2.21 {return option handling} {
    list [catch {
	return -level 0 -options {-options {-foo 1} -options {-bar 2}}
    } -> foo] $foo
} {0 {-foo 1 -bar 2 -code 0 -level 0}}







|







198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
    } -> foo] [dictSort $foo] [info errorstack]
} {2 {-code 1 -errorcode NONE -errorstack {CALL a CALL b} -level 1} {CALL a CALL b}}
test cmdMZ-return-2.19 {return option handling} -body {
    return -level 0 -options {-options {-code break} -code continue}
} -returnCodes continue -result {}
test cmdMZ-return-2.20 {return option handling} {
    list [catch {
	return -level 0 -options {-foo 1} -options {-bar 2}
    } -> foo] $foo
} {0 {-foo 1 -bar 2 -code 0 -level 0}}
test cmdMZ-return-2.21 {return option handling} {
    list [catch {
	return -level 0 -options {-options {-foo 1} -options {-bar 2}}
    } -> foo] $foo
} {0 {-foo 1 -bar 2 -code 0 -level 0}}
Changes to tests/dict.test.
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
	set d {p {q {a 1 b 2}}}
	apply {{} {
	    uplevel 1 {
		dict with d p q {
		    string cat "$a,$b"
		}
	    }
	}} 
    }}
} 1,2

proc linenumber {} {
    dict get [info frame -1] line
}
test dict-23.1 {dict compilation crash: Bug 3487626} {







|







1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
	set d {p {q {a 1 b 2}}}
	apply {{} {
	    uplevel 1 {
		dict with d p q {
		    string cat "$a,$b"
		}
	    }
	}}
    }}
} 1,2

proc linenumber {} {
    dict get [info frame -1] line
}
test dict-23.1 {dict compilation crash: Bug 3487626} {
Changes to tests/encoding.test.
80
81
82
83
84
85
86

87
88
89
90
91
92
93
    encoding system iso8859-1
    llength shiftjis		;# Shimmer away any cache of Tcl_Encoding
    lappend x [catch {encoding convertto shiftjis 乎} msg] $msg
} -cleanup {
    encoding system iso8859-1
    encoding dirs $path
    encoding system $system

} -result "\x8C\xC1 1 {unknown encoding \"shiftjis\"}"

test encoding-3.1 {Tcl_GetEncodingName, NULL} -setup {
    set old [encoding system]
} -body {
    encoding system shiftjis
    encoding system







>







80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
    encoding system iso8859-1
    llength shiftjis		;# Shimmer away any cache of Tcl_Encoding
    lappend x [catch {encoding convertto shiftjis 乎} msg] $msg
} -cleanup {
    encoding system iso8859-1
    encoding dirs $path
    encoding system $system
    unset -nocomplain path
} -result "\x8C\xC1 1 {unknown encoding \"shiftjis\"}"

test encoding-3.1 {Tcl_GetEncodingName, NULL} -setup {
    set old [encoding system]
} -body {
    encoding system shiftjis
    encoding system
134
135
136
137
138
139
140

141
142
143
144
145
146
147
} -cleanup {
    encoding dirs $path
    cd [workingDirectory]
    removeFile [file join tmp encoding junk2.enc]
    removeFile [file join tmp encoding junk.enc]
    removeDirectory [file join tmp encoding]
    removeDirectory tmp

} -result {junk junk2}

test encoding-5.1 {Tcl_SetSystemEncoding} -setup {
    set old [encoding system]
} -body {
    encoding system jis0208
    encoding convertto 乎







>







135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
} -cleanup {
    encoding dirs $path
    cd [workingDirectory]
    removeFile [file join tmp encoding junk2.enc]
    removeFile [file join tmp encoding junk.enc]
    removeDirectory [file join tmp encoding]
    removeDirectory tmp
    unset -nocomplain path
} -result {junk junk2}

test encoding-5.1 {Tcl_SetSystemEncoding} -setup {
    set old [encoding system]
} -body {
    encoding system jis0208
    encoding convertto 乎
232
233
234
235
236
237
238

239
240
241
242
243
244
245
    set system [encoding system]
    set path [encoding dirs]
    encoding system iso8859-1
    encoding dirs {}
    llength jis0208	;# Shimmer any cached Tcl_Encoding in shared literal
    set x [list [catch {encoding convertto jis0208 乎} msg] $msg]
    encoding dirs $path

    encoding system $system
    lappend x [encoding convertto jis0208 乎]
} {1 {unknown encoding "jis0208"} 8C}
test encoding-11.2 {LoadEncodingFile: single-byte} {
    encoding convertfrom jis0201 \xA1
} 。
test encoding-11.3 {LoadEncodingFile: double-byte} {







>







234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
    set system [encoding system]
    set path [encoding dirs]
    encoding system iso8859-1
    encoding dirs {}
    llength jis0208	;# Shimmer any cached Tcl_Encoding in shared literal
    set x [list [catch {encoding convertto jis0208 乎} msg] $msg]
    encoding dirs $path
    unset -nocomplain path
    encoding system $system
    lappend x [encoding convertto jis0208 乎]
} {1 {unknown encoding "jis0208"} 8C}
test encoding-11.2 {LoadEncodingFile: single-byte} {
    encoding convertfrom jis0201 \xA1
} 。
test encoding-11.3 {LoadEncodingFile: double-byte} {
271
272
273
274
275
276
277

278
279
280
281
282
283
284
} -returnCodes error -cleanup {
    file delete [file join [temporaryDirectory] tmp encoding splat.enc]
    removeDirectory [file join tmp encoding]
    removeDirectory tmp
    cd [workingDirectory]
    encoding dirs $path
    encoding system $system

} -result {invalid encoding file "splat"}
test encoding-11.8 {encoding: extended Unicode UTF-16} {
    encoding convertto utf-16le 😹
} =Ø9Þ
test encoding-11.9 {encoding: extended Unicode UTF-16} {
    encoding convertto utf-16be 😹
} Ø=Þ9







>







274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
} -returnCodes error -cleanup {
    file delete [file join [temporaryDirectory] tmp encoding splat.enc]
    removeDirectory [file join tmp encoding]
    removeDirectory tmp
    cd [workingDirectory]
    encoding dirs $path
    encoding system $system
    unset -nocomplain path
} -result {invalid encoding file "splat"}
test encoding-11.8 {encoding: extended Unicode UTF-16} {
    encoding convertto utf-16le 😹
} =Ø9Þ
test encoding-11.9 {encoding: extended Unicode UTF-16} {
    encoding convertto utf-16be 😹
} Ø=Þ9
1250
1251
1252
1253
1254
1255
1256










1257
1258
1259
1260
1261
1262
1263
1264
1265
    encoding convertfrom -profile replace iso2022-jp "\x1b\$B\$*;n\$"
} -result \u304A\u8A66\uFFFD

test encoding-bug-7346adc50f-tcl8 {OOM on convertfrom truncated iso2022 - tcl8} -body {
    encoding convertfrom -profile tcl8 iso2022-jp "\x1b\$B\$*;n\$"
} -result \u304A\u8A66\uFFFD












# cleanup
namespace delete ::tcl::test::encoding
::tcltest::cleanupTests
return

# Local Variables:
# mode: tcl
# End:







>
>
>
>
>
>
>
>
>
>









1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
    encoding convertfrom -profile replace iso2022-jp "\x1b\$B\$*;n\$"
} -result \u304A\u8A66\uFFFD

test encoding-bug-7346adc50f-tcl8 {OOM on convertfrom truncated iso2022 - tcl8} -body {
    encoding convertfrom -profile tcl8 iso2022-jp "\x1b\$B\$*;n\$"
} -result \u304A\u8A66\uFFFD

test encoding-dirs-bug-87b69745be {encoding dirs reset on interp creation} -setup {
    set origEncodingDirs [encoding dirs]
} -cleanup {
    encoding dirs $origEncodingDirs
    unset -nocomplain origEncodingDirs
} -body {
    encoding dirs [linsert [encoding dirs] end /temp]
    interp delete [interp create]
	encoding dirs
} -result [linsert [encoding dirs] end /temp]

# cleanup
namespace delete ::tcl::test::encoding
::tcltest::cleanupTests
return

# Local Variables:
# mode: tcl
# End:
Changes to tests/exec.test.
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838

# ----------------------------------------------------------------------
# cleanup

foreach file {gorp.file gorp.file2 echo echo2 echobin cat wc sh sh2 sleep exit err} {
    removeFile $file
}
unset -nocomplain path

::tcltest::cleanupTests
return

# Local Variables:
# mode: tcl
# End:







|







824
825
826
827
828
829
830
831
832
833
834
835
836
837
838

# ----------------------------------------------------------------------
# cleanup

foreach file {gorp.file gorp.file2 echo echo2 echobin cat wc sh sh2 sleep exit err} {
    removeFile $file
}
unset -nocomplain path tmp

::tcltest::cleanupTests
return

# Local Variables:
# mode: tcl
# End:
Changes to tests/fCmd.test.
2704
2705
2706
2707
2708
2709
2710

2711
2712
2713
2714
2715
2716
2717
2718

2719
2720
2721

2722
2723
2724
2725
2726
2727
2728
2729

2730
2731
2732
2733
2734
2735
2736
2737

2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748

2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764

2765
2766
2767

2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781

2782
2783
2784

2785
2786
2787
2788

2789
2790
2791

2792
2793
2794
2795
2796
2797
2798
test fCmd-30.3 {file readable on 'pagefile.sys'} -constraints {win notInCIenv} -body {
    set r {}
    if {[info exists env(SystemDrive)]} {
	set path $env(SystemDrive)/pagefile.sys
	lappend r exists [file exists $path]
	lappend r readable [file readable $path]
	lappend r stat [catch {file stat $path a} e] $e

    }
    return $r
} -result {exists 1 readable 0 stat 0 {}}

test fCmd-31.1 {file home} -body {
    file home
} -result [file join $::env(HOME)]
test fCmd-31.2 {file home - obeys env} -setup {

    set ::env(HOME) $::env(HOME)/xxx
} -cleanup {
    set ::env(HOME) [file dirname $::env(HOME)]

} -body {
    file home
} -result [file join $::env(HOME) xxx]
test fCmd-31.3 {file home - \ -> /} -constraints win -setup {
    set saved $::env(HOME)
    set ::env(HOME) C:\\backslash\\path
} -cleanup {
    set ::env(HOME) $saved

} -body {
    file home
} -result C:/backslash/path
test fCmd-31.4 {file home - error} -setup {
    set saved $::env(HOME)
    unset ::env(HOME)
} -cleanup {
    set ::env(HOME) $saved

} -body {
    file home
} -returnCodes error -result {couldn't find HOME environment variable to expand path}
test fCmd-31.5 {
    file home - relative path. Following 8.x ~ expansion behavior, relative
    paths are not made absolute
} -setup {
    set saved $::env(HOME)
    set ::env(HOME) relative/path
} -cleanup {
    set ::env(HOME) $saved

} -body {
    file home
} -result relative/path
test fCmd-31.6 {file home USER} -body {
    # Note - as in 8.x this form does NOT necessarily give same result as
    # env(HOME) even when user is current user. Assume result contains user
    # name, else not sure how to check
    string tolower [file home $::tcl_platform(user)]
} -match glob -result [gethomedirglob $::tcl_platform(user)]
test fCmd-31.7 {file home UNKNOWNUSER} -body {
    file home nosuchuser
} -returnCodes error -result {user "nosuchuser" doesn't exist}
test fCmd-31.8 {file home extra arg} -body {
    file home $::tcl_platform(user) arg
} -returnCodes error -result {wrong # args: should be "file home ?user?"}
test fCmd-31.9 {file home USER does not follow env(HOME)} -setup {

    set ::env(HOME) [file join $::env(HOME) foo]
} -cleanup {
    set ::env(HOME) [file dirname $::env(HOME)]

} -body {
    string tolower [file home $::tcl_platform(user)]
} -match glob -result [gethomedirglob $::tcl_platform(user)]

# file tildeexpand and testfstildexpand are identical in behavior
# but tested separately as the former is a script wrapper that does some
# sanitization/optimization while the latter is a raw call to Tcl_FSTildeExpand.
test fCmd-32.1 {file tildeexpand ~} -body {
    file tildeexpand ~
} -result [file join $::env(HOME)]
test fCmd-32.1.1 {Tcl_FSTildeExpand ~} -constraints testfstildeexpand -body {
    testfstildeexpand ~
} -result [file join $::env(HOME)]
test fCmd-32.2 {file tildeexpand ~ - obeys env} -setup {

    set ::env(HOME) $::env(HOME)/xxx
} -cleanup {
    set ::env(HOME) [file dirname $::env(HOME)]

} -body {
    file tildeexpand ~
} -result [file join $::env(HOME) xxx]
test fCmd-32.2.1 {Tcl_FSTildeExpand ~ - obeys env} -setup {

    set ::env(HOME) $::env(HOME)/xxx
} -cleanup {
    set ::env(HOME) [file dirname $::env(HOME)]

} -constraints testfstildeexpand -body {
    testfstildeexpand ~
} -result [file join $::env(HOME) xxx]
test fCmd-32.3 {file tildeexpand ~ - error} -setup {
    set saved $::env(HOME)
    unset ::env(HOME)
} -cleanup {







>








>


|
>




|


|
>








>











>
















>


|
>














>


|
>




>


|
>







2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
test fCmd-30.3 {file readable on 'pagefile.sys'} -constraints {win notInCIenv} -body {
    set r {}
    if {[info exists env(SystemDrive)]} {
	set path $env(SystemDrive)/pagefile.sys
	lappend r exists [file exists $path]
	lappend r readable [file readable $path]
	lappend r stat [catch {file stat $path a} e] $e
        unset -nocomplain path
    }
    return $r
} -result {exists 1 readable 0 stat 0 {}}

test fCmd-31.1 {file home} -body {
    file home
} -result [file join $::env(HOME)]
test fCmd-31.2 {file home - obeys env} -setup {
    set temp $::env(HOME)
    set ::env(HOME) $::env(HOME)/xxx
} -cleanup {
    set ::env(HOME) $temp
    unset temp
} -body {
    file home
} -result [file join $::env(HOME) xxx]
test fCmd-31.3 {file home - \ -> /} -constraints win -setup {
    set temp $::env(HOME)
    set ::env(HOME) C:\\backslash\\path
} -cleanup {
    set ::env(HOME) $temp
    unset temp
} -body {
    file home
} -result C:/backslash/path
test fCmd-31.4 {file home - error} -setup {
    set saved $::env(HOME)
    unset ::env(HOME)
} -cleanup {
    set ::env(HOME) $saved
    unset saved
} -body {
    file home
} -returnCodes error -result {couldn't find HOME environment variable to expand path}
test fCmd-31.5 {
    file home - relative path. Following 8.x ~ expansion behavior, relative
    paths are not made absolute
} -setup {
    set saved $::env(HOME)
    set ::env(HOME) relative/path
} -cleanup {
    set ::env(HOME) $saved
    unset saved
} -body {
    file home
} -result relative/path
test fCmd-31.6 {file home USER} -body {
    # Note - as in 8.x this form does NOT necessarily give same result as
    # env(HOME) even when user is current user. Assume result contains user
    # name, else not sure how to check
    string tolower [file home $::tcl_platform(user)]
} -match glob -result [gethomedirglob $::tcl_platform(user)]
test fCmd-31.7 {file home UNKNOWNUSER} -body {
    file home nosuchuser
} -returnCodes error -result {user "nosuchuser" doesn't exist}
test fCmd-31.8 {file home extra arg} -body {
    file home $::tcl_platform(user) arg
} -returnCodes error -result {wrong # args: should be "file home ?user?"}
test fCmd-31.9 {file home USER does not follow env(HOME)} -setup {
    set saved $::env(HOME)
    set ::env(HOME) [file join $::env(HOME) foo]
} -cleanup {
    set ::env(HOME) $saved
    unset saved
} -body {
    string tolower [file home $::tcl_platform(user)]
} -match glob -result [gethomedirglob $::tcl_platform(user)]

# file tildeexpand and testfstildexpand are identical in behavior
# but tested separately as the former is a script wrapper that does some
# sanitization/optimization while the latter is a raw call to Tcl_FSTildeExpand.
test fCmd-32.1 {file tildeexpand ~} -body {
    file tildeexpand ~
} -result [file join $::env(HOME)]
test fCmd-32.1.1 {Tcl_FSTildeExpand ~} -constraints testfstildeexpand -body {
    testfstildeexpand ~
} -result [file join $::env(HOME)]
test fCmd-32.2 {file tildeexpand ~ - obeys env} -setup {
    set saved $::env(HOME)
    set ::env(HOME) $::env(HOME)/xxx
} -cleanup {
    set ::env(HOME) $saved
    unset saved
} -body {
    file tildeexpand ~
} -result [file join $::env(HOME) xxx]
test fCmd-32.2.1 {Tcl_FSTildeExpand ~ - obeys env} -setup {
    set saved $::env(HOME)
    set ::env(HOME) $::env(HOME)/xxx
} -cleanup {
    set ::env(HOME) $saved
    unset saved
} -constraints testfstildeexpand -body {
    testfstildeexpand ~
} -result [file join $::env(HOME) xxx]
test fCmd-32.3 {file tildeexpand ~ - error} -setup {
    set saved $::env(HOME)
    unset ::env(HOME)
} -cleanup {
2917
2918
2919
2920
2921
2922
2923

2924
2925
2926
2927
2928
2929
2930

2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
test fCmd-32.16.1 {Tcl_FSTildeExpand ~USER\\bar} -constraints testfstildeexpand -body {
    # Note - as in 8.x this form does NOT necessarily give same result as
    # env(HOME) even when user is current user. Assume result contains user
    # name, else not sure how to check
    string tolower [testfstildeexpand ~$::tcl_platform(user)\\bar]
} -constraints win -match glob -result [file join [gethomedirglob $::tcl_platform(user)] bar]
test fCmd-32.17 {file tildeexpand ~USER does not mirror HOME} -setup {

    set ::env(HOME) [file join $::env(HOME) foo]
} -cleanup {
    set ::env(HOME) [file dirname $::env(HOME)]
} -body {
    string tolower [file tildeexpand ~$::tcl_platform(user)]
} -match glob -result [gethomedirglob $::tcl_platform(user)]
test fCmd-32.17.1 {Tcl_FSTildeExpand ~USER does not mirror HOME} -setup {

    set ::env(HOME) [file join $::env(HOME) foo]
} -cleanup {
    set ::env(HOME) [file dirname $::env(HOME)]
} -constraints testfstildeexpand -body {
    string tolower [testfstildeexpand ~$::tcl_platform(user)]
} -match glob -result [gethomedirglob $::tcl_platform(user)]


# cleanup
cleanup







>


|




>


|







2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
test fCmd-32.16.1 {Tcl_FSTildeExpand ~USER\\bar} -constraints testfstildeexpand -body {
    # Note - as in 8.x this form does NOT necessarily give same result as
    # env(HOME) even when user is current user. Assume result contains user
    # name, else not sure how to check
    string tolower [testfstildeexpand ~$::tcl_platform(user)\\bar]
} -constraints win -match glob -result [file join [gethomedirglob $::tcl_platform(user)] bar]
test fCmd-32.17 {file tildeexpand ~USER does not mirror HOME} -setup {
    set oldHome $::env(HOME)
    set ::env(HOME) [file join $::env(HOME) foo]
} -cleanup {
    set ::env(HOME) $oldHome
} -body {
    string tolower [file tildeexpand ~$::tcl_platform(user)]
} -match glob -result [gethomedirglob $::tcl_platform(user)]
test fCmd-32.17.1 {Tcl_FSTildeExpand ~USER does not mirror HOME} -setup {
    set oldHome $::env(HOME)
    set ::env(HOME) [file join $::env(HOME) foo]
} -cleanup {
    set ::env(HOME) $oldHome
} -constraints testfstildeexpand -body {
    string tolower [testfstildeexpand ~$::tcl_platform(user)]
} -match glob -result [gethomedirglob $::tcl_platform(user)]


# cleanup
cleanup
Changes to tests/fileName.test.
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# See the file "license.terms" for information on usage and redistribution of
# this file, and for a DISCLAIMER OF ALL WARRANTIES.

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


::tcltest::loadTestedCommands
catch [list package require -exact tcl::test [info patchlevel]]
source [file join [file dirname [info script]] tcltests.tcl]

testConstraint testsetplatform [llength [info commands testsetplatform]]
testConstraint testtranslatefilename [llength [info commands testtranslatefilename]]







|







10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# See the file "license.terms" for information on usage and redistribution of
# this file, and for a DISCLAIMER OF ALL WARRANTIES.

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

::tcltest::loadTestedCommands
catch [list package require -exact tcl::test [info patchlevel]]
source [file join [file dirname [info script]] tcltests.tcl]

testConstraint testsetplatform [llength [info commands testsetplatform]]
testConstraint testtranslatefilename [llength [info commands testtranslatefilename]]
1269
1270
1271
1272
1273
1274
1275




1276
1277
1278
1279
1280
1281

1282
1283
1284
1285
1286
1287
1288
} -result {}
test filename-14.22 {asterisks, question marks, and brackets} -body {
    glob goo/* x*z foo?q
} -result {}
test filename-14.23 {slash globbing} {unix} {
    glob /
} /




test filename-14.23.2 {slash globbing} {win} {
    glob /
} [file norm /]
test filename-14.24 {slash globbing} {win} {
    glob {\\}
} [file norm /]

test filename-14.25 {type specific globbing} {unix} {
    lsort [glob -dir globTest -types f *]
} [lsort [list \
	[file join $globname "weird name.c"]\
	[file join $globname x,z1.c]\
	[file join $globname x1.c]\
	[file join $globname y1.c] [file join $globname z1.c]]]







>
>
>
>


|


|
>







1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
} -result {}
test filename-14.22 {asterisks, question marks, and brackets} -body {
    glob goo/* x*z foo?q
} -result {}
test filename-14.23 {slash globbing} {unix} {
    glob /
} /

# NOTE: [The string index x/ 1] construction is a workaround for the
# testsetplatform calls above interacting with normalized path caching
# in -singleproc 1 runs. See ticket [8c63606802].
test filename-14.23.2 {slash globbing} {win} {
    glob /
} [file normalize [string index x/ 1]]
test filename-14.24 {slash globbing} {win} {
    glob {\\}
} [file normalize [string index x/ 1]]

test filename-14.25 {type specific globbing} {unix} {
    lsort [glob -dir globTest -types f *]
} [lsort [list \
	[file join $globname "weird name.c"]\
	[file join $globname x,z1.c]\
	[file join $globname x1.c]\
	[file join $globname y1.c] [file join $globname z1.c]]]
1693
1694
1695
1696
1697
1698
1699




1700
1701
1702
1703
1704
1705
1706
cd $oldpwd
catch {removeDirectory tcl[pid]}
set env(HOME) $oldhome
if {[testConstraint testsetplatform]} {
    testsetplatform $platform
    catch {unset platform}
}




catch {unset oldhome temp result globPreResult}
::tcltest::cleanupTests
return

# Local Variables:
# mode: tcl
# End:







>
>
>
>
|






1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
cd $oldpwd
catch {removeDirectory tcl[pid]}
set env(HOME) $oldhome
if {[testConstraint testsetplatform]} {
    testsetplatform $platform
    catch {unset platform}
}
unset -nocomplain {*}[lmap x [info globals] {
    if {$x in $existingGlobals} {continue}
    set x
}]

::tcltest::cleanupTests
return

# Local Variables:
# mode: tcl
# End:
Changes to tests/fileSystem.test.
330
331
332
333
334
335
336

337
338
339
340
341
342
343
    set dir [pwd]
} -constraints {win moreThanOneDrive notInCIenv} -body {
    set path "[string range [lindex $drives 0] 0 1]foo"
    cd [lindex $drives 1]
    file norm $path
} -cleanup {
    cd $dir

} -result "[lindex $drives 0]foo"
test filesystem-1.39 {file normalisation with volume relative} -setup {
    set old [pwd]
} -constraints {win} -body {
    set drv C:/
    cd [lindex [glob -type d -dir $drv *] 0]
    file norm [string range $drv 0 1]







>







330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
    set dir [pwd]
} -constraints {win moreThanOneDrive notInCIenv} -body {
    set path "[string range [lindex $drives 0] 0 1]foo"
    cd [lindex $drives 1]
    file norm $path
} -cleanup {
    cd $dir
    unset -nocomplain path
} -result "[lindex $drives 0]foo"
test filesystem-1.39 {file normalisation with volume relative} -setup {
    set old [pwd]
} -constraints {win} -body {
    set drv C:/
    cd [lindex [glob -type d -dir $drv *] 0]
    file norm [string range $drv 0 1]
Changes to tests/oo.test.
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
	foreach initial $initials {
	    lappend x [info object class $initial]
	}
	return $x
    }] {lsort [lsearch -all -not -inline $x *::delegate]}
} -cleanup {
    interp delete $fresh
} -result {{} {::oo::Slot ::oo::abstract ::oo::class ::oo::configurable ::oo::configuresupport::configurable ::oo::object ::oo::singleton} {::oo::configuresupport::objreadableproperties ::oo::configuresupport::objwritableproperties ::oo::configuresupport::readableproperties ::oo::configuresupport::writableproperties ::oo::define::filter ::oo::define::mixin ::oo::define::superclass ::oo::define::variable ::oo::objdefine::filter ::oo::objdefine::mixin ::oo::objdefine::variable} {::oo::Slot ::oo::class ::oo::configuresupport::configurable} {::oo::abstract ::oo::configurable ::oo::singleton} {} {} {} {} {} ::oo::object ::oo::object ::oo::class ::oo::class ::oo::class}
test oo-1.22 {basic test of OO functionality: nested ownership destruction order} -setup {
    oo::class create parent
} -body {
    oo::class create abc {
	superclass parent
	variable n
	constructor {} {set n 0}







|







386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
	foreach initial $initials {
	    lappend x [info object class $initial]
	}
	return $x
    }] {lsort [lsearch -all -not -inline $x *::delegate]}
} -cleanup {
    interp delete $fresh
} -result {{} {::oo::SingletonInstance ::oo::Slot ::oo::abstract ::oo::class ::oo::configurable ::oo::configuresupport::configurable ::oo::object ::oo::singleton} {::oo::configuresupport::objreadableproperties ::oo::configuresupport::objwritableproperties ::oo::configuresupport::readableproperties ::oo::configuresupport::writableproperties ::oo::define::filter ::oo::define::mixin ::oo::define::superclass ::oo::define::variable ::oo::objdefine::filter ::oo::objdefine::mixin ::oo::objdefine::variable} {::oo::SingletonInstance ::oo::Slot ::oo::class ::oo::configuresupport::configurable} {::oo::abstract ::oo::configurable ::oo::singleton} {} {} {} {} {} ::oo::object ::oo::object ::oo::class ::oo::class ::oo::class}
test oo-1.22 {basic test of OO functionality: nested ownership destruction order} -setup {
    oo::class create parent
} -body {
    oo::class create abc {
	superclass parent
	variable n
	constructor {} {set n 0}
Changes to tests/ooUtil.test.
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
	lappend ::result {*}$args
    }
    set result {}
} -body {
    trace add execution oo::define::initialise enter appendToResultVar
    oo::class create ::cls {
	superclass parent
	initialize {proc xyzzy {} {}}
    }
    return $result
} -cleanup {
    catch {
	trace remove execution oo::define::initialise enter appendToResultVar
    }
    rename ::appendToResultVar {}
    parent destroy
} -result {{initialize {proc xyzzy {} {}}} enter}
test ooUtil-3.5 {TIP 478: class initialisation} -body {
    oo::define oo::object {
	::list [::namespace which initialise] [::namespace which initialize] \
	     [::namespace origin initialise] [::namespace origin initialize]
    }
} -result {::oo::define::initialise ::oo::define::initialize ::oo::define::initialise ::oo::define::initialise}

test ooUtil-4.1 {TIP 478: singleton} -setup {
    oo::class create parent
} -body {
    oo::singleton create xyz {
	superclass parent
    }







|








|
<
<
<
<
<
<







362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378






379
380
381
382
383
384
385
	lappend ::result {*}$args
    }
    set result {}
} -body {
    trace add execution oo::define::initialise enter appendToResultVar
    oo::class create ::cls {
	superclass parent
	initialise {proc xyzzy {} {}}
    }
    return $result
} -cleanup {
    catch {
	trace remove execution oo::define::initialise enter appendToResultVar
    }
    rename ::appendToResultVar {}
    parent destroy
} -result {{initialise {proc xyzzy {} {}}} enter}







test ooUtil-4.1 {TIP 478: singleton} -setup {
    oo::class create parent
} -body {
    oo::singleton create xyz {
	superclass parent
    }
Changes to tests/platform.test.
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44

test platform-1.0 {tcl_platform(engine)} {
  set tcl_platform(engine)
} {Tcl}

test platform-1.1 {TclpSetVariables: tcl_platform} {
    interp create i
    i eval {catch {unset tcl_platform(debug)}}
    i eval {catch {unset tcl_platform(threaded)}}
    set result [i eval {lsort [array names tcl_platform]}]
    interp delete i
    set result
} {byteOrder engine machine os osVersion pathSeparator platform pointerSize user wordSize}

test platform-2.1 {tcl_platform(wordSize) indicates size of native word} testlongsize {
    expr {$tcl_platform(wordSize) == [testlongsize]}







<
<







29
30
31
32
33
34
35


36
37
38
39
40
41
42

test platform-1.0 {tcl_platform(engine)} {
  set tcl_platform(engine)
} {Tcl}

test platform-1.1 {TclpSetVariables: tcl_platform} {
    interp create i


    set result [i eval {lsort [array names tcl_platform]}]
    interp delete i
    set result
} {byteOrder engine machine os osVersion pathSeparator platform pointerSize user wordSize}

test platform-2.1 {tcl_platform(wordSize) indicates size of native word} testlongsize {
    expr {$tcl_platform(wordSize) == [testlongsize]}
68
69
70
71
72
73
74


































75
76
77
78
79
80
81
82
83
84
    # "still reachable" reports.
    platform::identify
} -result {^([^-]+-)+[^-]+$}
test platform-4.2 {format of platform::generic result} -match regexp -body {
    platform::generic
} -result {^([^-]+-)+[^-]+$}



































# cleanup
cleanupTests

}
namespace delete ::tcl::test::platform
return

# Local Variables:
# mode: tcl
# End:







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










66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
    # "still reachable" reports.
    platform::identify
} -result {^([^-]+-)+[^-]+$}
test platform-4.2 {format of platform::generic result} -match regexp -body {
    platform::generic
} -result {^([^-]+-)+[^-]+$}

test platform-5.0 {format of platform::generic result} -setup {
    set old_machine $::tcl_platform(machine)
    set old_os $::tcl_platform(os)
    set old_wordsize $::tcl_platform(wordSize)
    set old_version $tcl_platform(osVersion)
    set ::tcl_platform(machine) arm
    set ::tcl_platform(os) Darwin
    set ::tcl_platform(wordSize) 8
} -body {
    set res {}
    set l {macosx10.15-x86_64 macosx10.14-x86_64 macosx10.13-x86_64 macosx10.12-x86_64 macosx10.11-x86_64 macosx10.10-x86_64 macosx10.9-x86_64 tcl}
    foreach v {20.0 21.0 22.0 23.0 24.0 25.0 26.0} {
	set ::tcl_platform(osVersion) $v
	set id [platform::identify]
	set l [linsert $l 0 [string range $id 0 end-4]-x86_64]
	set l [linsert $l 0 $id]
	lappend res $id
	lappend res [expr {($l eq [platform::patterns $id]) ? 1 : [platform::patterns $id]}]
    }
    set res
} -cleanup {
    set ::tcl_platform(machine) $old_machine
    set ::tcl_platform(os) $old_os
    set ::tcl_platform(wordSize) $old_wordsize
    set ::tcl_platform(osVersion) $old_version
    unset res l old_machine old_os old_wordsize old_version
} -result {macos11-arm 1 macos12-arm 1 macos13-arm 1 macos14-arm 1 macos15-arm 1 macos26-arm 1 macos27-arm 1}
test platform-5.1 {format of platform::patterns macos26-x86_64} -body {
    platform::patterns macos26-x86_64
} -result {macos26-x86_64 macos15-x86_64 macos14-x86_64 macos13-x86_64 macos12-x86_64 macos11-x86_64 macosx10.15-x86_64 macosx10.14-x86_64 macosx10.13-x86_64 macosx10.12-x86_64 macosx10.11-x86_64 macosx10.10-x86_64 macosx10.9-x86_64 tcl}
test platform-5.2 {format of platform::patterns macos26-arm} -body {
    platform::patterns macos26-arm
} -result {macos26-arm macos26-x86_64 macos15-arm macos15-x86_64 macos14-arm macos14-x86_64 macos13-arm macos13-x86_64 macos12-arm macos12-x86_64 macos11-arm macos11-x86_64 macosx10.15-x86_64 macosx10.14-x86_64 macosx10.13-x86_64 macosx10.12-x86_64 macosx10.11-x86_64 macosx10.10-x86_64 macosx10.9-x86_64 tcl}

# cleanup
cleanupTests

}
namespace delete ::tcl::test::platform
return

# Local Variables:
# mode: tcl
# End:
Changes to tests/registry.test.
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
    namespace import -force ::tcltest::*
}

testConstraint reg 0
if {[testConstraint win]} {
    if {![catch {
	    ::tcltest::loadTestedCommands
	    set ::regver [package require registry 1.4a0]
	}]} {
	testConstraint reg 1
    }
}
testConstraint notWine [expr {![info exists ::env(CI_USING_WINE)]}]

# determine the current locale
testConstraint english [expr {
    [llength [info commands testlocale]]
    && [string match "English*" [testlocale all ""]]
}]

test registry-1.0 {check if we are testing the right dll} {win reg} {
    set ::regver
} {1.4a0}
test registry-1.1 {argument parsing for registry command} {win reg} {
    list [catch {registry} msg] $msg
} {1 {wrong # args: should be "registry ?-32bit|-64bit? option ?arg ...?"}}
test registry-1.1a {argument parsing for registry command} {win reg} {
    list [catch {registry -32bit} msg] $msg
} {1 {wrong # args: should be "registry ?-32bit|-64bit? option ?arg ...?"}}
test registry-1.1b {argument parsing for registry command} {win reg} {







|














|







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
    namespace import -force ::tcltest::*
}

testConstraint reg 0
if {[testConstraint win]} {
    if {![catch {
	    ::tcltest::loadTestedCommands
	    set ::regver [package require registry 1.4a1]
	}]} {
	testConstraint reg 1
    }
}
testConstraint notWine [expr {![info exists ::env(CI_USING_WINE)]}]

# determine the current locale
testConstraint english [expr {
    [llength [info commands testlocale]]
    && [string match "English*" [testlocale all ""]]
}]

test registry-1.0 {check if we are testing the right dll} {win reg} {
    set ::regver
} {1.4a1}
test registry-1.1 {argument parsing for registry command} {win reg} {
    list [catch {registry} msg] $msg
} {1 {wrong # args: should be "registry ?-32bit|-64bit? option ?arg ...?"}}
test registry-1.1a {argument parsing for registry command} {win reg} {
    list [catch {registry -32bit} msg] $msg
} {1 {wrong # args: should be "registry ?-32bit|-64bit? option ?arg ...?"}}
test registry-1.1b {argument parsing for registry command} {win reg} {
Changes to tests/tailcall.test.
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
    rename foo {}
} -result {5 0}
test tailcall-15.3 {tailcall memory leak check} -constraints memory -setup {
    proc foo {args} {llength $args}
} -body {
    list [
	apply {args {
	    tailcall foo 1 2 {*}$args 3 4 {*}$args 5 
	}} a b c
    ] [
	leaktest {
	    apply {args {
		tailcall foo 1 2 {*}$args 3 4 {*}$args 5 
	    }} a b c
	}
    ]
} -cleanup {
    rename foo {}
} -result {11 0}








|




|







761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
    rename foo {}
} -result {5 0}
test tailcall-15.3 {tailcall memory leak check} -constraints memory -setup {
    proc foo {args} {llength $args}
} -body {
    list [
	apply {args {
	    tailcall foo 1 2 {*}$args 3 4 {*}$args 5
	}} a b c
    ] [
	leaktest {
	    apply {args {
		tailcall foo 1 2 {*}$args 3 4 {*}$args 5
	    }} a b c
	}
    ]
} -cleanup {
    rename foo {}
} -result {11 0}

Changes to tests/unixInit.test.
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
    set env(LANG) japanese
    set env(LC_ALL) japanese
    set f [open "|[list [interpreter]]" w+]
    chan configure $f -buffering none
    puts $f {puts [encoding system]; exit}
    set enc [gets $f]
    close $f
    set validEncodings [list euc-jp]
    if {[string match HP-UX $tcl_platform(os)]} {
	# Some older HP-UX systems need us to accept this as valid Bug 453883
	# reports that newer HP-UX systems report euc-jp like everybody else.
	lappend validEncodings shiftjis
    }
    expr {$enc ni $validEncodings}
} -cleanup {
    unset -nocomplain env(LANG) env(LC_ALL)
    catch {set env(LC_ALL) $oldlc_all}
    catch {set env(TCL_LIBRARY) $oldtcl_library}
} -result 0

test unixInit-4.1 {TclpSetVariables} {unix} {
    # just make sure they exist
    set a [list $tcl_library $tcl_pkgPath $tcl_platform(os)]
    set a [list $tcl_platform(osVersion) $tcl_platform(machine)]
    set tcl_platform(platform)
} "unix"







|
<
<
<
<
<
<




|







119
120
121
122
123
124
125
126






127
128
129
130
131
132
133
134
135
136
137
138
    set env(LANG) japanese
    set env(LC_ALL) japanese
    set f [open "|[list [interpreter]]" w+]
    chan configure $f -buffering none
    puts $f {puts [encoding system]; exit}
    set enc [gets $f]
    close $f
    set enc






} -cleanup {
    unset -nocomplain env(LANG) env(LC_ALL)
    catch {set env(LC_ALL) $oldlc_all}
    catch {set env(TCL_LIBRARY) $oldtcl_library}
} -result {^(euc-jp|shiftjis)$} -match regexp

test unixInit-4.1 {TclpSetVariables} {unix} {
    # just make sure they exist
    set a [list $tcl_library $tcl_pkgPath $tcl_platform(os)]
    set a [list $tcl_platform(osVersion) $tcl_platform(machine)]
    set tcl_platform(platform)
} "unix"
Changes to tests/winDde.test.
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
    gets $f line
    return $f
}

# -------------------------------------------------------------------------
test winDde-1.0 {check if we are testing the right dll} {win dde} {
    set ::ddever
} {1.5a0}

test winDde-1.1 {Settings the server's topic name} -constraints dde -body {
    list [dde servername foobar] [dde servername] [dde servername self]
} -result {foobar foobar self}

test winDde-2.1 {Checking for other services} -constraints dde -body {
    expr {[llength [dde services {} {}]] >= 0}







|







101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
    gets $f line
    return $f
}

# -------------------------------------------------------------------------
test winDde-1.0 {check if we are testing the right dll} {win dde} {
    set ::ddever
} {1.5a1}

test winDde-1.1 {Settings the server's topic name} -constraints dde -body {
    list [dde servername foobar] [dde servername] [dde servername self]
} -result {foobar foobar self}

test winDde-2.1 {Checking for other services} -constraints dde -body {
    expr {[llength [dde services {} {}]] >= 0}
Changes to tools/tclOOScript.tcl.
8
9
10
11
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
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
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
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
# Copyright © 2013 Andreas Kupries
# Copyright © 2017 Gerald Lester
#
# See the file "license.terms" for information on usage and redistribution of
# this file, and for a DISCLAIMER OF ALL WARRANTIES.

::namespace eval ::oo {
    ::namespace path {}

    #
    # Commands that are made available to objects by default.
    #
    namespace eval Helpers {
	namespace path {}

	# ------------------------------------------------------------------
	#
	# callback, mymethod --
	#
	#	Create a script prefix that calls a method on the current
	#	object. Same operation, two names.
	#
	# ------------------------------------------------------------------

	proc callback {method args} {
	    list [uplevel 1 {::namespace which my}] $method {*}$args
	}

	# Make the [callback] command appear as [mymethod] too.
	namespace export callback
	namespace eval tmp {namespace import ::oo::Helpers::callback}
	namespace export -clear
	rename tmp::callback mymethod
	namespace delete tmp

	# ------------------------------------------------------------------
	#
	# classvariable --
	#
	#	Link to a variable in the class of the current object.
	#
	# ------------------------------------------------------------------

	proc classvariable {name args} {
	    # Get a reference to the class's namespace
	    set ns [info object namespace [uplevel 1 {self class}]]
	    # Double up the list of variable names
	    foreach v [list $name {*}$args] {
		if {[string match *(*) $v]} {
		    set reason "can't create a scalar variable that looks like an array element"
		    return -code error -errorcode {TCL UPVAR LOCAL_ELEMENT} \
			[format {bad variable name "%s": %s} $v $reason]
		}
		if {[string match *::* $v]} {
		    set reason "can't create a local variable with a namespace separator in it"
		    return -code error -errorcode {TCL UPVAR INVERTED} \
			[format {bad variable name "%s": %s} $v $reason]
		}
		lappend vs $v $v
	    }
	    # Lastly, link the caller's local variables to the class's variables
	    tailcall namespace upvar $ns {*}$vs
	}

	# ------------------------------------------------------------------
	#
	# link --
	#
	#	Make a command that invokes a method on the current object.
	#	The name of the command and the name of the method match by
	#	default.
	#
	# ------------------------------------------------------------------

	proc link {args} {
	    set ns [uplevel 1 {::namespace current}]
	    foreach link $args {
		if {[llength $link] == 2} {
		    lassign $link src dst
		} elseif {[llength $link] == 1} {
		    lassign $link src
		    set dst $src
		} else {
		    return -code error -errorcode {TCL OO CMDLINK_FORMAT} \
			"bad link description; must only have one or two elements"
		}
		if {![string match ::* $src]} {
		    set src [string cat $ns :: $src]
		}
		interp alias {} $src {} ${ns}::my $dst
		trace add command ${ns}::my delete [list \
		    ::oo::UnlinkLinkedCommand $src]
	    }
	    return
	}
    }

    # ----------------------------------------------------------------------
    #
    # UnlinkLinkedCommand --
    #
    #	Callback used to remove linked command when the underlying mechanism
    #	that supports it is deleted.
    #
    # ----------------------------------------------------------------------

    proc UnlinkLinkedCommand {cmd args} {
	if {[namespace which $cmd] ne {}} {
	    rename $cmd {}
	}
    }

    # ----------------------------------------------------------------------
    #
    # DelegateName --
    #
    #	Utility that gets the name of the class delegate for a class. It's
    #	trivial, but makes working with them much easier as delegate names are
    #	intentionally hard to create by accident.
    #
    # ----------------------------------------------------------------------

    proc DelegateName {class} {
	string cat [info object namespace $class] {:: oo ::delegate}
    }

    # ----------------------------------------------------------------------
    #
    # MixinClassDelegates --
    #
    #	Support code called *after* [oo::define] inside the constructor of a
    #	class that patches in the appropriate class delegates.
    #
    # ----------------------------------------------------------------------

    proc MixinClassDelegates {class} {
	if {![info object isa class $class]} {
	    return
	}
	set delegate [DelegateName $class]
	if {![info object isa class $delegate]} {
	    return
	}
	foreach c [info class superclass $class] {
	    set d [DelegateName $c]
	    if {![info object isa class $d]} {
		continue
	    }
	    define $delegate ::oo::define::superclass -appendifnew $d
	}
	objdefine $class ::oo::objdefine::mixin -appendifnew $delegate
    }

    # ----------------------------------------------------------------------
    #
    # UpdateClassDelegatesAfterClone --
    #
    #	Support code that is like [MixinClassDelegates] except for when a
    #	class is cloned.
    #
    # ----------------------------------------------------------------------

    proc UpdateClassDelegatesAfterClone {originObject targetObject} {
	# Rebuild the class inheritance delegation class
	set originDelegate [DelegateName $originObject]
	set targetDelegate [DelegateName $targetObject]
	if {
	    [info object isa class $originDelegate]
	    && ![info object isa class $targetDelegate]
	} then {
	    copy $originDelegate $targetDelegate
	    objdefine $targetObject ::oo::objdefine::mixin -set \
		{*}[lmap c [info object mixin $targetObject] {
		    if {$c eq $originDelegate} {set targetDelegate} {set c}
		}]
	}
    }

    # ----------------------------------------------------------------------
    #
    # oo::define::classmethod --
    #
    #	Defines a class method. See define(n) for details.
    #
    # Note that the ::oo::define namespace is semi-public and a bit weird
    # anyway, so we don't regard the namespace path as being under control:
    # fully qualified names are used for everything.
    #
    # ----------------------------------------------------------------------

    proc define::classmethod {name args} {
	# Create the method on the class if the caller gave arguments and body
	::set argc [::llength [::info level 0]]
	::if {$argc == 3} {
	    ::return -code error -errorcode {TCL WRONGARGS} [::format \
		{wrong # args: should be "%s name ?args body?"} \
		[::lindex [::info level 0] 0]]
	}
	::set cls [::uplevel 1 self]
	::if {$argc == 4} {
	    ::oo::define [::oo::DelegateName $cls] method $name {*}$args
	}
	# Make the connection by forwarding
	::tailcall forward $name myclass $name
    }

    # ----------------------------------------------------------------------
    #
    # oo::define::initialise, oo::define::initialize --
    #
    #	Do specific initialisation for a class. See define(n) for details.
    #
    # Note that the ::oo::define namespace is semi-public and a bit weird
    # anyway, so we don't regard the namespace path as being under control:
    # fully qualified names are used for everything.
    #
    # ----------------------------------------------------------------------

    proc define::initialise {body} {
	::set clsns [::info object namespace [::uplevel 1 self]]
	::tailcall apply [::list {} $body $clsns]
    }

    # Make the [initialise] definition appear as [initialize] too
    namespace eval define {
	::namespace export initialise
	::namespace eval tmp {::namespace import ::oo::define::initialise}
	::namespace export -clear
	::rename tmp::initialise initialize
	::namespace delete tmp
    }

    # ----------------------------------------------------------------------
    #
    # Slot --
    #
    #	The class of slot operations, which are basically lists at the low
    #	level of TclOO; this provides a more consistent interface to them.
    #
    # ----------------------------------------------------------------------

    define Slot {
	# ------------------------------------------------------------------
	#
	# Slot Get --
	#
	#	Basic slot getter. Retrieves the contents of the slot.
	#	Particular slots must provide concrete non-erroring
	#	implementation.
	#
	# ------------------------------------------------------------------

	method Get -unexport {} {
	    return -code error -errorcode {TCL OO ABSTRACT_SLOT} "unimplemented"
	}

	# ------------------------------------------------------------------
	#
	# Slot Set --
	#
	#	Basic slot setter. Sets the contents of the slot.  Particular
	#	slots must provide concrete non-erroring implementation.
	#
	# ------------------------------------------------------------------

	method Set -unexport list {
	    return -code error -errorcode {TCL OO ABSTRACT_SLOT} "unimplemented"
	}

	# ------------------------------------------------------------------
	#
	# Slot Resolve --
	#
	#	Helper that lets a slot convert a list of arguments of a
	#	particular type to their canonical forms. Defaults to doing
	#	nothing (suitable for simple strings).
	#
	# ------------------------------------------------------------------

	method Resolve -unexport list {
	    return $list
	}

	# ------------------------------------------------------------------
	#
	# Slot -set, -append, -clear, --default-operation --
	#
	#	Standard public slot operations. If a slot can't figure out
	#	what method to call directly, it uses --default-operation.
	#
	# ------------------------------------------------------------------

	method -set -export args {
	    set my [namespace which my]
	    set args [lmap a $args {uplevel 1 [list $my Resolve $a]}]
	    tailcall my Set $args
	}
	method -append -export args {
	    set my [namespace which my]
	    set args [lmap a $args {uplevel 1 [list $my Resolve $a]}]
	    set current [uplevel 1 [list $my Get]]
	    tailcall my Set [list {*}$current {*}$args]
	}
	method -appendifnew -export args {
	    set my [namespace which my]
	    set current [uplevel 1 [list $my Get]]
	    foreach a $args {
		set a [uplevel 1 [list $my Resolve $a]]
		if {$a ni $current} {
		    lappend current $a
		}
	    }
	    tailcall my Set $current
	}
	method -clear -export {} {tailcall my Set {}}
	method -prepend -export args {
	    set my [namespace which my]
	    set args [lmap a $args {uplevel 1 [list $my Resolve $a]}]
	    set current [uplevel 1 [list $my Get]]
	    tailcall my Set [list {*}$args {*}$current]
	}
	method -remove -export args {
	    set my [namespace which my]
	    set args [lmap a $args {uplevel 1 [list $my Resolve $a]}]
	    set current [uplevel 1 [list $my Get]]
	    tailcall my Set [lmap val $current {
		if {$val in $args} continue else {set val}
	    }]
	}

	# Default handling
	forward --default-operation my -append
	method unknown -unexport {args} {
	    set def --default-operation
	    if {[llength $args] == 0} {
		tailcall my $def
	    } elseif {![string match -* [lindex $args 0]]} {
		tailcall my $def {*}$args
	    }
	    next {*}$args
	}

	# Hide destroy
	unexport destroy
    }

    # Set the default operation differently for these slots
    objdefine define::superclass forward --default-operation my -set
    objdefine define::mixin forward --default-operation my -set
    objdefine objdefine::mixin forward --default-operation my -set

    # ----------------------------------------------------------------------
    #
    # oo::object <cloned> --
    #
    #	Handler for cloning objects that clones basic bits (only!) of the
    #	object's namespace. Non-procedures, traces, sub-namespaces, etc. need
    #	more complex (and class-specific) handling.







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







8
9
10
11
12
13
14
























































































































































































































































































































































15
16
17
18
19
20
21
# Copyright © 2013 Andreas Kupries
# Copyright © 2017 Gerald Lester
#
# See the file "license.terms" for information on usage and redistribution of
# this file, and for a DISCLAIMER OF ALL WARRANTIES.

::namespace eval ::oo {
























































































































































































































































































































































    # ----------------------------------------------------------------------
    #
    # oo::object <cloned> --
    #
    #	Handler for cloning objects that clones basic bits (only!) of the
    #	object's namespace. Non-procedures, traces, sub-namespaces, etc. need
    #	more complex (and class-specific) handling.
404
405
406
407
408
409
410

411
412
413











414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429

430
431
432














433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
    # oo::class <cloned> --
    #
    #	Handler for cloning classes, which fixes up the delegates.
    #
    # ----------------------------------------------------------------------

    define class method <cloned> -unexport {originObject} {

	next $originObject
	# Rebuild the class inheritance delegation class
	::oo::UpdateClassDelegatesAfterClone $originObject [self]











    }

    # ----------------------------------------------------------------------
    #
    # oo::singleton --
    #
    #	A metaclass that is used to make classes that only permit one instance
    #	of them to exist. See singleton(n).
    #
    # ----------------------------------------------------------------------

    class create singleton {
	superclass class
	variable object
	unexport create createWithNamespace
	method new args {

	    if {![info exists object] || ![info object isa object $object]} {
		set object [next {*}$args]
		::oo::objdefine $object {














		    method destroy {} {
			::return -code error -errorcode {TCL OO SINGLETON} \
			    "may not destroy a singleton object"
		    }
		    method <cloned> -unexport {originObject} {
			::return -code error -errorcode {TCL OO SINGLETON} \
			    "may not clone a singleton object"
		    }
		}
	    }
	    return $object
	}
    }

    # ----------------------------------------------------------------------
    #
    # oo::abstract --
    #
    #	A metaclass that is used to make classes that can't be directly
    #	instantiated. See abstract(n).
    #
    # ----------------------------------------------------------------------

    class create abstract {
	superclass class
	unexport create createWithNamespace new
    }

    # ----------------------------------------------------------------------
    #
    # oo::configuresupport --
    #
    #	Namespace that holds all the implementation details of TIP #558.
    #	Also includes the commands:







>


|
>
>
>
>
>
>
>
>
>
>
>











|
|
<
|
|
>
|
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
|
|
|
|
|
<
<
<
<
<











|
|
|
<







60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94

95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121





122
123
124
125
126
127
128
129
130
131
132
133
134
135

136
137
138
139
140
141
142
    # oo::class <cloned> --
    #
    #	Handler for cloning classes, which fixes up the delegates.
    #
    # ----------------------------------------------------------------------

    define class method <cloned> -unexport {originObject} {
	set targetObject [self]
	next $originObject
	# Rebuild the class inheritance delegation class
	set originDelegate [::oo::DelegateName $originObject]
	set targetDelegate [::oo::DelegateName $targetObject]
	if {
	    [info object isa class $originDelegate]
	    && ![info object isa class $targetDelegate]
	} then {
	    ::oo::copy $originDelegate $targetDelegate
	    ::oo::objdefine $targetObject mixin -set \
		{*}[lmap c [info object mixin $targetObject] {
		    if {$c eq $originDelegate} {set targetDelegate} {set c}
		}]
	}
    }

    # ----------------------------------------------------------------------
    #
    # oo::singleton --
    #
    #	A metaclass that is used to make classes that only permit one instance
    #	of them to exist. See singleton(n).
    #
    # ----------------------------------------------------------------------

    class create singleton
    define singleton superclass -set class

    define singleton unexport create createWithNamespace
    define singleton method new args {
	variable object
	if {![info exists object] || ![info object isa object $object]} {
	    set object [next {*}$args]
	    ::oo::objdefine $object mixin -prepend ::oo::SingletonInstance
	}
	return $object
    }

    # ----------------------------------------------------------------------
    #
    # oo::SingletonInstance --
    #
    #	A mixin used to make an object so it won't be destroyed or cloned (or
    #	at least not easily).
    #
    # ----------------------------------------------------------------------

    class create SingletonInstance
    define SingletonInstance method destroy {} {
	return -code error -errorcode {TCL OO SINGLETON} \
	    "may not destroy a singleton object"
    }
    define SingletonInstance method <cloned> -unexport {originObject} {
	return -code error -errorcode {TCL OO SINGLETON} \
	    "may not clone a singleton object"





    }

    # ----------------------------------------------------------------------
    #
    # oo::abstract --
    #
    #	A metaclass that is used to make classes that can't be directly
    #	instantiated. See abstract(n).
    #
    # ----------------------------------------------------------------------

    class create abstract
    define abstract superclass -set class
    define abstract unexport create createWithNamespace new


    # ----------------------------------------------------------------------
    #
    # oo::configuresupport --
    #
    #	Namespace that holds all the implementation details of TIP #558.
    #	Also includes the commands:
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
    #	These cause very fast basic implementation methods for a property
    #	following the standard model of property implementation naming.
    #	Property schemes that use other models (such as to be more Tk-like)
    #	should not use these (or the oo::cconfigurable metaclass).
    #
    # ----------------------------------------------------------------------

    namespace eval configuresupport {
	# ------------------------------------------------------------------
	#
	# oo::configuresupport::configurableclass,
	# oo::configuresupport::configurableobject --
	#
	#	Namespaces used as implementation vectors for oo::define and
	#	oo::objdefine when the class/instance is configurable.
	#	Note that these also contain commands implemented in C,
	#	especially the [property] definition command.
	#
	# ------------------------------------------------------------------

	::namespace eval configurableclass {
	    # Plural alias just in case; deliberately NOT documented!
	    ::proc properties args {::tailcall property {*}$args}
	    ::namespace path ::oo::define
	    ::namespace export property
	}

	::namespace eval configurableobject {
	    # Plural alias just in case; deliberately NOT documented!
	    ::proc properties args {::tailcall property {*}$args}
	    ::namespace path ::oo::objdefine
	    ::namespace export property
	}

	# ------------------------------------------------------------------
	#
	# oo::configuresupport::configurable --
	#
	#	The class that contains the implementation of the actual
	#	'configure' method (mixed into actually configurable classes).
	#	The 'configure' method is in tclOOBasic.c.
	#
	# ------------------------------------------------------------------

	::oo::define configurable {
	    definitionnamespace -instance configurableobject
	    definitionnamespace -class configurableclass
	}
    }

    # ----------------------------------------------------------------------
    #
    # oo::configurable --
    #
    #	A metaclass that is used to make classes that can be configured in
    #	their creation phase (and later too). All the metaclass itself does is
    #	arrange for the class created to have a 'configure' method and for
    #	oo::define and oo::objdefine (on the class and its instances) to have
    #	a property definition for setting things up for 'configure'.
    #
    # ----------------------------------------------------------------------

    class create configurable {
	superclass class

	constructor {{definitionScript ""}} {
	    next {mixin ::oo::configuresupport::configurable}
	    next $definitionScript
	}

	definitionnamespace -class configuresupport::configurableclass
    }
}

# Local Variables:
# mode: tcl
# c-basic-offset: 4
# fill-column: 78
# End:







<
|
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|

|
|
|
|
|
|

|
|
|
|
|
|
|
|
|

|
|
|
<














|
|
<
|
|
|
|

|
<







155
156
157
158
159
160
161

162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200

201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216

217
218
219
220
221
222

223
224
225
226
227
228
229
    #	These cause very fast basic implementation methods for a property
    #	following the standard model of property implementation naming.
    #	Property schemes that use other models (such as to be more Tk-like)
    #	should not use these (or the oo::cconfigurable metaclass).
    #
    # ----------------------------------------------------------------------


    # ------------------------------------------------------------------
    #
    # oo::configuresupport::configurableclass,
    # oo::configuresupport::configurableobject --
    #
    #	Namespaces used as implementation vectors for oo::define and
    #	oo::objdefine when the class/instance is configurable.
    #	Note that these also contain commands implemented in C,
    #	especially the [property] definition command.
    #
    # ------------------------------------------------------------------

    namespace eval configuresupport::configurableclass {
	# Plural alias just in case; deliberately NOT documented!
	::proc properties args {::tailcall property {*}$args}
	::namespace path ::oo::define
	::namespace export property
    }

    namespace eval configuresupport::configurableobject {
	# Plural alias just in case; deliberately NOT documented!
	::proc properties args {::tailcall property {*}$args}
	::namespace path ::oo::objdefine
	::namespace export property
    }

    # ------------------------------------------------------------------
    #
    # oo::configuresupport::configurable --
    #
    #	The class that contains the implementation of the actual
    #	'configure' method (mixed into actually configurable classes).
    #	The 'configure' method is in tclOOBasic.c.
    #
    # ------------------------------------------------------------------

    define configuresupport::configurable {
	definitionnamespace -instance configuresupport::configurableobject
	definitionnamespace -class configuresupport::configurableclass

    }

    # ----------------------------------------------------------------------
    #
    # oo::configurable --
    #
    #	A metaclass that is used to make classes that can be configured in
    #	their creation phase (and later too). All the metaclass itself does is
    #	arrange for the class created to have a 'configure' method and for
    #	oo::define and oo::objdefine (on the class and its instances) to have
    #	a property definition for setting things up for 'configure'.
    #
    # ----------------------------------------------------------------------

    class create configurable
    define configurable superclass -set class

    define configurable constructor {{definitionScript ""}} {
	::oo::define [self] {mixin -append ::oo::configuresupport::configurable}
	next $definitionScript
    }

    define configurable definitionnamespace -class configuresupport::configurableclass

}

# Local Variables:
# mode: tcl
# c-basic-offset: 4
# fill-column: 78
# End:
Changes to unix/Makefile.in.
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
# around; better to use the install-sh script that comes with the
# distribution, which is slower but guaranteed to work.

INSTALL_STRIP_PROGRAM	= strip
INSTALL_STRIP_LIBRARY	= strip -x

INSTALL			= $(SHELL) $(UNIX_DIR)/install-sh -c
INSTALL_PROGRAM		= ${INSTALL}
INSTALL_LIBRARY		= ${INSTALL}
INSTALL_DATA		= ${INSTALL} -m 644
INSTALL_DATA_DIR	= ${INSTALL} -d -m 755

# NATIVE_TCLSH is the name of a tclsh executable that is available *BEFORE*
# running make for the first time. Certain build targets (make genstubs) need
# it to be available on the PATH. This executable should *NOT* be required
# just to do a normal build although it can be required to run make dist.







|
|







150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
# around; better to use the install-sh script that comes with the
# distribution, which is slower but guaranteed to work.

INSTALL_STRIP_PROGRAM	= strip
INSTALL_STRIP_LIBRARY	= strip -x

INSTALL			= $(SHELL) $(UNIX_DIR)/install-sh -c
INSTALL_PROGRAM		= ${INSTALL} -m 755
INSTALL_LIBRARY		= ${INSTALL} -m 755
INSTALL_DATA		= ${INSTALL} -m 644
INSTALL_DATA_DIR	= ${INSTALL} -d -m 755

# NATIVE_TCLSH is the name of a tclsh executable that is available *BEFORE*
# running make for the first time. Certain build targets (make genstubs) need
# it to be available on the PATH. This executable should *NOT* be required
# just to do a normal build although it can be required to run make dist.
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
	    if [ ! -d "$$i" ] ; then \
		echo "Making directory $$i"; \
		$(INSTALL_DATA_DIR) "$$i"; \
	    fi; \
	done
	@echo "Installing $(LIB_FILE) to $(DLL_INSTALL_DIR)/"
	@@INSTALL_LIB@
	@chmod 555 "$(DLL_INSTALL_DIR)/$(LIB_FILE)"
	@echo "Installing ${TCL_EXE} as $(BIN_INSTALL_DIR)/tclsh$(VERSION)${EXE_SUFFIX}"
	@$(INSTALL_PROGRAM) ${TCL_EXE} "$(BIN_INSTALL_DIR)/tclsh$(VERSION)${EXE_SUFFIX}"
	@echo "Installing tclConfig.sh to $(CONFIG_INSTALL_DIR)/"
	@$(INSTALL_DATA) tclConfig.sh "$(CONFIG_INSTALL_DIR)/tclConfig.sh"
	@echo "Installing tclooConfig.sh to $(CONFIG_INSTALL_DIR)/"
	@$(INSTALL_DATA) $(UNIX_DIR)/tclooConfig.sh \
		"$(CONFIG_INSTALL_DIR)/tclooConfig.sh"







<







1025
1026
1027
1028
1029
1030
1031

1032
1033
1034
1035
1036
1037
1038
	    if [ ! -d "$$i" ] ; then \
		echo "Making directory $$i"; \
		$(INSTALL_DATA_DIR) "$$i"; \
	    fi; \
	done
	@echo "Installing $(LIB_FILE) to $(DLL_INSTALL_DIR)/"
	@@INSTALL_LIB@

	@echo "Installing ${TCL_EXE} as $(BIN_INSTALL_DIR)/tclsh$(VERSION)${EXE_SUFFIX}"
	@$(INSTALL_PROGRAM) ${TCL_EXE} "$(BIN_INSTALL_DIR)/tclsh$(VERSION)${EXE_SUFFIX}"
	@echo "Installing tclConfig.sh to $(CONFIG_INSTALL_DIR)/"
	@$(INSTALL_DATA) tclConfig.sh "$(CONFIG_INSTALL_DIR)/tclConfig.sh"
	@echo "Installing tclooConfig.sh to $(CONFIG_INSTALL_DIR)/"
	@$(INSTALL_DATA) $(UNIX_DIR)/tclooConfig.sh \
		"$(CONFIG_INSTALL_DIR)/tclooConfig.sh"
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
	@echo "Installing package opt0.4 files to $(SCRIPT_INSTALL_DIR)/opt0.4/"
	@for i in $(TOP_DIR)/library/opt/*.tcl; do \
	    $(INSTALL_DATA) $$i "$(SCRIPT_INSTALL_DIR)/opt0.4"; \
	done
	@echo "Installing package msgcat 1.7.1 as a Tcl Module"
	@$(INSTALL_DATA) $(TOP_DIR)/library/msgcat/msgcat.tcl \
		"$(MODULE_INSTALL_DIR)/9.0/msgcat-1.7.1.tm"
	@echo "Installing package tcltest 2.5.9 as a Tcl Module"
	@$(INSTALL_DATA) $(TOP_DIR)/library/tcltest/tcltest.tcl \
		"$(MODULE_INSTALL_DIR)/9.0/tcltest-2.5.9.tm"
	@echo "Installing package platform 1.0.19 as a Tcl Module"
	@$(INSTALL_DATA) $(TOP_DIR)/library/platform/platform.tcl \
		"$(MODULE_INSTALL_DIR)/9.0/platform-1.0.19.tm"
	@echo "Installing package platform::shell 1.1.4 as a Tcl Module"
	@$(INSTALL_DATA) $(TOP_DIR)/library/platform/shell.tcl \
		"$(MODULE_INSTALL_DIR)/9.0/platform/shell-1.1.4.tm"
	@echo "Installing encoding files to $(SCRIPT_INSTALL_DIR)/encoding/"
	@for i in $(TOP_DIR)/library/encoding/*.enc; do \
		$(INSTALL_DATA) $$i "$(SCRIPT_INSTALL_DIR)/encoding"; \
	done







|

|
|

|







1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
	@echo "Installing package opt0.4 files to $(SCRIPT_INSTALL_DIR)/opt0.4/"
	@for i in $(TOP_DIR)/library/opt/*.tcl; do \
	    $(INSTALL_DATA) $$i "$(SCRIPT_INSTALL_DIR)/opt0.4"; \
	done
	@echo "Installing package msgcat 1.7.1 as a Tcl Module"
	@$(INSTALL_DATA) $(TOP_DIR)/library/msgcat/msgcat.tcl \
		"$(MODULE_INSTALL_DIR)/9.0/msgcat-1.7.1.tm"
	@echo "Installing package tcltest 2.5.10 as a Tcl Module"
	@$(INSTALL_DATA) $(TOP_DIR)/library/tcltest/tcltest.tcl \
		"$(MODULE_INSTALL_DIR)/9.0/tcltest-2.5.10.tm"
	@echo "Installing package platform 1.1.0 as a Tcl Module"
	@$(INSTALL_DATA) $(TOP_DIR)/library/platform/platform.tcl \
		"$(MODULE_INSTALL_DIR)/9.0/platform-1.1.0.tm"
	@echo "Installing package platform::shell 1.1.4 as a Tcl Module"
	@$(INSTALL_DATA) $(TOP_DIR)/library/platform/shell.tcl \
		"$(MODULE_INSTALL_DIR)/9.0/platform/shell-1.1.4.tm"
	@echo "Installing encoding files to $(SCRIPT_INSTALL_DIR)/encoding/"
	@for i in $(TOP_DIR)/library/encoding/*.enc; do \
		$(INSTALL_DATA) $$i "$(SCRIPT_INSTALL_DIR)/encoding"; \
	done
Changes to unix/configure.
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720




TCL_VERSION=9.1
TCL_MAJOR_VERSION=9
TCL_MINOR_VERSION=1
TCL_PATCH_LEVEL="a0"
VERSION=${TCL_VERSION}

EXTRA_INSTALL_BINARIES=${EXTRA_INSTALL_BINARIES:-"@:"}
EXTRA_BUILD_HTML=${EXTRA_BUILD_HTML:-"@:"}

#------------------------------------------------------------------------
# Setup configure arguments for bundled packages







|







2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720




TCL_VERSION=9.1
TCL_MAJOR_VERSION=9
TCL_MINOR_VERSION=1
TCL_PATCH_LEVEL="a1"
VERSION=${TCL_VERSION}

EXTRA_INSTALL_BINARIES=${EXTRA_INSTALL_BINARIES:-"@:"}
EXTRA_BUILD_HTML=${EXTRA_BUILD_HTML:-"@:"}

#------------------------------------------------------------------------
# Setup configure arguments for bundled packages
Changes to unix/configure.ac.
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
    /* override */ #undef PACKAGE_STRING
    #endif /* _TCLCONFIG */])
])

TCL_VERSION=9.1
TCL_MAJOR_VERSION=9
TCL_MINOR_VERSION=1
TCL_PATCH_LEVEL="a0"
VERSION=${TCL_VERSION}

EXTRA_INSTALL_BINARIES=${EXTRA_INSTALL_BINARIES:-"@:"}
EXTRA_BUILD_HTML=${EXTRA_BUILD_HTML:-"@:"}

#------------------------------------------------------------------------
# Setup configure arguments for bundled packages







|







22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
    /* override */ #undef PACKAGE_STRING
    #endif /* _TCLCONFIG */])
])

TCL_VERSION=9.1
TCL_MAJOR_VERSION=9
TCL_MINOR_VERSION=1
TCL_PATCH_LEVEL="a1"
VERSION=${TCL_VERSION}

EXTRA_INSTALL_BINARIES=${EXTRA_INSTALL_BINARIES:-"@:"}
EXTRA_BUILD_HTML=${EXTRA_BUILD_HTML:-"@:"}

#------------------------------------------------------------------------
# Setup configure arguments for bundled packages
Changes to unix/dltest/pkgt.c.
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
DLLEXPORT int
Pkgt_Init(
    Tcl_Interp *interp)		/* Interpreter in which the package is to be
				 * made available. */
{
    int code;

    if (Tcl_InitStubs(interp, "8.7-", 0) == NULL) {
	return TCL_ERROR;
    }
    code = Tcl_PkgProvide(interp, "pkgt", "1.0");
    if (code != TCL_OK) {
	return code;
    }
    Tcl_CreateObjCommand2(interp, "pkgt_eq", Pkgt_EqObjCmd2, NULL, NULL);







|







101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
DLLEXPORT int
Pkgt_Init(
    Tcl_Interp *interp)		/* Interpreter in which the package is to be
				 * made available. */
{
    int code;

    if (Tcl_InitStubs(interp, "9.0-", 0) == NULL) {
	return TCL_ERROR;
    }
    code = Tcl_PkgProvide(interp, "pkgt", "1.0");
    if (code != TCL_OK) {
	return code;
    }
    Tcl_CreateObjCommand2(interp, "pkgt_eq", Pkgt_EqObjCmd2, NULL, NULL);
Changes to unix/tcl.spec.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# This file is the basis for a binary Tcl RPM for Linux.

%{!?directory:%define directory /usr/local}

Name:          tcl
Summary:       Tcl scripting language development environment
Version:       9.1a0
Release:       2
License:       BSD
Group:         Development/Languages
Source:        https://prdownloads.sourceforge.net/tcl/tcl%{version}-src.tar.gz
URL:           https://www.tcl-lang.org/
Buildroot:     /var/tmp/%{name}%{version}







|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
# This file is the basis for a binary Tcl RPM for Linux.

%{!?directory:%define directory /usr/local}

Name:          tcl
Summary:       Tcl scripting language development environment
Version:       9.1a1
Release:       2
License:       BSD
Group:         Development/Languages
Source:        https://prdownloads.sourceforge.net/tcl/tcl%{version}-src.tar.gz
URL:           https://www.tcl-lang.org/
Buildroot:     /var/tmp/%{name}%{version}

Changes to unix/tclAppInit.c.
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tcl.h"
#if TCL_MAJOR_VERSION < 9
#  if defined(USE_TCL_STUBS)
#	error "Don't build with USE_TCL_STUBS!"
#  endif
#  if TCL_MINOR_VERSION < 7
#   define Tcl_LibraryInitProc Tcl_PackageInitProc
#   define Tcl_StaticLibrary Tcl_StaticPackage
#  endif
#endif

#ifdef TCL_TEST
#ifdef __cplusplus
extern "C" {
#endif
extern Tcl_LibraryInitProc Tcltest_Init;







|

|
<


<







10
11
12
13
14
15
16
17
18
19

20
21

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

#include "tcl.h"
#if TCL_MAJOR_VERSION < 9
#   if defined(USE_TCL_STUBS)
#	error "Don't build with USE_TCL_STUBS!"
#   endif

#   define Tcl_LibraryInitProc Tcl_PackageInitProc
#   define Tcl_StaticLibrary Tcl_StaticPackage

#endif

#ifdef TCL_TEST
#ifdef __cplusplus
extern "C" {
#endif
extern Tcl_LibraryInitProc Tcltest_Init;
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
{
#ifdef TCL_XT_TEST
    XtToolkitInitialize();
#endif

#ifdef TCL_LOCAL_MAIN_HOOK
    TCL_LOCAL_MAIN_HOOK(&argc, &argv);
#elif (TCL_MAJOR_VERSION > 8 || TCL_MINOR_VERSION > 6) && (!defined(_WIN32) || defined(UNICODE))
    /* New in Tcl 8.7. This doesn't work on Windows without UNICODE */
    TclZipfs_AppHook(&argc, &argv);
#endif

    Tcl_Main(argc, argv, TCL_LOCAL_APPINIT);
    return 0;			/* Needed only to prevent compiler warning. */
}








|
|







86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
{
#ifdef TCL_XT_TEST
    XtToolkitInitialize();
#endif

#ifdef TCL_LOCAL_MAIN_HOOK
    TCL_LOCAL_MAIN_HOOK(&argc, &argv);
#elif TCL_MAJOR_VERSION > 8 && (!defined(_WIN32) || defined(UNICODE))
    /* New in Tcl 9.0. This doesn't work on Windows without UNICODE */
    TclZipfs_AppHook(&argc, &argv);
#endif

    Tcl_Main(argc, argv, TCL_LOCAL_APPINIT);
    return 0;			/* Needed only to prevent compiler warning. */
}

Changes to win/Makefile.in.
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
DDE_LIB_FILE		= @LIBPREFIX@tcldde$(DDEVER)${DLLSUFFIX}${LIBSUFFIX}
REG_DLL_FILE		= tcl9registry$(REGVER)${DLLSUFFIX}
REG_LIB_FILE		= @LIBPREFIX@tclregistry$(REGVER)${DLLSUFFIX}${LIBSUFFIX}
TEST_DLL_FILE		= tcltest$(VER)${DLLSUFFIX}
TEST_EXE_FILE		= tcltest${EXESUFFIX}
TEST_LIB_FILE		= @LIBPREFIX@tcltest$(VER)${DLLSUFFIX}${LIBSUFFIX}
TEST_LOAD_PRMS		= lappend ::auto_path {$(ROOT_DIR_WIN_NATIVE)/tests};\
			  package ifneeded dde 1.5a0 [list load ${DDE_DLL_FILE}];\
			  package ifneeded registry 1.4a0 [list load ${REG_DLL_FILE}]
TEST_LOAD_FACILITIES	= package ifneeded tcl::test ${VERSION}@TCL_PATCH_LEVEL@ [list load ${TEST_DLL_FILE} Tcltest];\
			  $(TEST_LOAD_PRMS)
ZLIB_DLL_FILE		= zlib1.dll
TOMMATH_DLL_FILE	= libtommath.dll

SHARED_LIBRARIES	= $(TCL_DLL_FILE) @ZLIB_DLL_FILE@ @TOMMATH_DLL_FILE@
STATIC_LIBRARIES	= $(TCL_LIB_FILE)







|
|







155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
DDE_LIB_FILE		= @LIBPREFIX@tcldde$(DDEVER)${DLLSUFFIX}${LIBSUFFIX}
REG_DLL_FILE		= tcl9registry$(REGVER)${DLLSUFFIX}
REG_LIB_FILE		= @LIBPREFIX@tclregistry$(REGVER)${DLLSUFFIX}${LIBSUFFIX}
TEST_DLL_FILE		= tcltest$(VER)${DLLSUFFIX}
TEST_EXE_FILE		= tcltest${EXESUFFIX}
TEST_LIB_FILE		= @LIBPREFIX@tcltest$(VER)${DLLSUFFIX}${LIBSUFFIX}
TEST_LOAD_PRMS		= lappend ::auto_path {$(ROOT_DIR_WIN_NATIVE)/tests};\
			  package ifneeded dde 1.5a1 [list load ${DDE_DLL_FILE}];\
			  package ifneeded registry 1.4a1 [list load ${REG_DLL_FILE}]
TEST_LOAD_FACILITIES	= package ifneeded tcl::test ${VERSION}@TCL_PATCH_LEVEL@ [list load ${TEST_DLL_FILE} Tcltest];\
			  $(TEST_LOAD_PRMS)
ZLIB_DLL_FILE		= zlib1.dll
TOMMATH_DLL_FILE	= libtommath.dll

SHARED_LIBRARIES	= $(TCL_DLL_FILE) @ZLIB_DLL_FILE@ @TOMMATH_DLL_FILE@
STATIC_LIBRARIES	= $(TCL_LIB_FILE)
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772

%.${OBJEXT}: %.c
	$(CC) -c $(CC_SWITCHES) -DBUILD_tcl @DEPARG@ $(CC_OBJNAME)

.rc.$(RES):
	$(RC) @RC_OUT@ $@ @RC_TYPE@ @RC_DEFINES@ @RC_INCLUDE@ "$(GENERIC_DIR_NATIVE)" @RC_INCLUDE@ "$(WIN_DIR_NATIVE)" @DEPARG@



#--------------------------------------------------------------------------
# Minizip implementation
#--------------------------------------------------------------------------
adler32.$(HOST_OBJEXT):
	$(HOST_CC) -o $@ -I$(ZLIB_DIR) -c $(ZLIB_DIR)/adler32.c








|







758
759
760
761
762
763
764
765
766
767
768
769
770
771
772

%.${OBJEXT}: %.c
	$(CC) -c $(CC_SWITCHES) -DBUILD_tcl @DEPARG@ $(CC_OBJNAME)

.rc.$(RES):
	$(RC) @RC_OUT@ $@ @RC_TYPE@ @RC_DEFINES@ @RC_INCLUDE@ "$(GENERIC_DIR_NATIVE)" @RC_INCLUDE@ "$(WIN_DIR_NATIVE)" @DEPARG@

tclOO.${OBJEXT}: tclOO.c tclOOScript.h

#--------------------------------------------------------------------------
# Minizip implementation
#--------------------------------------------------------------------------
adler32.$(HOST_OBJEXT):
	$(HOST_CC) -o $@ -I$(ZLIB_DIR) -c $(ZLIB_DIR)/adler32.c

929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
	@$(COPY) $(ROOT_DIR)/library/http/http.tcl "$(MODULE_INSTALL_DIR)/9.0/http-2.10.0.tm";
	@echo "Installing package opt 0.4.7";
	@for j in $(ROOT_DIR)/library/opt/*.tcl; do \
	    $(COPY) "$$j" "$(SCRIPT_INSTALL_DIR)/opt0.4"; \
	    done;
	@echo "Installing package msgcat 1.7.1 as a Tcl Module";
	@$(COPY) $(ROOT_DIR)/library/msgcat/msgcat.tcl "$(MODULE_INSTALL_DIR)/9.0/msgcat-1.7.1.tm";
	@echo "Installing package tcltest 2.5.9 as a Tcl Module";
	@$(COPY) $(ROOT_DIR)/library/tcltest/tcltest.tcl "$(MODULE_INSTALL_DIR)/9.0/tcltest-2.5.9.tm";
	@echo "Installing package platform 1.0.19 as a Tcl Module";
	@$(COPY) $(ROOT_DIR)/library/platform/platform.tcl "$(MODULE_INSTALL_DIR)/9.0/platform-1.0.19.tm";
	@echo "Installing package platform::shell 1.1.4 as a Tcl Module";
	@$(COPY) $(ROOT_DIR)/library/platform/shell.tcl "$(MODULE_INSTALL_DIR)/9.0/platform/shell-1.1.4.tm";
	@echo "Installing encodings";
	@for i in $(ROOT_DIR)/library/encoding/*.enc ; do \
		$(COPY) "$$i" "$(SCRIPT_INSTALL_DIR)/encoding"; \
	done;








|
|
|
|







929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
	@$(COPY) $(ROOT_DIR)/library/http/http.tcl "$(MODULE_INSTALL_DIR)/9.0/http-2.10.0.tm";
	@echo "Installing package opt 0.4.7";
	@for j in $(ROOT_DIR)/library/opt/*.tcl; do \
	    $(COPY) "$$j" "$(SCRIPT_INSTALL_DIR)/opt0.4"; \
	    done;
	@echo "Installing package msgcat 1.7.1 as a Tcl Module";
	@$(COPY) $(ROOT_DIR)/library/msgcat/msgcat.tcl "$(MODULE_INSTALL_DIR)/9.0/msgcat-1.7.1.tm";
	@echo "Installing package tcltest 2.5.10 as a Tcl Module";
	@$(COPY) $(ROOT_DIR)/library/tcltest/tcltest.tcl "$(MODULE_INSTALL_DIR)/9.0/tcltest-2.5.10.tm";
	@echo "Installing package platform 1.1.0 as a Tcl Module";
	@$(COPY) $(ROOT_DIR)/library/platform/platform.tcl "$(MODULE_INSTALL_DIR)/9.0/platform-1.1.0.tm";
	@echo "Installing package platform::shell 1.1.4 as a Tcl Module";
	@$(COPY) $(ROOT_DIR)/library/platform/shell.tcl "$(MODULE_INSTALL_DIR)/9.0/platform/shell-1.1.4.tm";
	@echo "Installing encodings";
	@for i in $(ROOT_DIR)/library/encoding/*.enc ; do \
		$(COPY) "$$i" "$(SCRIPT_INSTALL_DIR)/encoding"; \
	done;

Changes to win/configure.
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
# versions of autoconf incorrectly set SHELL to /bin/bash instead of
# /bin/sh. The bash shell seems to suffer from some strange failures.
SHELL=/bin/sh

TCL_VERSION=9.1
TCL_MAJOR_VERSION=9
TCL_MINOR_VERSION=1
TCL_PATCH_LEVEL="a0"
VER=$TCL_MAJOR_VERSION$TCL_MINOR_VERSION

TCL_DDE_VERSION=1.5
TCL_DDE_MAJOR_VERSION=1
TCL_DDE_MINOR_VERSION=5
DDEVER=$TCL_DDE_MAJOR_VERSION$TCL_DDE_MINOR_VERSION








|







2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
# versions of autoconf incorrectly set SHELL to /bin/bash instead of
# /bin/sh. The bash shell seems to suffer from some strange failures.
SHELL=/bin/sh

TCL_VERSION=9.1
TCL_MAJOR_VERSION=9
TCL_MINOR_VERSION=1
TCL_PATCH_LEVEL="a1"
VER=$TCL_MAJOR_VERSION$TCL_MINOR_VERSION

TCL_DDE_VERSION=1.5
TCL_DDE_MAJOR_VERSION=1
TCL_DDE_MINOR_VERSION=5
DDEVER=$TCL_DDE_MAJOR_VERSION$TCL_DDE_MINOR_VERSION

Changes to win/configure.ac.
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# versions of autoconf incorrectly set SHELL to /bin/bash instead of
# /bin/sh. The bash shell seems to suffer from some strange failures.
SHELL=/bin/sh

TCL_VERSION=9.1
TCL_MAJOR_VERSION=9
TCL_MINOR_VERSION=1
TCL_PATCH_LEVEL="a0"
VER=$TCL_MAJOR_VERSION$TCL_MINOR_VERSION

TCL_DDE_VERSION=1.5
TCL_DDE_MAJOR_VERSION=1
TCL_DDE_MINOR_VERSION=5
DDEVER=$TCL_DDE_MAJOR_VERSION$TCL_DDE_MINOR_VERSION








|







11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# versions of autoconf incorrectly set SHELL to /bin/bash instead of
# /bin/sh. The bash shell seems to suffer from some strange failures.
SHELL=/bin/sh

TCL_VERSION=9.1
TCL_MAJOR_VERSION=9
TCL_MINOR_VERSION=1
TCL_PATCH_LEVEL="a1"
VER=$TCL_MAJOR_VERSION$TCL_MINOR_VERSION

TCL_DDE_VERSION=1.5
TCL_DDE_MAJOR_VERSION=1
TCL_DDE_MINOR_VERSION=5
DDEVER=$TCL_DDE_MAJOR_VERSION$TCL_DDE_MINOR_VERSION

Changes to win/makefile.vc.
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
TCLSHRAW=$(TCLSH:.exe=-raw.exe)
TCLLIBRAW=$(TCLLIB:.dll=-raw.dll)

# Tcl version info based on macros set up by rules.vc
DOTVERSION      = $(TCL_MAJOR_VERSION).$(TCL_MINOR_VERSION)
VERSION         = $(TCL_MAJOR_VERSION)$(TCL_MINOR_VERSION)

# The staticpkg option is not longer supported in Tcl 8.7
# though extensions may still be using it. If specified together
# with "static", ignore it as that is now the default for
# static build. For non-static builds, no longer supported
# now (was permitted in 8.6)
!if $(TCL_USE_STATIC_PACKAGES)
!if $(STATIC_BUILD)
!message *** NOTE: The "staticpkg" option redundant in 8.7.
!else
!message *** NOTE: The "staticpkg" option ignored for shared library builds.
!endif
!endif

!if [nmakehlp -f $(OPTS) "noembed"]
!message *** Option noembed specified. Tcl script library will not be appended to the binary.







|






|







148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
TCLSHRAW=$(TCLSH:.exe=-raw.exe)
TCLLIBRAW=$(TCLLIB:.dll=-raw.dll)

# Tcl version info based on macros set up by rules.vc
DOTVERSION      = $(TCL_MAJOR_VERSION).$(TCL_MINOR_VERSION)
VERSION         = $(TCL_MAJOR_VERSION)$(TCL_MINOR_VERSION)

# The staticpkg option is not longer supported in Tcl 9.0
# though extensions may still be using it. If specified together
# with "static", ignore it as that is now the default for
# static build. For non-static builds, no longer supported
# now (was permitted in 8.6)
!if $(TCL_USE_STATIC_PACKAGES)
!if $(STATIC_BUILD)
!message *** NOTE: The "staticpkg" option redundant in 9.0.
!else
!message *** NOTE: The "staticpkg" option ignored for shared library builds.
!endif
!endif

!if [nmakehlp -f $(OPTS) "noembed"]
!message *** Option noembed specified. Tcl script library will not be appended to the binary.
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
!endif
setup:      default-setup

test: test-core test-pkgs
test-core: tcltest
	set TCL_LIBRARY=$(TCL_TEST_LIBRARY)
	$(DEBUGGER) $(TCLTEST) "$(ROOT:\=/)/tests/all.tcl" $(TESTFLAGS) -loadfile <<
		package ifneeded dde 1.5a0 [list load "$(TCLDDELIB:\=/)"]
		package ifneeded registry 1.4a0 [list load "$(TCLREGLIB:\=/)"]
<<

runtest: setup $(TCLTEST) dlls
	set TCL_LIBRARY=$(TCL_TEST_LIBRARY)
	$(DEBUGGER) $(TCLTEST) $(SCRIPT)

runshell: setup core shell dlls







|
|







553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
!endif
setup:      default-setup

test: test-core test-pkgs
test-core: tcltest
	set TCL_LIBRARY=$(TCL_TEST_LIBRARY)
	$(DEBUGGER) $(TCLTEST) "$(ROOT:\=/)/tests/all.tcl" $(TESTFLAGS) -loadfile <<
		package ifneeded dde 1.5a1 [list load "$(TCLDDELIB:\=/)"]
		package ifneeded registry 1.4a1 [list load "$(TCLREGLIB:\=/)"]
<<

runtest: setup $(TCLTEST) dlls
	set TCL_LIBRARY=$(TCL_TEST_LIBRARY)
	$(DEBUGGER) $(TCLTEST) $(SCRIPT)

runshell: setup core shell dlls
Changes to win/rules.vc.
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
# DEBUG - 1 -> debug build, 0 -> release builds
# SYMBOLS - 1 -> generate PDB's, 0 -> no PDB's
# PROFILE - 1 -> generate profiling info, 0 -> no profiling
# PGO     - 1 -> profile based optimization, 0 -> no
# MSVCRT  - 1 -> link to dynamic C runtime even when building static Tcl build
#           0 -> link to static C runtime for static Tcl build.
#           Does not impact shared Tcl builds (STATIC_BUILD == 0)
#           Default: 1 for Tcl 8.7 and up, 0 otherwise.
# TCL_USE_STATIC_PACKAGES - 1 -> statically link the registry and dde extensions
#           in the Tcl and Wish shell. 0 -> keep them as shared libraries. Does
#           not impact shared Tcl builds. Implied by STATIC_BUILD since Tcl 8.7.
# USE_THREAD_ALLOC - 1 -> Use a shared global free pool for allocation.
#           0 -> Use the non-thread allocator.
# UNCHECKED - 1 -> when doing a debug build with symbols, use the release
#           C runtime, 0 -> use the debug C runtime.
# USE_STUBS - 1 -> compile to use stubs interfaces, 0 -> direct linking
# CONFIG_CHECK - 1 -> check current build configuration against Tcl
#           configuration (ignored for Tcl itself)







|


|







800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
# DEBUG - 1 -> debug build, 0 -> release builds
# SYMBOLS - 1 -> generate PDB's, 0 -> no PDB's
# PROFILE - 1 -> generate profiling info, 0 -> no profiling
# PGO     - 1 -> profile based optimization, 0 -> no
# MSVCRT  - 1 -> link to dynamic C runtime even when building static Tcl build
#           0 -> link to static C runtime for static Tcl build.
#           Does not impact shared Tcl builds (STATIC_BUILD == 0)
#           Default: 1 for Tcl 9.0 and up, 0 otherwise.
# TCL_USE_STATIC_PACKAGES - 1 -> statically link the registry and dde extensions
#           in the Tcl and Wish shell. 0 -> keep them as shared libraries. Does
#           not impact shared Tcl builds. Implied by STATIC_BUILD since Tcl 9.0.
# USE_THREAD_ALLOC - 1 -> Use a shared global free pool for allocation.
#           0 -> Use the non-thread allocator.
# UNCHECKED - 1 -> when doing a debug build with symbols, use the release
#           C runtime, 0 -> use the debug C runtime.
# USE_STUBS - 1 -> compile to use stubs interfaces, 0 -> direct linking
# CONFIG_CHECK - 1 -> check current build configuration against Tcl
#           configuration (ignored for Tcl itself)
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
################################################################
# 10. Construct output directory and file paths
# Figure-out how to name our intermediate and output directories.
# In order to avoid inadvertent mixing of object files built using
# different compilers, build configurations etc.,
#
# Naming convention (suffixes):
#   t = full thread support. (Not used for Tcl >= 8.7)
#   s = static library (as opposed to an import library)
#   g = linked to the debug enabled C run-time.
#   x = special static build when it links to the dynamic C run-time.
#
# The following macros are set in this section:
# SUFX - the suffix to use for binaries based on above naming convention
# BUILDDIRTOP - the toplevel default output directory







|







1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
################################################################
# 10. Construct output directory and file paths
# Figure-out how to name our intermediate and output directories.
# In order to avoid inadvertent mixing of object files built using
# different compilers, build configurations etc.,
#
# Naming convention (suffixes):
#   t = full thread support. (Not used for Tcl >= 9.0)
#   s = static library (as opposed to an import library)
#   g = linked to the debug enabled C run-time.
#   x = special static build when it links to the dynamic C run-time.
#
# The following macros are set in this section:
# SUFX - the suffix to use for binaries based on above naming convention
# BUILDDIRTOP - the toplevel default output directory
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
!if $(TCL_MAJOR_VERSION) == 8
TCLSTUBLIB	= $(_TCLDIR)\lib\tclstub$(TCL_VERSION).lib
!else
TCLSTUBLIB	= $(_TCLDIR)\lib\tclstub.lib
!endif
TCLIMPLIB	= $(_TCLDIR)\lib\tcl$(TCL_VERSION)$(SUFX:t=).lib
# When building extensions, may be linking against Tcl that does not add
# "t" suffix (e.g. 8.5 or 8.7). If lib not found check for that possibility.
!if !exist("$(TCLIMPLIB)")
TCLIMPLIB	= $(_TCLDIR)\lib\tcl$(TCL_VERSION)t$(SUFX:t=).lib
!endif
TCL_LIBRARY	= $(_TCLDIR)\lib
TCLREGLIB	= $(_TCLDIR)\lib\tclreg13$(SUFX:t=).lib
TCLDDELIB	= $(_TCLDIR)\lib\tcldde14$(SUFX:t=).lib
TCLSCRIPTZIP	= $(_TCLDIR)\lib\$(TCL_ZIP_FILE)







|







1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
!if $(TCL_MAJOR_VERSION) == 8
TCLSTUBLIB	= $(_TCLDIR)\lib\tclstub$(TCL_VERSION).lib
!else
TCLSTUBLIB	= $(_TCLDIR)\lib\tclstub.lib
!endif
TCLIMPLIB	= $(_TCLDIR)\lib\tcl$(TCL_VERSION)$(SUFX:t=).lib
# When building extensions, may be linking against Tcl that does not add
# "t" suffix (e.g. 8.6). If lib not found check for that possibility.
!if !exist("$(TCLIMPLIB)")
TCLIMPLIB	= $(_TCLDIR)\lib\tcl$(TCL_VERSION)t$(SUFX:t=).lib
!endif
TCL_LIBRARY	= $(_TCLDIR)\lib
TCLREGLIB	= $(_TCLDIR)\lib\tclreg13$(SUFX:t=).lib
TCLDDELIB	= $(_TCLDIR)\lib\tcldde14$(SUFX:t=).lib
TCLSCRIPTZIP	= $(_TCLDIR)\lib\$(TCL_ZIP_FILE)
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
!if $(TCL_MAJOR_VERSION) == 8
TCLSTUBLIB	= $(_TCLDIR)\win\$(BUILDDIRTOP)\tclstub$(TCL_VERSION).lib
!else
TCLSTUBLIB	= $(_TCLDIR)\win\$(BUILDDIRTOP)\tclstub.lib
!endif
TCLIMPLIB	= $(_TCLDIR)\win\$(BUILDDIRTOP)\tcl$(TCL_VERSION)$(SUFX:t=).lib
# When building extensions, may be linking against Tcl that does not add
# "t" suffix (e.g. 8.5 or 8.7). If lib not found check for that possibility.
!if !exist("$(TCLIMPLIB)")
TCLIMPLIB	= $(_TCLDIR)\win\$(BUILDDIRTOP)\tcl$(TCL_VERSION)t$(SUFX:t=).lib
!endif
TCL_LIBRARY	= $(_TCLDIR)\library
TCLREGLIB	= $(_TCLDIR)\win\$(BUILDDIRTOP)\tclreg13$(SUFX:t=).lib
TCLDDELIB	= $(_TCLDIR)\win\$(BUILDDIRTOP)\tcldde14$(SUFX:t=).lib
TCLSCRIPTZIP	= $(_TCLDIR)\win\$(BUILDDIRTOP)\$(TCL_ZIP_FILE)







|







1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
!if $(TCL_MAJOR_VERSION) == 8
TCLSTUBLIB	= $(_TCLDIR)\win\$(BUILDDIRTOP)\tclstub$(TCL_VERSION).lib
!else
TCLSTUBLIB	= $(_TCLDIR)\win\$(BUILDDIRTOP)\tclstub.lib
!endif
TCLIMPLIB	= $(_TCLDIR)\win\$(BUILDDIRTOP)\tcl$(TCL_VERSION)$(SUFX:t=).lib
# When building extensions, may be linking against Tcl that does not add
# "t" suffix (e.g. 8.6). If lib not found check for that possibility.
!if !exist("$(TCLIMPLIB)")
TCLIMPLIB	= $(_TCLDIR)\win\$(BUILDDIRTOP)\tcl$(TCL_VERSION)t$(SUFX:t=).lib
!endif
TCL_LIBRARY	= $(_TCLDIR)\library
TCLREGLIB	= $(_TCLDIR)\win\$(BUILDDIRTOP)\tclreg13$(SUFX:t=).lib
TCLDDELIB	= $(_TCLDIR)\win\$(BUILDDIRTOP)\tcldde14$(SUFX:t=).lib
TCLSCRIPTZIP	= $(_TCLDIR)\win\$(BUILDDIRTOP)\$(TCL_ZIP_FILE)
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
!else # effectively NEED_TK

!if $(TKINSTALL) # Building against installed Tk
WISH		= $(_TKDIR)\bin\$(WISHNAME)
TKSTUBLIB	= $(_TKDIR)\lib\$(TKSTUBLIBNAME)
TKIMPLIB	= $(_TKDIR)\lib\$(TKIMPLIBNAME)
# When building extensions, may be linking against Tk that does not add
# "t" suffix (e.g. 8.5 or 8.7). If lib not found check for that possibility.
!if !exist("$(TKIMPLIB)")
TKIMPLIBNAME	= tk$(TK_VERSION)$(SUFX:t=).lib
TKIMPLIB	= $(_TKDIR)\lib\$(TKIMPLIBNAME)
!endif
TK_INCLUDES     = -I"$(_TKDIR)\include"
TKSCRIPTZIP     = $(_TKDIR)\lib\$(TK_ZIP_FILE)

!else # Building against Tk sources

WISH		= $(_TKDIR)\win\$(BUILDDIRTOP)\$(WISHNAME)
TKSTUBLIB	= $(_TKDIR)\win\$(BUILDDIRTOP)\$(TKSTUBLIBNAME)
TKIMPLIB	= $(_TKDIR)\win\$(BUILDDIRTOP)\$(TKIMPLIBNAME)
# When building extensions, may be linking against Tk that does not add
# "t" suffix (e.g. 8.5 or 8.7). If lib not found check for that possibility.
!if !exist("$(TKIMPLIB)")
TKIMPLIBNAME	= tk$(TK_VERSION)$(SUFX:t=).lib
TKIMPLIB	= $(_TKDIR)\win\$(BUILDDIRTOP)\$(TKIMPLIBNAME)
!endif
TK_INCLUDES     = -I"$(_TKDIR)\generic" -I"$(_TKDIR)\win" -I"$(_TKDIR)\xlib"
TKSCRIPTZIP     = $(_TKDIR)\win\$(BUILDDIRTOP)\$(TK_ZIP_FILE)








|













|







1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
!else # effectively NEED_TK

!if $(TKINSTALL) # Building against installed Tk
WISH		= $(_TKDIR)\bin\$(WISHNAME)
TKSTUBLIB	= $(_TKDIR)\lib\$(TKSTUBLIBNAME)
TKIMPLIB	= $(_TKDIR)\lib\$(TKIMPLIBNAME)
# When building extensions, may be linking against Tk that does not add
# "t" suffix (e.g. 8.6). If lib not found check for that possibility.
!if !exist("$(TKIMPLIB)")
TKIMPLIBNAME	= tk$(TK_VERSION)$(SUFX:t=).lib
TKIMPLIB	= $(_TKDIR)\lib\$(TKIMPLIBNAME)
!endif
TK_INCLUDES     = -I"$(_TKDIR)\include"
TKSCRIPTZIP     = $(_TKDIR)\lib\$(TK_ZIP_FILE)

!else # Building against Tk sources

WISH		= $(_TKDIR)\win\$(BUILDDIRTOP)\$(WISHNAME)
TKSTUBLIB	= $(_TKDIR)\win\$(BUILDDIRTOP)\$(TKSTUBLIBNAME)
TKIMPLIB	= $(_TKDIR)\win\$(BUILDDIRTOP)\$(TKIMPLIBNAME)
# When building extensions, may be linking against Tk that does not add
# "t" suffix (e.g. 8.6). If lib not found check for that possibility.
!if !exist("$(TKIMPLIB)")
TKIMPLIBNAME	= tk$(TK_VERSION)$(SUFX:t=).lib
TKIMPLIB	= $(_TKDIR)\win\$(BUILDDIRTOP)\$(TKIMPLIBNAME)
!endif
TK_INCLUDES     = -I"$(_TKDIR)\generic" -I"$(_TKDIR)\win" -I"$(_TKDIR)\xlib"
TKSCRIPTZIP     = $(_TKDIR)\win\$(BUILDDIRTOP)\$(TK_ZIP_FILE)

Changes to win/tclAppInit.c.
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 */

#include "tcl.h"
#if TCL_MAJOR_VERSION < 9
#  if defined(USE_TCL_STUBS)
#	error "Don't build with USE_TCL_STUBS!"
#  endif
#  if TCL_MINOR_VERSION < 7
#   define Tcl_LibraryInitProc Tcl_PackageInitProc
#   define Tcl_StaticLibrary Tcl_StaticPackage
#  endif
#endif

#ifdef TCL_TEST
#ifdef __cplusplus
extern "C" {
#endif
extern Tcl_LibraryInitProc Tcltest_Init;







|

|
<


<







12
13
14
15
16
17
18
19
20
21

22
23

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

#include "tcl.h"
#if TCL_MAJOR_VERSION < 9
#   if defined(USE_TCL_STUBS)
#	error "Don't build with USE_TCL_STUBS!"
#   endif

#   define Tcl_LibraryInitProc Tcl_PackageInitProc
#   define Tcl_StaticLibrary Tcl_StaticPackage

#endif

#ifdef TCL_TEST
#ifdef __cplusplus
extern "C" {
#endif
extern Tcl_LibraryInitProc Tcltest_Init;
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
	if (*p == '\\') {
	    *p = '/';
	}
    }

#ifdef TCL_LOCAL_MAIN_HOOK
    TCL_LOCAL_MAIN_HOOK(&argc, &argv);
#elif (TCL_MAJOR_VERSION > 8 || TCL_MINOR_VERSION > 6) && (!defined(_WIN32) || defined(UNICODE))
    /* New in Tcl 8.7. This doesn't work on Windows without UNICODE */
    TclZipfs_AppHook(&argc, &argv);
#endif

    Tcl_Main(argc, argv, TCL_LOCAL_APPINIT);
    return 0;			/* Needed only to prevent compiler warning. */
}








|
|







136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
	if (*p == '\\') {
	    *p = '/';
	}
    }

#ifdef TCL_LOCAL_MAIN_HOOK
    TCL_LOCAL_MAIN_HOOK(&argc, &argv);
#elif TCL_MAJOR_VERSION > 8 && (!defined(_WIN32) || defined(UNICODE))
    /* New in Tcl 9.0. This doesn't work on Windows without UNICODE */
    TclZipfs_AppHook(&argc, &argv);
#endif

    Tcl_Main(argc, argv, TCL_LOCAL_APPINIT);
    return 0;			/* Needed only to prevent compiler warning. */
}

Changes to win/tclWinDde.c.
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
 */

static HSZ ddeServiceGlobal = 0;
static DWORD ddeInstance;	/* The application instance handle given to us
				 * by DdeInitialize. */
static int ddeIsServer = 0;

#define TCL_DDE_VERSION		"1.5a0"
#define TCL_DDE_PACKAGE_NAME	"dde"
#define TCL_DDE_SERVICE_NAME	L"TclEval"
#define TCL_DDE_EXECUTE_RESULT	L"$TCLEVAL$EXECUTE$RESULT"

enum TclDdeFlags {
    DDE_FLAG_ASYNC = 1,
    DDE_FLAG_BINARY = 2,







|







75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
 */

static HSZ ddeServiceGlobal = 0;
static DWORD ddeInstance;	/* The application instance handle given to us
				 * by DdeInitialize. */
static int ddeIsServer = 0;

#define TCL_DDE_VERSION		"1.5a1"
#define TCL_DDE_PACKAGE_NAME	"dde"
#define TCL_DDE_SERVICE_NAME	L"TclEval"
#define TCL_DDE_EXECUTE_RESULT	L"$TCLEVAL$EXECUTE$RESULT"

enum TclDdeFlags {
    DDE_FLAG_ASYNC = 1,
    DDE_FLAG_BINARY = 2,
Changes to win/tclWinReg.c.
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
    if (Tcl_InitStubs(interp, "9.0-", 0) == NULL) {
	return TCL_ERROR;
    }

    cmd = Tcl_CreateObjCommand2(interp, "registry", RegistryObjCmd,
	    interp, DeleteCmd);
    Tcl_SetAssocData(interp, REGISTRY_ASSOC_KEY, NULL, cmd);
    return Tcl_PkgProvideEx(interp, "registry", "1.4a0", NULL);
}

/*
 *----------------------------------------------------------------------
 *
 * Registry_Unload --
 *







|







159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
    if (Tcl_InitStubs(interp, "9.0-", 0) == NULL) {
	return TCL_ERROR;
    }

    cmd = Tcl_CreateObjCommand2(interp, "registry", RegistryObjCmd,
	    interp, DeleteCmd);
    Tcl_SetAssocData(interp, REGISTRY_ASSOC_KEY, NULL, cmd);
    return Tcl_PkgProvideEx(interp, "registry", "1.4a1", NULL);
}

/*
 *----------------------------------------------------------------------
 *
 * Registry_Unload --
 *